blob: 42e84323e420beeae06759badea27765fce95220 [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"
Matteo Martincigh24e8f922019-09-19 11:57:46 +01009#include "ICounterDirectory.hpp"
Matteo Martincigh5d737fb2019-10-07 13:05:13 +010010#include "ISendCounterPacket.hpp"
Matteo Martincigh24e8f922019-09-19 11:57:46 +010011#include "IProfilingConnection.hpp"
Matteo Martincigh5d737fb2019-10-07 13:05:13 +010012#include "ProfilingStateMachine.hpp"
Narumol Prangnawarat0ec068f2019-09-30 16:20:20 +010013#include "ProfilingUtils.hpp"
Matteo Martincigh24e8f922019-09-19 11:57:46 +010014
15#include <atomic>
Narumol Prangnawarat0ec068f2019-09-30 16:20:20 +010016#include <condition_variable>
Matteo Martincigh24e8f922019-09-19 11:57:46 +010017#include <mutex>
18#include <thread>
Narumol Prangnawarat0ec068f2019-09-30 16:20:20 +010019#include <type_traits>
Ferran Balaguer73882172019-09-02 16:39:42 +010020
21namespace armnn
22{
23
24namespace profiling
25{
26
27class SendCounterPacket : public ISendCounterPacket
28{
29public:
Matteo Martincigh5d737fb2019-10-07 13:05:13 +010030 using CategoryRecord = std::vector<uint32_t>;
31 using DeviceRecord = std::vector<uint32_t>;
32 using CounterSetRecord = std::vector<uint32_t>;
33 using EventRecord = std::vector<uint32_t>;
Francis Murtagh3a161982019-09-04 15:25:02 +010034 using IndexValuePairsVector = std::vector<std::pair<uint16_t, uint32_t>>;
35
Matteo Martincigh5d737fb2019-10-07 13:05:13 +010036 SendCounterPacket(ProfilingStateMachine& profilingStateMachine, IBufferManager& buffer, int timeout = 1000)
37 : m_StateMachine(profilingStateMachine)
38 , m_BufferManager(buffer)
Matteo Martincighe61ffd02019-10-07 10:19:35 +010039 , m_Timeout(timeout)
Matteo Martincigh24e8f922019-09-19 11:57:46 +010040 , m_IsRunning(false)
41 , m_KeepRunning(false)
Matteo Martincigh5d737fb2019-10-07 13:05:13 +010042 , m_SendThreadException(nullptr)
Matteo Martincigh149528e2019-09-05 12:02:04 +010043 {}
Matteo Martincigh5d737fb2019-10-07 13:05:13 +010044 ~SendCounterPacket()
45 {
46 // Don't rethrow when destructing the object
47 Stop(false);
48 }
Ferran Balaguer73882172019-09-02 16:39:42 +010049
50 void SendStreamMetaDataPacket() override;
51
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +010052 void SendCounterDirectoryPacket(const ICounterDirectory& counterDirectory) override;
Ferran Balaguer73882172019-09-02 16:39:42 +010053
Francis Murtagh3a161982019-09-04 15:25:02 +010054 void SendPeriodicCounterCapturePacket(uint64_t timestamp, const IndexValuePairsVector& values) override;
Ferran Balaguer73882172019-09-02 16:39:42 +010055
56 void SendPeriodicCounterSelectionPacket(uint32_t capturePeriod,
57 const std::vector<uint16_t>& selectedCounterIds) override;
58
59 void SetReadyToRead() override;
60
Ferran Balaguer47d0fe92019-09-04 16:47:34 +010061 static const unsigned int PIPE_MAGIC = 0x45495434;
Ferran Balaguer47d0fe92019-09-04 16:47:34 +010062
Matteo Martincighe61ffd02019-10-07 10:19:35 +010063 void Start(IProfilingConnection& profilingConnection);
Matteo Martincigh5d737fb2019-10-07 13:05:13 +010064 void Stop(bool rethrowSendThreadExceptions = true);
Matteo Martincigh24e8f922019-09-19 11:57:46 +010065 bool IsRunning() { return m_IsRunning.load(); }
66
Colm Donelan2ba48d22019-11-29 09:10:59 +000067 void WaitForPacketSent(uint32_t timeout = 1000)
Matteo Martincighe8485382019-10-10 14:08:21 +010068 {
69 std::unique_lock<std::mutex> lock(m_PacketSentWaitMutex);
Colm Donelan2ba48d22019-11-29 09:10:59 +000070 // Blocks until notified that at least a packet has been sent or until timeout expires.
71 m_PacketSentWaitCondition.wait_for(lock, std::chrono::milliseconds(timeout));
Matteo Martincighe8485382019-10-10 14:08:21 +010072 }
73
Ferran Balaguer73882172019-09-02 16:39:42 +010074private:
Matteo Martincighe61ffd02019-10-07 10:19:35 +010075 void Send(IProfilingConnection& profilingConnection);
Matteo Martincigh24e8f922019-09-19 11:57:46 +010076
Matteo Martincigh149528e2019-09-05 12:02:04 +010077 template <typename ExceptionType>
78 void CancelOperationAndThrow(const std::string& errorMessage)
79 {
Narumol Prangnawarat404b2752019-09-24 17:23:16 +010080 // Throw a runtime exception with the given error message
81 throw ExceptionType(errorMessage);
82 }
83
84 template <typename ExceptionType>
Matteo Martincigh2ffcc412019-11-05 11:47:40 +000085 void CancelOperationAndThrow(IPacketBufferPtr& writerBuffer, const std::string& errorMessage)
Narumol Prangnawarat404b2752019-09-24 17:23:16 +010086 {
Narumol Prangnawarat0ec068f2019-09-30 16:20:20 +010087 if (std::is_same<ExceptionType, armnn::profiling::BufferExhaustion>::value)
88 {
89 SetReadyToRead();
90 }
Matteo Martincigh5d737fb2019-10-07 13:05:13 +010091
Narumol Prangnawarat404b2752019-09-24 17:23:16 +010092 if (writerBuffer != nullptr)
93 {
94 // Cancel the operation
95 m_BufferManager.Release(writerBuffer);
96 }
Matteo Martincigh149528e2019-09-05 12:02:04 +010097
98 // Throw a runtime exception with the given error message
99 throw ExceptionType(errorMessage);
100 }
101
Matteo Martincighe8485382019-10-10 14:08:21 +0100102 void FlushBuffer(IProfilingConnection& profilingConnection, bool notifyWatchers = true);
Narumol Prangnawarat0ec068f2019-09-30 16:20:20 +0100103
Matteo Martincigh5d737fb2019-10-07 13:05:13 +0100104 ProfilingStateMachine& m_StateMachine;
Narumol Prangnawarat404b2752019-09-24 17:23:16 +0100105 IBufferManager& m_BufferManager;
Matteo Martincighe61ffd02019-10-07 10:19:35 +0100106 int m_Timeout;
Matteo Martincigh24e8f922019-09-19 11:57:46 +0100107 std::mutex m_WaitMutex;
108 std::condition_variable m_WaitCondition;
109 std::thread m_SendThread;
110 std::atomic<bool> m_IsRunning;
111 std::atomic<bool> m_KeepRunning;
Matteo Martincigh5d737fb2019-10-07 13:05:13 +0100112 std::exception_ptr m_SendThreadException;
Matteo Martincighe8485382019-10-10 14:08:21 +0100113 std::mutex m_PacketSentWaitMutex;
114 std::condition_variable m_PacketSentWaitCondition;
Matteo Martincigh42f9d9e2019-09-05 12:02:04 +0100115
116protected:
117 // Helper methods, protected for testing
118 bool CreateCategoryRecord(const CategoryPtr& category,
119 const Counters& counters,
120 CategoryRecord& categoryRecord,
121 std::string& errorMessage);
122 bool CreateDeviceRecord(const DevicePtr& device,
123 DeviceRecord& deviceRecord,
124 std::string& errorMessage);
125 bool CreateCounterSetRecord(const CounterSetPtr& counterSet,
126 CounterSetRecord& counterSetRecord,
127 std::string& errorMessage);
128 bool CreateEventRecord(const CounterPtr& counter,
129 EventRecord& eventRecord,
130 std::string& errorMessage);
Ferran Balaguer73882172019-09-02 16:39:42 +0100131};
132
133} // namespace profiling
134
135} // namespace armnn