1 //
2 // Copyright © 2019 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5
6 #pragma once
7
8 #include "IBufferManager.hpp"
9 #include "ProfilingUtils.hpp"
10
11 #include <client/include/ISendTimelinePacket.hpp>
12
13 #include <common/include/Assert.hpp>
14
15 #include <memory>
16
17 namespace arm
18 {
19
20 namespace pipe
21 {
22
23 class SendTimelinePacket : public ISendTimelinePacket
24 {
25 public:
SendTimelinePacket(IBufferManager & bufferManager)26 SendTimelinePacket(IBufferManager& bufferManager)
27 : m_BufferManager(bufferManager)
28 , m_WriteBuffer(nullptr)
29 , m_Offset(8u)
30 , m_RemainingBufferSize(0u)
31 , m_PacketDataLength(0u)
32 {}
33
34 /// Commits the current buffer and reset the member variables
35 void Commit() override;
36
37 /// Create and write a TimelineEntityBinaryPacket from the parameters to the buffer.
38 void SendTimelineEntityBinaryPacket(uint64_t profilingGuid) override;
39
40 /// Create and write a TimelineEventBinaryPacket from the parameters to the buffer.
41 void SendTimelineEventBinaryPacket(uint64_t timestamp, int threadId, uint64_t profilingGuid) override;
42
43 /// Create and write a TimelineEventClassBinaryPacket from the parameters to the buffer.
44 void SendTimelineEventClassBinaryPacket(uint64_t profilingGuid, uint64_t nameGuid) override;
45
46 /// Create and write a TimelineLabelBinaryPacket from the parameters to the buffer.
47 void SendTimelineLabelBinaryPacket(uint64_t profilingGuid, const std::string& label) override;
48
49 /// Create and write a TimelineMessageDirectoryPackage in the buffer
50 void SendTimelineMessageDirectoryPackage() override;
51
52 /// Create and write a TimelineRelationshipBinaryPacket from the parameters to the buffer.
53 virtual void SendTimelineRelationshipBinaryPacket(ProfilingRelationshipType relationshipType,
54 uint64_t relationshipGuid,
55 uint64_t headGuid,
56 uint64_t tailGuid,
57 uint64_t attributeGuid) override;
58 private:
59 /// Reserves maximum packet size from buffer
60 void ReserveBuffer();
61
62 template <typename Func, typename ... Params>
63 void ForwardWriteBinaryFunction(Func& func, Params&& ... params);
64
65 IBufferManager& m_BufferManager;
66 IPacketBufferPtr m_WriteBuffer;
67 unsigned int m_Offset;
68 unsigned int m_RemainingBufferSize;
69
70 const unsigned int m_uint32_t_size = sizeof(uint32_t);
71
72 std::pair<uint32_t, uint32_t> m_PacketHeader;
73 uint32_t m_PacketDataLength;
74
75 bool m_DirectoryPackage = false;
76 };
77
78 template<typename Func, typename ... Params>
ForwardWriteBinaryFunction(Func & func,Params &&...params)79 void SendTimelinePacket::ForwardWriteBinaryFunction(Func& func, Params&& ... params)
80 {
81 try
82 {
83 ReserveBuffer();
84 ARM_PIPE_ASSERT(m_WriteBuffer);
85 unsigned int numberOfBytesWritten = 0;
86 // Header will be prepended to the buffer on Commit()
87 while ( true )
88 {
89 TimelinePacketStatus result = func(std::forward<Params>(params)...,
90 &m_WriteBuffer->GetWritableData()[m_Offset],
91 m_RemainingBufferSize,
92 numberOfBytesWritten);
93 switch ( result )
94 {
95 case TimelinePacketStatus::BufferExhaustion:
96 Commit();
97 ReserveBuffer();
98 continue;
99
100 case TimelinePacketStatus::Error:
101 throw arm::pipe::ProfilingException("Error processing while sending TimelineBinaryPacket",
102 LOCATION());
103
104 default:
105 m_Offset += numberOfBytesWritten;
106 m_RemainingBufferSize -= numberOfBytesWritten;
107 return;
108 }
109 }
110 }
111 catch (const arm::pipe::BufferExhaustion& ex)
112 {
113 // ditto
114 throw ex;
115 }
116 catch (const arm::pipe::ProfilingException& ex)
117 {
118 // don't swallow in the catch all block
119 throw ex;
120 }
121 catch ( ... )
122 {
123 throw arm::pipe::ProfilingException("Unknown Exception thrown while sending TimelineBinaryPacket", LOCATION());
124 }
125 }
126
127 } // namespace pipe
128
129 } // namespace arm
130