blob: deafcfdc9273bd84d2e49501638a23b7667c68ff [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//
5
6#pragma once
7
Matteo Martincigh65984272019-10-17 13:26:21 +01008#include <CommandHandlerRegistry.hpp>
9#include <Packet.hpp>
10
Colm Donelanb682d842019-10-16 12:24:20 +010011#include <atomic>
Colm Donelana21620d2019-10-11 13:09:49 +010012#include <string>
13#include <thread>
Colm Donelana21620d2019-10-11 13:09:49 +010014
Colm Donelana21620d2019-10-11 13:09:49 +010015namespace armnn
16{
17
18namespace gatordmock
19{
20
21enum class TargetEndianness
22{
Colm Donelanb682d842019-10-16 12:24:20 +010023 BeWire,
24 LeWire
Colm Donelana21620d2019-10-11 13:09:49 +010025};
26
27enum class PacketDirection
28{
Colm Donelanb682d842019-10-16 12:24:20 +010029 Sending,
30 ReceivedHeader,
31 ReceivedData
Colm Donelana21620d2019-10-11 13:09:49 +010032};
33
34/// A class that implements a Mock Gatord server. It will listen on a specified Unix domain socket (UDS)
35/// namespace for client connections. It will then allow opertaions to manage coutners while receiving counter data.
36class GatordMockService
37{
38public:
Colm Donelana21620d2019-10-11 13:09:49 +010039 /// @param registry reference to a command handler registry.
40 /// @param echoPackets if true the raw packets will be printed to stdout.
41 GatordMockService(armnn::profiling::CommandHandlerRegistry& registry, bool echoPackets)
42 : m_HandlerRegistry(registry)
43 , m_EchoPackets(echoPackets)
44 {
45 m_PacketsReceivedCount.store(0, std::memory_order_relaxed);
46 }
47
48 ~GatordMockService()
49 {
50 // We have set SOCK_CLOEXEC on these sockets but we'll close them to be good citizens.
51 close(m_ClientConnection);
52 close(m_ListeningSocket);
53 }
54
55 /// Establish the Unix domain socket and set it to listen for connections.
56 /// @param udsNamespace the namespace (socket address) associated with the listener.
57 /// @return true only if the socket has been correctly setup.
58 bool OpenListeningSocket(std::string udsNamespace);
59
60 /// Block waiting to accept one client to connect to the UDS.
61 /// @return the file descriptor of the client connection.
62 int BlockForOneClient();
63
64 /// Once the connection is open wait to receive the stream meta data packet from the client. Reading this
65 /// packet differs from others as we need to determine endianness.
66 /// @return true only if a valid stream met data packet has been received.
67 bool WaitForStreamMetaData();
68
69 /// Send a connection acknowledged packet back to the client.
70 void SendConnectionAck();
71
Finn Williams15db7452019-10-15 14:22:13 +010072 /// Send a request counter directory packet back to the client.
73 void SendRequestCounterDir();
74
Colm Donelana21620d2019-10-11 13:09:49 +010075 /// Start the thread that will receive all packets and print them nicely to stdout.
76 bool LaunchReceivingThread();
77
78 /// Return the total number of periodic counter capture packets received since the receive thread started.
79 /// @return number of periodic counter capture packets received.
80 uint32_t GetPacketsReceivedCount()
81 {
82 return m_PacketsReceivedCount.load(std::memory_order_acquire);
83 }
84
85 /// This is a placeholder method to prevent main exiting. It can be removed once the
86 /// command handling code is added.
87 void WaitForReceivingThread();
88
89 /// Send the counter list to ArmNN.
Colm Donelanb682d842019-10-16 12:24:20 +010090 void SendPeriodicCounterSelectionList(uint32_t period, std::vector<uint16_t> counters);
Colm Donelana21620d2019-10-11 13:09:49 +010091
92 /// Execute the WAIT command from the comamnd file.
93 void WaitCommand(uint timeout);
94
95 uint32_t GetStreamMetadataVersion()
96 {
97 return m_StreamMetaDataVersion;
98 }
99
100 uint32_t GetStreamMetadataMaxDataLen()
101 {
102 return m_StreamMetaDataMaxDataLen;
103 }
104
105 uint32_t GetStreamMetadataPid()
106 {
107 return m_StreamMetaDataPid;
108 }
109
110private:
Colm Donelana21620d2019-10-11 13:09:49 +0100111 void ReceiveLoop(GatordMockService& mockService);
112
113 /// Block on the client connection until a complete packet has been received. This is a placeholder function to
114 /// enable early testing of the tool.
115 /// @return true if a valid packet has been received.
116 armnn::profiling::Packet WaitForPacket(uint32_t timeoutMs);
117
118 armnn::profiling::Packet ReceivePacket();
119
120 bool SendPacket(uint32_t packetFamily, uint32_t packetId, const u_char* data, uint32_t dataLength);
121
122 void EchoPacket(PacketDirection direction, u_char* packet, size_t lengthInBytes);
123
124 bool ReadHeader(uint32_t headerAsWords[2]);
125
126 bool ReadFromSocket(u_char* packetData, uint32_t expectedLength);
127
128 uint32_t ToUint32(u_char* data, TargetEndianness endianness);
129
130 void InsertU32(uint32_t value, u_char* data, TargetEndianness endianness);
131
132 static const uint32_t PIPE_MAGIC = 0x45495434;
133
134 std::atomic<uint32_t> m_PacketsReceivedCount;
Colm Donelanb682d842019-10-16 12:24:20 +0100135 TargetEndianness m_Endianness;
136 uint32_t m_StreamMetaDataVersion;
137 uint32_t m_StreamMetaDataMaxDataLen;
138 uint32_t m_StreamMetaDataPid;
Colm Donelana21620d2019-10-11 13:09:49 +0100139
140 armnn::profiling::CommandHandlerRegistry& m_HandlerRegistry;
141
142 bool m_EchoPackets;
143 int m_ListeningSocket;
144 int m_ClientConnection;
145 std::thread m_ListeningThread;
146 std::atomic<bool> m_CloseReceivingThread;
147};
Colm Donelanb682d842019-10-16 12:24:20 +0100148} // namespace gatordmock
Colm Donelana21620d2019-10-11 13:09:49 +0100149
Colm Donelanb682d842019-10-16 12:24:20 +0100150} // namespace armnn