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
SendConnectionAck()24 void GatordMockService::SendConnectionAck()
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
SendRequestCounterDir()34 void GatordMockService::SendRequestCounterDir()
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
SendActivateTimelinePacket()44 void GatordMockService::SendActivateTimelinePacket()
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
SendDeactivateTimelinePacket()54 void GatordMockService::SendDeactivateTimelinePacket()
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
LaunchReceivingThread()64 bool GatordMockService::LaunchReceivingThread()
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
WaitForReceivingThread()81 void GatordMockService::WaitForReceivingThread()
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
WaitForStreamMetaData()101 bool GatordMockService::WaitForStreamMetaData()
102 {
103 return m_BasePipeServer->WaitForStreamMetaData();
104 }
105
SendPeriodicCounterSelectionList(uint32_t period,std::vector<uint16_t> counters)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
WaitCommand(uint32_t timeout)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
ReceiveLoop()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
201