blob: 10bf88406eedf8b1d34fff4111420167895a8a3d [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
72 /// Start the thread that will receive all packets and print them nicely to stdout.
73 bool LaunchReceivingThread();
74
75 /// Return the total number of periodic counter capture packets received since the receive thread started.
76 /// @return number of periodic counter capture packets received.
77 uint32_t GetPacketsReceivedCount()
78 {
79 return m_PacketsReceivedCount.load(std::memory_order_acquire);
80 }
81
82 /// This is a placeholder method to prevent main exiting. It can be removed once the
83 /// command handling code is added.
84 void WaitForReceivingThread();
85
86 /// Send the counter list to ArmNN.
Colm Donelanb682d842019-10-16 12:24:20 +010087 void SendPeriodicCounterSelectionList(uint32_t period, std::vector<uint16_t> counters);
Colm Donelana21620d2019-10-11 13:09:49 +010088
89 /// Execute the WAIT command from the comamnd file.
90 void WaitCommand(uint timeout);
91
92 uint32_t GetStreamMetadataVersion()
93 {
94 return m_StreamMetaDataVersion;
95 }
96
97 uint32_t GetStreamMetadataMaxDataLen()
98 {
99 return m_StreamMetaDataMaxDataLen;
100 }
101
102 uint32_t GetStreamMetadataPid()
103 {
104 return m_StreamMetaDataPid;
105 }
106
107private:
Colm Donelana21620d2019-10-11 13:09:49 +0100108 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;
Colm Donelanb682d842019-10-16 12:24:20 +0100132 TargetEndianness m_Endianness;
133 uint32_t m_StreamMetaDataVersion;
134 uint32_t m_StreamMetaDataMaxDataLen;
135 uint32_t m_StreamMetaDataPid;
Colm Donelana21620d2019-10-11 13:09:49 +0100136
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};
Colm Donelanb682d842019-10-16 12:24:20 +0100145} // namespace gatordmock
Colm Donelana21620d2019-10-11 13:09:49 +0100146
Colm Donelanb682d842019-10-16 12:24:20 +0100147} // namespace armnn