1 //
2 // Copyright © 2019 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5
6 #include "SendTimelinePacket.hpp"
7
8 namespace arm
9 {
10
11 namespace pipe
12 {
13
Commit()14 void SendTimelinePacket::Commit()
15 {
16 if (m_WriteBuffer == nullptr)
17 {
18 // Can't commit from a null buffer
19 return;
20 }
21
22 if (!m_DirectoryPackage)
23 {
24 // Datalength should be Offset minus the two header words
25 m_PacketDataLength = m_Offset - m_uint32_t_size * 2;
26 // Reset offset to prepend header with full packet datalength
27 m_Offset = 0;
28
29 // Add header before commit
30 m_PacketHeader = CreateTimelinePacketHeader(1,0,1,0,0,m_PacketDataLength);
31
32 // Write the timeline binary packet header to the buffer
33 WriteUint32(m_WriteBuffer->GetWritableData(), m_Offset, m_PacketHeader.first);
34 m_Offset += m_uint32_t_size;
35 WriteUint32(m_WriteBuffer->GetWritableData(), m_Offset, m_PacketHeader.second);
36
37 m_BufferManager.Commit(m_WriteBuffer, m_PacketDataLength + m_uint32_t_size * 2);
38
39 }
40 else
41 {
42 m_DirectoryPackage = false;
43 m_BufferManager.Commit(m_WriteBuffer, m_Offset);
44 }
45
46 // Commit the message
47 m_WriteBuffer.reset(nullptr);
48 // Reset offset to start after prepended header
49 m_Offset = 8;
50 m_RemainingBufferSize = 0;
51 }
52
ReserveBuffer()53 void SendTimelinePacket::ReserveBuffer()
54 {
55 if (m_WriteBuffer != nullptr)
56 {
57 // Buffer already reserved
58 return;
59 }
60
61 uint32_t reserved = 0;
62
63 // Reserve the buffer
64 m_WriteBuffer = m_BufferManager.Reserve(MAX_METADATA_PACKET_LENGTH, reserved);
65
66 // Check if there is enough space in the buffer
67 if (m_WriteBuffer == nullptr)
68 {
69 throw arm::pipe::BufferExhaustion("No free buffers left", LOCATION());
70 }
71 if (reserved < m_Offset)
72 {
73 throw arm::pipe::BufferExhaustion("Reserved space too small for use", LOCATION());
74 }
75
76 if (m_DirectoryPackage)
77 {
78 m_RemainingBufferSize = reserved;
79 return;
80 }
81 // Account for the header size which is added at Commit()
82 m_RemainingBufferSize = reserved - 8;
83 }
84
SendTimelineEntityBinaryPacket(uint64_t profilingGuid)85 void SendTimelinePacket::SendTimelineEntityBinaryPacket(uint64_t profilingGuid)
86 {
87 ForwardWriteBinaryFunction(WriteTimelineEntityBinary,
88 profilingGuid);
89 }
90
SendTimelineEventBinaryPacket(uint64_t timestamp,int threadId,uint64_t profilingGuid)91 void SendTimelinePacket::SendTimelineEventBinaryPacket(uint64_t timestamp,
92 int threadId,
93 uint64_t profilingGuid)
94 {
95 ForwardWriteBinaryFunction(WriteTimelineEventBinary,
96 timestamp,
97 threadId,
98 profilingGuid);
99 }
100
SendTimelineEventClassBinaryPacket(uint64_t profilingGuid,uint64_t nameGuid)101 void SendTimelinePacket::SendTimelineEventClassBinaryPacket(uint64_t profilingGuid, uint64_t nameGuid)
102 {
103 ForwardWriteBinaryFunction(WriteTimelineEventClassBinary,
104 profilingGuid,
105 nameGuid);
106 }
107
SendTimelineLabelBinaryPacket(uint64_t profilingGuid,const std::string & label)108 void SendTimelinePacket::SendTimelineLabelBinaryPacket(uint64_t profilingGuid, const std::string& label)
109 {
110 ForwardWriteBinaryFunction(WriteTimelineLabelBinaryPacket,
111 profilingGuid,
112 label);
113 }
114
SendTimelineRelationshipBinaryPacket(ProfilingRelationshipType relationshipType,uint64_t relationshipGuid,uint64_t headGuid,uint64_t tailGuid,uint64_t attributeGuid)115 void SendTimelinePacket::SendTimelineRelationshipBinaryPacket(ProfilingRelationshipType relationshipType,
116 uint64_t relationshipGuid,
117 uint64_t headGuid,
118 uint64_t tailGuid,
119 uint64_t attributeGuid)
120 {
121 ForwardWriteBinaryFunction(WriteTimelineRelationshipBinary,
122 relationshipType,
123 relationshipGuid,
124 headGuid,
125 tailGuid,
126 attributeGuid);
127 }
128
SendTimelineMessageDirectoryPackage()129 void SendTimelinePacket::SendTimelineMessageDirectoryPackage()
130 {
131 try
132 {
133 // Flag to Reserve & Commit() that a DirectoryPackage is being sent
134 m_DirectoryPackage = true;
135 // Reserve buffer if it hasn't already been reserved
136 ReserveBuffer();
137 // Write to buffer
138 unsigned int numberOfBytesWritten = 0;
139 // Offset is initialised to 8
140 m_Offset = 0;
141
142 TimelinePacketStatus result = WriteTimelineMessageDirectoryPackage(&m_WriteBuffer->GetWritableData()[m_Offset],
143 m_RemainingBufferSize,
144 numberOfBytesWritten);
145 if (result != TimelinePacketStatus::Ok)
146 {
147 throw arm::pipe::ProfilingException("Error processing TimelineMessageDirectoryPackage", LOCATION());
148 }
149
150 // Commit the message
151 m_Offset += numberOfBytesWritten;
152 m_RemainingBufferSize -= numberOfBytesWritten;
153 Commit();
154 }
155 catch (...)
156 {
157 throw arm::pipe::ProfilingException("Error processing TimelineMessageDirectoryPackage", LOCATION());
158 }
159 }
160
161 } // namespace pipe
162
163 } // namespace arm
164