blob: 748371b9fa4245a124f34b83f7f506b4a21e4a2b [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
Narumol Prangnawarat0ec068f2019-09-30 16:20:20 +010036 SendCounterPacket(IProfilingConnection& profilingConnection, IBufferManager& buffer, int timeout = 1)
Matteo Martincigh24e8f922019-09-19 11:57:46 +010037 : m_ProfilingConnection(profilingConnection)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +010038 , m_BufferManager(buffer)
Matteo Martincigh24e8f922019-09-19 11:57:46 +010039 , m_IsRunning(false)
40 , m_KeepRunning(false)
Narumol Prangnawarat0ec068f2019-09-30 16:20:20 +010041 , m_Timeout(timeout)
Matteo Martincigh149528e2019-09-05 12:02:04 +010042 {}
Matteo Martincigh24e8f922019-09-19 11:57:46 +010043 ~SendCounterPacket() { Stop(); }
Ferran Balaguer73882172019-09-02 16:39:42 +010044
45 void SendStreamMetaDataPacket() override;
46
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +010047 void SendCounterDirectoryPacket(const ICounterDirectory& counterDirectory) override;
Ferran Balaguer73882172019-09-02 16:39:42 +010048
Francis Murtagh3a161982019-09-04 15:25:02 +010049 void SendPeriodicCounterCapturePacket(uint64_t timestamp, const IndexValuePairsVector& values) override;
Ferran Balaguer73882172019-09-02 16:39:42 +010050
51 void SendPeriodicCounterSelectionPacket(uint32_t capturePeriod,
52 const std::vector<uint16_t>& selectedCounterIds) override;
53
54 void SetReadyToRead() override;
55
Ferran Balaguer47d0fe92019-09-04 16:47:34 +010056 static const unsigned int PIPE_MAGIC = 0x45495434;
57 static const unsigned int MAX_METADATA_PACKET_LENGTH = 4096;
58
Matteo Martincigh24e8f922019-09-19 11:57:46 +010059 void Start();
60 void Stop();
61 bool IsRunning() { return m_IsRunning.load(); }
62
Ferran Balaguer73882172019-09-02 16:39:42 +010063private:
Matteo Martincigh24e8f922019-09-19 11:57:46 +010064 void Send();
65
Matteo Martincigh149528e2019-09-05 12:02:04 +010066 template <typename ExceptionType>
67 void CancelOperationAndThrow(const std::string& errorMessage)
68 {
Narumol Prangnawarat404b2752019-09-24 17:23:16 +010069 // Throw a runtime exception with the given error message
70 throw ExceptionType(errorMessage);
71 }
72
73 template <typename ExceptionType>
74 void CancelOperationAndThrow(std::unique_ptr<IPacketBuffer>& writerBuffer, const std::string& errorMessage)
75 {
Narumol Prangnawarat0ec068f2019-09-30 16:20:20 +010076 if (std::is_same<ExceptionType, armnn::profiling::BufferExhaustion>::value)
77 {
78 SetReadyToRead();
79 }
Narumol Prangnawarat404b2752019-09-24 17:23:16 +010080 if (writerBuffer != nullptr)
81 {
82 // Cancel the operation
83 m_BufferManager.Release(writerBuffer);
84 }
Matteo Martincigh149528e2019-09-05 12:02:04 +010085
86 // Throw a runtime exception with the given error message
87 throw ExceptionType(errorMessage);
88 }
89
Narumol Prangnawarat0ec068f2019-09-30 16:20:20 +010090 void FlushBuffer();
91
Matteo Martincigh24e8f922019-09-19 11:57:46 +010092 IProfilingConnection& m_ProfilingConnection;
Narumol Prangnawarat404b2752019-09-24 17:23:16 +010093 IBufferManager& m_BufferManager;
Matteo Martincigh24e8f922019-09-19 11:57:46 +010094 std::mutex m_WaitMutex;
95 std::condition_variable m_WaitCondition;
96 std::thread m_SendThread;
97 std::atomic<bool> m_IsRunning;
98 std::atomic<bool> m_KeepRunning;
Narumol Prangnawarat0ec068f2019-09-30 16:20:20 +010099 int m_Timeout;
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +0100100
101protected:
102 // Helper methods, protected for testing
103 bool CreateCategoryRecord(const CategoryPtr& category,
104 const Counters& counters,
105 CategoryRecord& categoryRecord,
106 std::string& errorMessage);
107 bool CreateDeviceRecord(const DevicePtr& device,
108 DeviceRecord& deviceRecord,
109 std::string& errorMessage);
110 bool CreateCounterSetRecord(const CounterSetPtr& counterSet,
111 CounterSetRecord& counterSetRecord,
112 std::string& errorMessage);
113 bool CreateEventRecord(const CounterPtr& counter,
114 EventRecord& eventRecord,
115 std::string& errorMessage);
Ferran Balaguer73882172019-09-02 16:39:42 +0100116};
117
118} // namespace profiling
119
120} // namespace armnn