1 // 2 // Copyright © 2019 Arm Ltd and Contributors. All rights reserved. 3 // SPDX-License-Identifier: MIT 4 // 5 6 #pragma once 7 8 #include "IProfilingConnection.hpp" 9 #include "ProfilingUtils.hpp" 10 11 #include <client/include/ILocalPacketHandler.hpp> 12 #include <client/include/ProfilingOptions.hpp> 13 14 #include <common/include/Assert.hpp> 15 #include <common/include/Packet.hpp> 16 17 #include <server/include/timelineDecoder/DirectoryCaptureCommandHandler.hpp> 18 19 #include <atomic> 20 #include <fstream> 21 #include <map> 22 #include <queue> 23 24 #if !defined(ARMNN_DISABLE_THREADS) 25 #include <condition_variable> 26 #include <mutex> 27 #include <thread> 28 #endif 29 30 namespace arm 31 { 32 33 namespace pipe 34 { 35 36 // forward declaration 37 class FileOnlyProfilingConnection; 38 39 class StreamMetaDataProcessor : public ILocalPacketHandler 40 { 41 public: StreamMetaDataProcessor(FileOnlyProfilingConnection * fileOnlyProfilingConnection)42 explicit StreamMetaDataProcessor(FileOnlyProfilingConnection* fileOnlyProfilingConnection) : 43 m_FileOnlyProfilingConnection(fileOnlyProfilingConnection), 44 m_MetaDataPacketHeader(ConstructHeader(0, 0)) {}; 45 46 std::vector<uint32_t> GetHeadersAccepted() override; 47 48 void HandlePacket(const arm::pipe::Packet& packet) override; 49 50 private: 51 FileOnlyProfilingConnection* m_FileOnlyProfilingConnection; 52 uint32_t m_MetaDataPacketHeader; 53 54 static uint32_t ToUint32(const unsigned char* data, TargetEndianness endianness); 55 }; 56 57 class FileOnlyProfilingConnection : public IProfilingConnection, public IInternalProfilingConnection 58 { 59 public: FileOnlyProfilingConnection(const ProfilingOptions & options)60 explicit FileOnlyProfilingConnection(const ProfilingOptions& options) 61 : m_Options(options) 62 , m_Endianness(TargetEndianness::LeWire) // Set a sensible default. 63 // StreamMetaDataProcessor will set a real value. 64 , m_IsRunning(false) 65 , m_KeepRunning(false) 66 , m_Timeout(1000) 67 { 68 // add the StreamMetaDataProcessor 69 auto streamMetaDataProcessor = std::make_shared<StreamMetaDataProcessor>(this); 70 AddLocalPacketHandler(streamMetaDataProcessor); 71 // and any additional ones added by the users 72 for (const ILocalPacketHandlerSharedPtr& localPacketHandler : options.m_LocalPacketHandlers) 73 { 74 AddLocalPacketHandler(localPacketHandler); 75 } 76 if (!m_PacketHandlers.empty()) 77 { 78 StartProcessingThread(); 79 } 80 // NOTE: could add timeout to the external profiling options 81 }; 82 83 ~FileOnlyProfilingConnection() override; 84 85 bool IsOpen() const override; 86 87 void Close() override; 88 89 // This is effectively receiving a data packet from ArmNN. 90 bool WritePacket(const unsigned char* buffer, uint32_t length) override; 91 92 // Sending a packet back to ArmNN. 93 arm::pipe::Packet ReadPacket(uint32_t timeout) override; 94 SetEndianess(const TargetEndianness & endianness)95 void SetEndianess(const TargetEndianness& endianness) override //IInternalProfilingConnection 96 { 97 m_Endianness = endianness; 98 } 99 100 void ReturnPacket(arm::pipe::Packet& packet) override; //IInternalProfilingConnection 101 102 private: 103 void AddLocalPacketHandler(ILocalPacketHandlerSharedPtr localPacketHandler); 104 void StartProcessingThread(); 105 void ClearReadableList(); 106 void DispatchPacketToHandlers(const arm::pipe::Packet& packet); 107 108 void Fail(const std::string& errorMessage); 109 110 void ForwardPacketToHandlers(arm::pipe::Packet& packet); 111 void ServiceLocalHandlers(); 112 113 ProfilingOptions m_Options; 114 std::queue<arm::pipe::Packet> m_PacketQueue; 115 TargetEndianness m_Endianness; 116 117 #if !defined(ARMNN_DISABLE_THREADS) 118 std::mutex m_PacketAvailableMutex; 119 std::condition_variable m_ConditionPacketAvailable; 120 #endif 121 122 std::vector<ILocalPacketHandlerSharedPtr> m_PacketHandlers; 123 std::map<uint32_t, std::vector<ILocalPacketHandlerSharedPtr>> m_IndexedHandlers; 124 std::vector<ILocalPacketHandlerSharedPtr> m_UniversalHandlers; 125 126 // List of readable packets for the local packet handlers 127 std::queue<arm::pipe::Packet> m_ReadableList; 128 // Mutex and condition variable for the readable packet list 129 #if !defined(ARMNN_DISABLE_THREADS) 130 std::mutex m_ReadableMutex; 131 std::condition_variable m_ConditionPacketReadable; 132 // thread that takes items from the readable list and dispatches them 133 // to the handlers. 134 std::thread m_LocalHandlersThread; 135 #endif 136 // atomic booleans that control the operation of the local handlers thread 137 std::atomic<bool> m_IsRunning; 138 std::atomic<bool> m_KeepRunning; 139 int m_Timeout; 140 }; 141 142 } // namespace pipe 143 144 } // namespace arm 145