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