blob: 13f688225be7dcb94cf66f4ff4cdb9b08ccb3480 [file] [log] [blame]
Colm Donelana21620d2019-10-11 13:09:49 +01001//
2// Copyright © 2019 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
Matteo Martincigh65984272019-10-17 13:26:21 +01005
Colm Donelana21620d2019-10-11 13:09:49 +01006#include "GatordMockService.hpp"
7
Matteo Martincigh65984272019-10-17 13:26:21 +01008#include <CommandHandlerRegistry.hpp>
Keith Davis3201eea2019-10-24 17:30:41 +01009#include <PacketVersionResolver.hpp>
10#include <ProfilingUtils.hpp>
Rob Hughes25b74362020-01-13 11:14:59 +000011#include <NetworkSockets.hpp>
Colm Donelana21620d2019-10-11 13:09:49 +010012
Narumol Prangnawarat627cbb42020-04-07 12:25:05 +010013#include <armnn/utility/Assert.hpp>
14
Colm Donelana21620d2019-10-11 13:09:49 +010015#include <cerrno>
Colm Donelanb682d842019-10-16 12:24:20 +010016#include <iomanip>
Colm Donelana21620d2019-10-11 13:09:49 +010017#include <iostream>
Colm Donelana21620d2019-10-11 13:09:49 +010018#include <string>
Rob Hughes25b74362020-01-13 11:14:59 +000019
20using namespace armnnUtils;
Colm Donelana21620d2019-10-11 13:09:49 +010021
Colm Donelana21620d2019-10-11 13:09:49 +010022namespace armnn
23{
24
25namespace gatordmock
26{
27
Colm Donelana21620d2019-10-11 13:09:49 +010028void GatordMockService::SendConnectionAck()
29{
30 if (m_EchoPackets)
31 {
32 std::cout << "Sending connection acknowledgement." << std::endl;
33 }
34 // The connection ack packet is an empty data packet with packetId == 1.
Finn Williams2ed809c2020-04-20 21:21:07 +010035 m_BasePipeServer.get()->SendPacket(0, 1, nullptr, 0);
Colm Donelana21620d2019-10-11 13:09:49 +010036}
37
Finn Williams15db7452019-10-15 14:22:13 +010038void GatordMockService::SendRequestCounterDir()
39{
40 if (m_EchoPackets)
41 {
42 std::cout << "Sending connection acknowledgement." << std::endl;
43 }
Keith Davis33ed2212020-03-30 10:43:41 +010044 // The request counter directory packet is an empty data packet with packetId == 3.
Finn Williams2ed809c2020-04-20 21:21:07 +010045 m_BasePipeServer.get()->SendPacket(0, 3, nullptr, 0);
Finn Williams15db7452019-10-15 14:22:13 +010046}
47
Keith Davis33ed2212020-03-30 10:43:41 +010048void GatordMockService::SendActivateTimelinePacket()
49{
50 if (m_EchoPackets)
51 {
52 std::cout << "Sending activate timeline packet." << std::endl;
53 }
54 // The activate timeline packet is an empty data packet with packetId == 6.
Finn Williams2ed809c2020-04-20 21:21:07 +010055 m_BasePipeServer.get()->SendPacket(0, 6, nullptr, 0);
Keith Davis33ed2212020-03-30 10:43:41 +010056}
57
58void GatordMockService::SendDeactivateTimelinePacket()
59{
60 if (m_EchoPackets)
61 {
62 std::cout << "Sending deactivate timeline packet." << std::endl;
63 }
64 // The deactivate timeline packet is an empty data packet with packetId == 7.
Finn Williams2ed809c2020-04-20 21:21:07 +010065 m_BasePipeServer.get()->SendPacket(0, 7, nullptr, 0);
Keith Davis33ed2212020-03-30 10:43:41 +010066}
67
Colm Donelana21620d2019-10-11 13:09:49 +010068bool GatordMockService::LaunchReceivingThread()
69{
70 if (m_EchoPackets)
71 {
72 std::cout << "Launching receiving thread." << std::endl;
73 }
74 // At this point we want to make the socket non blocking.
Finn Williams2ed809c2020-04-20 21:21:07 +010075 if (!m_BasePipeServer.get()->SetNonBlocking())
Colm Donelana21620d2019-10-11 13:09:49 +010076 {
Finn Williams2ed809c2020-04-20 21:21:07 +010077 m_BasePipeServer.get()->Close();
Colm Donelana21620d2019-10-11 13:09:49 +010078 std::cerr << "Failed to set socket as non blocking: " << strerror(errno) << std::endl;
79 return false;
80 }
Finn Williams2ed809c2020-04-20 21:21:07 +010081 m_ListeningThread = std::thread(&GatordMockService::ReceiveLoop, this);
Colm Donelana21620d2019-10-11 13:09:49 +010082 return true;
83}
84
85void GatordMockService::WaitForReceivingThread()
86{
Colm Donelan02705242019-11-14 14:19:07 +000087 // The receiving thread may already have died.
88 if (m_CloseReceivingThread != true)
89 {
90 m_CloseReceivingThread.store(true);
91 }
Colm Donelana21620d2019-10-11 13:09:49 +010092 // Check that the receiving thread is running
93 if (m_ListeningThread.joinable())
94 {
95 // Wait for the receiving thread to complete operations
96 m_ListeningThread.join();
97 }
Keith Davis33ed2212020-03-30 10:43:41 +010098
99 if(m_EchoPackets)
100 {
101 m_TimelineDecoder.print();
102 }
Colm Donelana21620d2019-10-11 13:09:49 +0100103}
104
Finn Williams2ed809c2020-04-20 21:21:07 +0100105bool GatordMockService::WaitForStreamMetaData()
106{
107 return m_BasePipeServer->WaitForStreamMetaData();
108}
109
Colm Donelanb682d842019-10-16 12:24:20 +0100110void GatordMockService::SendPeriodicCounterSelectionList(uint32_t period, std::vector<uint16_t> counters)
Colm Donelana21620d2019-10-11 13:09:49 +0100111{
Colm Donelanb682d842019-10-16 12:24:20 +0100112 // The packet body consists of a UINT32 representing the period following by zero or more
113 // UINT16's representing counter UID's. If the list is empty it implies all counters are to
114 // be disabled.
Colm Donelana21620d2019-10-11 13:09:49 +0100115
Colm Donelanb682d842019-10-16 12:24:20 +0100116 if (m_EchoPackets)
Colm Donelana21620d2019-10-11 13:09:49 +0100117 {
Colm Donelanb682d842019-10-16 12:24:20 +0100118 std::cout << "SendPeriodicCounterSelectionList: Period=" << std::dec << period << "uSec" << std::endl;
119 std::cout << "List length=" << counters.size() << std::endl;
Colm Donelanb682d842019-10-16 12:24:20 +0100120 }
121 // Start by calculating the length of the packet body in bytes. This will be at least 4.
122 uint32_t dataLength = static_cast<uint32_t>(4 + (counters.size() * 2));
123
124 std::unique_ptr<unsigned char[]> uniqueData = std::make_unique<unsigned char[]>(dataLength);
125 unsigned char* data = reinterpret_cast<unsigned char*>(uniqueData.get());
126
127 uint32_t offset = 0;
128 profiling::WriteUint32(data, offset, period);
129 offset += 4;
130 for (std::vector<uint16_t>::iterator it = counters.begin(); it != counters.end(); ++it)
131 {
132 profiling::WriteUint16(data, offset, *it);
133 offset += 2;
Colm Donelana21620d2019-10-11 13:09:49 +0100134 }
135
Colm Donelanb682d842019-10-16 12:24:20 +0100136 // Send the packet.
Finn Williams2ed809c2020-04-20 21:21:07 +0100137 m_BasePipeServer.get()->SendPacket(0, 4, data, dataLength);
Colm Donelanb682d842019-10-16 12:24:20 +0100138 // There will be an echo response packet sitting in the receive thread. PeriodicCounterSelectionResponseHandler
139 // should deal with it.
Colm Donelana21620d2019-10-11 13:09:49 +0100140}
141
Rob Hughes25b74362020-01-13 11:14:59 +0000142void GatordMockService::WaitCommand(uint32_t timeout)
Colm Donelana21620d2019-10-11 13:09:49 +0100143{
Colm Donelan02705242019-11-14 14:19:07 +0000144 // Wait for a maximum of timeout microseconds or if the receive thread has closed.
145 // There is a certain level of rounding involved in this timing.
Rob Hughes25b74362020-01-13 11:14:59 +0000146 uint32_t iterations = timeout / 1000;
Colm Donelan02705242019-11-14 14:19:07 +0000147 std::cout << std::dec << "Wait command with timeout of " << timeout << " iterations = " << iterations << std::endl;
Rob Hughes25b74362020-01-13 11:14:59 +0000148 uint32_t count = 0;
Colm Donelan02705242019-11-14 14:19:07 +0000149 while ((this->ReceiveThreadRunning() && (count < iterations)))
150 {
151 std::this_thread::sleep_for(std::chrono::microseconds(1000));
152 ++count;
153 }
Colm Donelana21620d2019-10-11 13:09:49 +0100154 if (m_EchoPackets)
155 {
156 std::cout << std::dec << "Wait command with timeout of " << timeout << " microseconds completed. " << std::endl;
157 }
158}
159
Finn Williams2ed809c2020-04-20 21:21:07 +0100160void GatordMockService::ReceiveLoop()
Colm Donelana21620d2019-10-11 13:09:49 +0100161{
162 m_CloseReceivingThread.store(false);
163 while (!m_CloseReceivingThread.load())
164 {
165 try
166 {
Finn Williams2ed809c2020-04-20 21:21:07 +0100167 profiling::Packet packet = m_BasePipeServer.get()->WaitForPacket(500);
168
169 profiling::PacketVersionResolver packetVersionResolver;
170
171 profiling::Version version =
172 packetVersionResolver.ResolvePacketVersion(packet.GetPacketFamily(), packet.GetPacketId());
173
174 profiling::CommandHandlerFunctor* commandHandlerFunctor = m_HandlerRegistry.GetFunctor(
175 packet.GetPacketFamily(),
176 packet.GetPacketId(),
177 version.GetEncodedValue());
178
179
180
181 ARMNN_ASSERT(commandHandlerFunctor);
182 commandHandlerFunctor->operator()(packet);
Colm Donelana21620d2019-10-11 13:09:49 +0100183 }
Jammy Zhoud80cc0c2019-10-21 16:44:40 +0800184 catch (const armnn::TimeoutException&)
Colm Donelana21620d2019-10-11 13:09:49 +0100185 {
186 // In this case we ignore timeouts and and keep trying to receive.
187 }
Keith Davis3201eea2019-10-24 17:30:41 +0100188 catch (const armnn::InvalidArgumentException& e)
Colm Donelanb682d842019-10-16 12:24:20 +0100189 {
190 // We couldn't find a functor to handle the packet?
191 std::cerr << "Packet received that could not be processed: " << e.what() << std::endl;
192 }
Keith Davis3201eea2019-10-24 17:30:41 +0100193 catch (const armnn::RuntimeException& e)
Colm Donelanb682d842019-10-16 12:24:20 +0100194 {
195 // A runtime exception occurred which means we must exit the loop.
196 std::cerr << "Receive thread closing: " << e.what() << std::endl;
197 m_CloseReceivingThread.store(true);
198 }
Colm Donelana21620d2019-10-11 13:09:49 +0100199 }
200}
201
Colm Donelanb682d842019-10-16 12:24:20 +0100202} // namespace gatordmock
Colm Donelana21620d2019-10-11 13:09:49 +0100203
Colm Donelanb682d842019-10-16 12:24:20 +0100204} // namespace armnn