| // |
| // Copyright © 2017 Arm Ltd. All rights reserved. |
| // SPDX-License-Identifier: MIT |
| // |
| |
| #pragma once |
| |
| #include "IBufferManager.hpp" |
| #include "ICounterDirectory.hpp" |
| #include "ISendCounterPacket.hpp" |
| #include "IProfilingConnection.hpp" |
| #include "ProfilingStateMachine.hpp" |
| #include "ProfilingUtils.hpp" |
| |
| #include <atomic> |
| #include <condition_variable> |
| #include <mutex> |
| #include <thread> |
| #include <type_traits> |
| |
| namespace armnn |
| { |
| |
| namespace profiling |
| { |
| |
| class SendCounterPacket : public ISendCounterPacket |
| { |
| public: |
| using CategoryRecord = std::vector<uint32_t>; |
| using DeviceRecord = std::vector<uint32_t>; |
| using CounterSetRecord = std::vector<uint32_t>; |
| using EventRecord = std::vector<uint32_t>; |
| using IndexValuePairsVector = std::vector<std::pair<uint16_t, uint32_t>>; |
| |
| SendCounterPacket(ProfilingStateMachine& profilingStateMachine, IBufferManager& buffer, int timeout = 1000) |
| : m_StateMachine(profilingStateMachine) |
| , m_BufferManager(buffer) |
| , m_Timeout(timeout) |
| , m_IsRunning(false) |
| , m_KeepRunning(false) |
| , m_SendThreadException(nullptr) |
| {} |
| ~SendCounterPacket() |
| { |
| // Don't rethrow when destructing the object |
| Stop(false); |
| } |
| |
| void SendStreamMetaDataPacket() override; |
| |
| void SendCounterDirectoryPacket(const ICounterDirectory& counterDirectory) override; |
| |
| void SendPeriodicCounterCapturePacket(uint64_t timestamp, const IndexValuePairsVector& values) override; |
| |
| void SendPeriodicCounterSelectionPacket(uint32_t capturePeriod, |
| const std::vector<uint16_t>& selectedCounterIds) override; |
| |
| void SetReadyToRead() override; |
| |
| static const unsigned int PIPE_MAGIC = 0x45495434; |
| static const unsigned int MAX_METADATA_PACKET_LENGTH = 4096; |
| |
| void Start(IProfilingConnection& profilingConnection); |
| void Stop(bool rethrowSendThreadExceptions = true); |
| bool IsRunning() { return m_IsRunning.load(); } |
| |
| private: |
| void Send(IProfilingConnection& profilingConnection); |
| |
| template <typename ExceptionType> |
| void CancelOperationAndThrow(const std::string& errorMessage) |
| { |
| // Throw a runtime exception with the given error message |
| throw ExceptionType(errorMessage); |
| } |
| |
| template <typename ExceptionType> |
| void CancelOperationAndThrow(std::unique_ptr<IPacketBuffer>& writerBuffer, const std::string& errorMessage) |
| { |
| if (std::is_same<ExceptionType, armnn::profiling::BufferExhaustion>::value) |
| { |
| SetReadyToRead(); |
| } |
| |
| if (writerBuffer != nullptr) |
| { |
| // Cancel the operation |
| m_BufferManager.Release(writerBuffer); |
| } |
| |
| // Throw a runtime exception with the given error message |
| throw ExceptionType(errorMessage); |
| } |
| |
| void FlushBuffer(IProfilingConnection& profilingConnection); |
| |
| ProfilingStateMachine& m_StateMachine; |
| IBufferManager& m_BufferManager; |
| int m_Timeout; |
| std::mutex m_WaitMutex; |
| std::condition_variable m_WaitCondition; |
| std::thread m_SendThread; |
| std::atomic<bool> m_IsRunning; |
| std::atomic<bool> m_KeepRunning; |
| std::exception_ptr m_SendThreadException; |
| |
| protected: |
| // Helper methods, protected for testing |
| bool CreateCategoryRecord(const CategoryPtr& category, |
| const Counters& counters, |
| CategoryRecord& categoryRecord, |
| std::string& errorMessage); |
| bool CreateDeviceRecord(const DevicePtr& device, |
| DeviceRecord& deviceRecord, |
| std::string& errorMessage); |
| bool CreateCounterSetRecord(const CounterSetPtr& counterSet, |
| CounterSetRecord& counterSetRecord, |
| std::string& errorMessage); |
| bool CreateEventRecord(const CounterPtr& counter, |
| EventRecord& eventRecord, |
| std::string& errorMessage); |
| }; |
| |
| } // namespace profiling |
| |
| } // namespace armnn |