ArmNN
 20.11
GatordMockService.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2019 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #include "GatordMockService.hpp"
7 
8 #include <common/include/Assert.hpp>
9 #include <common/include/CommandHandlerRegistry.hpp>
10 #include <common/include/CommonProfilingUtils.hpp>
11 #include <common/include/PacketVersionResolver.hpp>
12 #include <common/include/NetworkSockets.hpp>
13 
14 #include <cerrno>
15 #include <iostream>
16 #include <string>
17 
18 namespace armnn
19 {
20 
21 namespace gatordmock
22 {
23 
25 {
26  if (m_EchoPackets)
27  {
28  std::cout << "Sending connection acknowledgement." << std::endl;
29  }
30  // The connection ack packet is an empty data packet with packetId == 1.
31  m_BasePipeServer.get()->SendPacket(0, 1, nullptr, 0);
32 }
33 
35 {
36  if (m_EchoPackets)
37  {
38  std::cout << "Sending connection acknowledgement." << std::endl;
39  }
40  // The request counter directory packet is an empty data packet with packetId == 3.
41  m_BasePipeServer.get()->SendPacket(0, 3, nullptr, 0);
42 }
43 
45 {
46  if (m_EchoPackets)
47  {
48  std::cout << "Sending activate timeline packet." << std::endl;
49  }
50  // The activate timeline packet is an empty data packet with packetId == 6.
51  m_BasePipeServer.get()->SendPacket(0, 6, nullptr, 0);
52 }
53 
55 {
56  if (m_EchoPackets)
57  {
58  std::cout << "Sending deactivate timeline packet." << std::endl;
59  }
60  // The deactivate timeline packet is an empty data packet with packetId == 7.
61  m_BasePipeServer.get()->SendPacket(0, 7, nullptr, 0);
62 }
63 
65 {
66  if (m_EchoPackets)
67  {
68  std::cout << "Launching receiving thread." << std::endl;
69  }
70  // At this point we want to make the socket non blocking.
71  if (!m_BasePipeServer.get()->SetNonBlocking())
72  {
73  m_BasePipeServer.get()->Close();
74  std::cerr << "Failed to set socket as non blocking: " << strerror(errno) << std::endl;
75  return false;
76  }
77  m_ListeningThread = std::thread(&GatordMockService::ReceiveLoop, this);
78  return true;
79 }
80 
82 {
83  // The receiving thread may already have died.
84  if (m_CloseReceivingThread != true)
85  {
86  m_CloseReceivingThread.store(true);
87  }
88  // Check that the receiving thread is running
89  if (m_ListeningThread.joinable())
90  {
91  // Wait for the receiving thread to complete operations
92  m_ListeningThread.join();
93  }
94 
95  if(m_EchoPackets)
96  {
97  m_TimelineDecoder.print();
98  }
99 }
100 
102 {
103  return m_BasePipeServer->WaitForStreamMetaData();
104 }
105 
106 void GatordMockService::SendPeriodicCounterSelectionList(uint32_t period, std::vector<uint16_t> counters)
107 {
108  // The packet body consists of a UINT32 representing the period following by zero or more
109  // UINT16's representing counter UID's. If the list is empty it implies all counters are to
110  // be disabled.
111 
112  if (m_EchoPackets)
113  {
114  std::cout << "SendPeriodicCounterSelectionList: Period=" << std::dec << period << "uSec" << std::endl;
115  std::cout << "List length=" << counters.size() << std::endl;
116  }
117  // Start by calculating the length of the packet body in bytes. This will be at least 4.
118  uint32_t dataLength = static_cast<uint32_t>(4 + (counters.size() * 2));
119 
120  std::unique_ptr<unsigned char[]> uniqueData = std::make_unique<unsigned char[]>(dataLength);
121  unsigned char* data = reinterpret_cast<unsigned char*>(uniqueData.get());
122 
123  uint32_t offset = 0;
124  arm::pipe::WriteUint32(data, offset, period);
125  offset += 4;
126  for (std::vector<uint16_t>::iterator it = counters.begin(); it != counters.end(); ++it)
127  {
128  arm::pipe::WriteUint16(data, offset, *it);
129  offset += 2;
130  }
131 
132  // Send the packet.
133  m_BasePipeServer.get()->SendPacket(0, 4, data, dataLength);
134  // There will be an echo response packet sitting in the receive thread. PeriodicCounterSelectionResponseHandler
135  // should deal with it.
136 }
137 
138 void GatordMockService::WaitCommand(uint32_t timeout)
139 {
140  // Wait for a maximum of timeout microseconds or if the receive thread has closed.
141  // There is a certain level of rounding involved in this timing.
142  uint32_t iterations = timeout / 1000;
143  std::cout << std::dec << "Wait command with timeout of " << timeout << " iterations = " << iterations << std::endl;
144  uint32_t count = 0;
145  while ((this->ReceiveThreadRunning() && (count < iterations)))
146  {
147  std::this_thread::sleep_for(std::chrono::microseconds(1000));
148  ++count;
149  }
150  if (m_EchoPackets)
151  {
152  std::cout << std::dec << "Wait command with timeout of " << timeout << " microseconds completed. " << std::endl;
153  }
154 }
155 
156 void GatordMockService::ReceiveLoop()
157 {
158  m_CloseReceivingThread.store(false);
159  while (!m_CloseReceivingThread.load())
160  {
161  try
162  {
163  arm::pipe::Packet packet = m_BasePipeServer.get()->WaitForPacket(500);
164 
165  arm::pipe::PacketVersionResolver packetVersionResolver;
166 
167  arm::pipe::Version version =
168  packetVersionResolver.ResolvePacketVersion(packet.GetPacketFamily(), packet.GetPacketId());
169 
170  arm::pipe::CommandHandlerFunctor* commandHandlerFunctor = m_HandlerRegistry.GetFunctor(
171  packet.GetPacketFamily(),
172  packet.GetPacketId(),
173  version.GetEncodedValue());
174 
175 
176 
177  ARM_PIPE_ASSERT(commandHandlerFunctor);
178  commandHandlerFunctor->operator()(packet);
179  }
180  catch (const arm::pipe::TimeoutException&)
181  {
182  // In this case we ignore timeouts and and keep trying to receive.
183  }
184  catch (const arm::pipe::InvalidArgumentException& e)
185  {
186  // We couldn't find a functor to handle the packet?
187  std::cerr << "Packet received that could not be processed: " << e.what() << std::endl;
188  }
189  catch (const arm::pipe::ProfilingException& e)
190  {
191  // A runtime exception occurred which means we must exit the loop.
192  std::cerr << "Receive thread closing: " << e.what() << std::endl;
193  m_CloseReceivingThread.store(true);
194  }
195  }
196 }
197 
198 } // namespace gatordmock
199 
200 } // namespace armnn
void WriteUint16(const IPacketBufferPtr &packetBuffer, unsigned int offset, uint16_t value)
void WriteUint32(const IPacketBufferPtr &packetBuffer, unsigned int offset, uint32_t value)
Copyright (c) 2020 ARM Limited.
void SendDeactivateTimelinePacket()
Send a deactivate timeline packet back to the client.
void SendActivateTimelinePacket()
Send a activate timeline packet back to the client.
bool WaitForStreamMetaData()
Once the connection is open wait to receive the stream meta data packet from the client.
void SendRequestCounterDir()
Send a request counter directory packet back to the client.
bool LaunchReceivingThread()
Start the thread that will receive all packets and print them nicely to stdout.
void WaitCommand(uint32_t timeout)
Execute the WAIT command from the comamnd file.
void SendPeriodicCounterSelectionList(uint32_t period, std::vector< uint16_t > counters)
Send the counter list to ArmNN.
void WaitForReceivingThread()
This is a placeholder method to prevent main exiting.
void SendConnectionAck()
Send a connection acknowledged packet back to the client.