xref: /aosp_15_r20/external/armnn/src/profiling/test/TestTimelinePacketHandler.cpp (revision 89c4ff92f2867872bb9e2354d150bf0c8c502810)
1 //
2 // Copyright © 2020 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #include "TestTimelinePacketHandler.hpp"
7 
8 #include <client/src/IProfilingConnection.hpp>
9 
10 #include <common/include/LabelsAndEventClasses.hpp>
11 
12 #include <chrono>
13 #include <iostream>
14 
15 namespace arm
16 {
17 
18 namespace pipe
19 {
20 
GetHeadersAccepted()21 std::vector<uint32_t> TestTimelinePacketHandler::GetHeadersAccepted()
22 {
23     std::vector<uint32_t> headers;
24     headers.push_back(m_DirectoryHeader); // message directory
25     headers.push_back(m_MessageHeader); // message
26     return headers;
27 }
28 
HandlePacket(const arm::pipe::Packet & packet)29 void TestTimelinePacketHandler::HandlePacket(const arm::pipe::Packet& packet)
30 {
31     if (packet.GetHeader() == m_DirectoryHeader)
32     {
33         ProcessDirectoryPacket(packet);
34     }
35     else if (packet.GetHeader() == m_MessageHeader)
36     {
37         ProcessMessagePacket(packet);
38     }
39     else
40     {
41         std::stringstream ss;
42         ss << "Received a packet with unknown header [" << packet.GetHeader() << "]";
43         throw arm::pipe::ProfilingException(ss.str());
44     }
45 }
46 
Stop()47 void TestTimelinePacketHandler::Stop()
48 {
49     m_Connection->Close();
50 }
51 
WaitOnInferenceCompletion(unsigned int timeout)52 void TestTimelinePacketHandler::WaitOnInferenceCompletion(unsigned int timeout)
53 {
54     std::unique_lock<std::mutex> lck(m_InferenceCompletedMutex);
55 
56     auto start = std::chrono::high_resolution_clock::now();
57     // Here we we will go back to sleep after a spurious wake up if
58     // m_InferenceCompleted is not yet true.
59     if (!m_InferenceCompletedConditionVariable.wait_for(lck,
60                                                         std::chrono::milliseconds(timeout),
61                                                         [&]{return m_InferenceCompleted == true;}))
62     {
63         auto finish = std::chrono::high_resolution_clock::now();
64         std::chrono::duration<double, std::milli> elapsed = finish - start;
65         std::stringstream ss;
66         ss << "Timed out waiting on inference completion for " << elapsed.count() << " ms";
67         throw arm::pipe::TimeoutException(ss.str());
68     }
69     return;
70 }
71 
SetInferenceComplete()72 void TestTimelinePacketHandler::SetInferenceComplete()
73 {
74     {   // only lock when we are updating the inference completed variable
75         std::unique_lock<std::mutex> lck(m_InferenceCompletedMutex);
76         m_InferenceCompleted = true;
77     }
78     m_InferenceCompletedConditionVariable.notify_one();
79 }
80 
ProcessDirectoryPacket(const arm::pipe::Packet & packet)81 void TestTimelinePacketHandler::ProcessDirectoryPacket(const arm::pipe::Packet& packet)
82 {
83     m_DirectoryDecoder(packet);
84 }
85 
ProcessMessagePacket(const arm::pipe::Packet & packet)86 void TestTimelinePacketHandler::ProcessMessagePacket(const arm::pipe::Packet& packet)
87 {
88     m_Decoder(packet);
89 }
90 
91 // TimelineMessageDecoder functions
CreateEntity(const Entity & entity)92 arm::pipe::ITimelineDecoder::TimelineStatus TimelineMessageDecoder::CreateEntity(const Entity& entity)
93 {
94     m_TimelineModel.AddEntity(entity.m_Guid);
95     return arm::pipe::ITimelineDecoder::TimelineStatus::TimelineStatus_Success;
96 }
97 
CreateEventClass(const arm::pipe::ITimelineDecoder::EventClass & eventClass)98 arm::pipe::ITimelineDecoder::TimelineStatus TimelineMessageDecoder::CreateEventClass(
99     const arm::pipe::ITimelineDecoder::EventClass& eventClass)
100 {
101     m_TimelineModel.AddEventClass(eventClass);
102     return arm::pipe::ITimelineDecoder::TimelineStatus::TimelineStatus_Success;
103 }
104 
CreateEvent(const arm::pipe::ITimelineDecoder::Event & event)105 arm::pipe::ITimelineDecoder::TimelineStatus TimelineMessageDecoder::CreateEvent(
106     const arm::pipe::ITimelineDecoder::Event& event)
107 {
108     m_TimelineModel.AddEvent(event);
109     return arm::pipe::ITimelineDecoder::TimelineStatus::TimelineStatus_Success;
110 }
111 
CreateLabel(const arm::pipe::ITimelineDecoder::Label & label)112 arm::pipe::ITimelineDecoder::TimelineStatus TimelineMessageDecoder::CreateLabel(
113     const arm::pipe::ITimelineDecoder::Label& label)
114 {
115     m_TimelineModel.AddLabel(label);
116     return arm::pipe::ITimelineDecoder::TimelineStatus::TimelineStatus_Success;
117 }
118 
CreateRelationship(const arm::pipe::ITimelineDecoder::Relationship & relationship)119 arm::pipe::ITimelineDecoder::TimelineStatus TimelineMessageDecoder::CreateRelationship(
120     const arm::pipe::ITimelineDecoder::Relationship& relationship)
121 {
122     m_TimelineModel.AddRelationship(relationship);
123     // check to see if this is an execution link to an inference of event class end of life
124     // if so the inference has completed so send out a notification...
125     if (relationship.m_RelationshipType == RelationshipType::ExecutionLink &&
126         m_TimelineModel.IsInferenceGuid(relationship.m_HeadGuid))
127     {
128         ProfilingStaticGuid attributeGuid(relationship.m_AttributeGuid);
129         if (attributeGuid == LabelsAndEventClasses::ARMNN_PROFILING_EOL_EVENT_CLASS)
130         {
131             if (m_PacketHandler != nullptr)
132             {
133                 m_PacketHandler->SetInferenceComplete();
134             }
135         }
136     }
137     return arm::pipe::ITimelineDecoder::TimelineStatus::TimelineStatus_Success;
138 }
139 
140 } // namespace pipe
141 
142 } // namespace arm
143