blob: ed76937cc39ef1f860f7a92379099e894f5ef43d [file] [log] [blame]
Ferran Balaguer73882172019-09-02 16:39:42 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#pragma once
7
Narumol Prangnawarat404b2752019-09-24 17:23:16 +01008#include "IBufferManager.hpp"
Ferran Balaguer73882172019-09-02 16:39:42 +01009#include "ISendCounterPacket.hpp"
Matteo Martincigh24e8f922019-09-19 11:57:46 +010010#include "ICounterDirectory.hpp"
11#include "IProfilingConnection.hpp"
Narumol Prangnawarat0ec068f2019-09-30 16:20:20 +010012#include "ProfilingUtils.hpp"
Matteo Martincigh24e8f922019-09-19 11:57:46 +010013
14#include <atomic>
Narumol Prangnawarat0ec068f2019-09-30 16:20:20 +010015#include <condition_variable>
Matteo Martincigh24e8f922019-09-19 11:57:46 +010016#include <mutex>
17#include <thread>
Narumol Prangnawarat0ec068f2019-09-30 16:20:20 +010018#include <type_traits>
Ferran Balaguer73882172019-09-02 16:39:42 +010019
20namespace armnn
21{
22
23namespace profiling
24{
25
26class SendCounterPacket : public ISendCounterPacket
27{
28public:
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +010029 using CategoryRecord = std::vector<uint32_t>;
30 using DeviceRecord = std::vector<uint32_t>;
31 using CounterSetRecord = std::vector<uint32_t>;
32 using EventRecord = std::vector<uint32_t>;
33
Francis Murtagh3a161982019-09-04 15:25:02 +010034 using IndexValuePairsVector = std::vector<std::pair<uint16_t, uint32_t>>;
35
Matteo Martincighe61ffd02019-10-07 10:19:35 +010036 SendCounterPacket(IBufferManager& buffer, int timeout = 1000)
37 : m_BufferManager(buffer)
38 , m_Timeout(timeout)
Matteo Martincigh24e8f922019-09-19 11:57:46 +010039 , m_IsRunning(false)
40 , m_KeepRunning(false)
Matteo Martincigh149528e2019-09-05 12:02:04 +010041 {}
Matteo Martincigh24e8f922019-09-19 11:57:46 +010042 ~SendCounterPacket() { Stop(); }
Ferran Balaguer73882172019-09-02 16:39:42 +010043
44 void SendStreamMetaDataPacket() override;
45
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +010046 void SendCounterDirectoryPacket(const ICounterDirectory& counterDirectory) override;
Ferran Balaguer73882172019-09-02 16:39:42 +010047
Francis Murtagh3a161982019-09-04 15:25:02 +010048 void SendPeriodicCounterCapturePacket(uint64_t timestamp, const IndexValuePairsVector& values) override;
Ferran Balaguer73882172019-09-02 16:39:42 +010049
50 void SendPeriodicCounterSelectionPacket(uint32_t capturePeriod,
51 const std::vector<uint16_t>& selectedCounterIds) override;
52
53 void SetReadyToRead() override;
54
Ferran Balaguer47d0fe92019-09-04 16:47:34 +010055 static const unsigned int PIPE_MAGIC = 0x45495434;
56 static const unsigned int MAX_METADATA_PACKET_LENGTH = 4096;
57
Matteo Martincighe61ffd02019-10-07 10:19:35 +010058 void Start(IProfilingConnection& profilingConnection);
Matteo Martincigh24e8f922019-09-19 11:57:46 +010059 void Stop();
60 bool IsRunning() { return m_IsRunning.load(); }
61
Ferran Balaguer73882172019-09-02 16:39:42 +010062private:
Matteo Martincighe61ffd02019-10-07 10:19:35 +010063 void Send(IProfilingConnection& profilingConnection);
Matteo Martincigh24e8f922019-09-19 11:57:46 +010064
Matteo Martincigh149528e2019-09-05 12:02:04 +010065 template <typename ExceptionType>
66 void CancelOperationAndThrow(const std::string& errorMessage)
67 {
Narumol Prangnawarat404b2752019-09-24 17:23:16 +010068 // Throw a runtime exception with the given error message
69 throw ExceptionType(errorMessage);
70 }
71
72 template <typename ExceptionType>
73 void CancelOperationAndThrow(std::unique_ptr<IPacketBuffer>& writerBuffer, const std::string& errorMessage)
74 {
Narumol Prangnawarat0ec068f2019-09-30 16:20:20 +010075 if (std::is_same<ExceptionType, armnn::profiling::BufferExhaustion>::value)
76 {
77 SetReadyToRead();
78 }
Narumol Prangnawarat404b2752019-09-24 17:23:16 +010079 if (writerBuffer != nullptr)
80 {
81 // Cancel the operation
82 m_BufferManager.Release(writerBuffer);
83 }
Matteo Martincigh149528e2019-09-05 12:02:04 +010084
85 // Throw a runtime exception with the given error message
86 throw ExceptionType(errorMessage);
87 }
88
Matteo Martincighe61ffd02019-10-07 10:19:35 +010089 void FlushBuffer(IProfilingConnection& profilingConnection);
Narumol Prangnawarat0ec068f2019-09-30 16:20:20 +010090
Narumol Prangnawarat404b2752019-09-24 17:23:16 +010091 IBufferManager& m_BufferManager;
Matteo Martincighe61ffd02019-10-07 10:19:35 +010092 int m_Timeout;
Matteo Martincigh24e8f922019-09-19 11:57:46 +010093 std::mutex m_WaitMutex;
94 std::condition_variable m_WaitCondition;
95 std::thread m_SendThread;
96 std::atomic<bool> m_IsRunning;
97 std::atomic<bool> m_KeepRunning;
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +010098
99protected:
100 // Helper methods, protected for testing
101 bool CreateCategoryRecord(const CategoryPtr& category,
102 const Counters& counters,
103 CategoryRecord& categoryRecord,
104 std::string& errorMessage);
105 bool CreateDeviceRecord(const DevicePtr& device,
106 DeviceRecord& deviceRecord,
107 std::string& errorMessage);
108 bool CreateCounterSetRecord(const CounterSetPtr& counterSet,
109 CounterSetRecord& counterSetRecord,
110 std::string& errorMessage);
111 bool CreateEventRecord(const CounterPtr& counter,
112 EventRecord& eventRecord,
113 std::string& errorMessage);
Ferran Balaguer73882172019-09-02 16:39:42 +0100114};
115
116} // namespace profiling
117
118} // namespace armnn