a77d7ff4807044b584776284d97a91044035eee3
[platform/upstream/armnn.git] / tests / profiling / gatordmock / GatordMockService.hpp
1 //
2 // Copyright © 2019 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5
6 #pragma once
7
8 #include <CommandHandlerRegistry.hpp>
9 #include <Packet.hpp>
10
11 #include <atomic>
12 #include <string>
13 #include <thread>
14
15 namespace armnn
16 {
17
18 namespace gatordmock
19 {
20
21 enum class TargetEndianness
22 {
23     BeWire,
24     LeWire
25 };
26
27 enum class PacketDirection
28 {
29     Sending,
30     ReceivedHeader,
31     ReceivedData
32 };
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.
36 class GatordMockService
37 {
38 public:
39     /// @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
72     /// Send a request counter directory packet back to the client.
73     void SendRequestCounterDir();
74
75     /// 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.
90     void SendPeriodicCounterSelectionList(uint32_t period, std::vector<uint16_t> counters);
91
92     /// Execute the WAIT command from the comamnd file.
93     void WaitCommand(uint32_t 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
110 private:
111     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 uint8_t* data, uint32_t dataLength);
121
122     void EchoPacket(PacketDirection direction, uint8_t* packet, size_t lengthInBytes);
123
124     bool ReadHeader(uint32_t headerAsWords[2]);
125
126     bool ReadFromSocket(uint8_t* packetData, uint32_t expectedLength);
127
128     uint32_t ToUint32(uint8_t* data, TargetEndianness endianness);
129
130     void InsertU32(uint32_t value, uint8_t* data, TargetEndianness endianness);
131
132     static const uint32_t PIPE_MAGIC = 0x45495434;
133
134     std::atomic<uint32_t> m_PacketsReceivedCount;
135     TargetEndianness m_Endianness;
136     uint32_t m_StreamMetaDataVersion;
137     uint32_t m_StreamMetaDataMaxDataLen;
138     uint32_t m_StreamMetaDataPid;
139
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 };
148 }    // namespace gatordmock
149
150 }    // namespace armnn