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