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()21std::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)29void 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()47void TestTimelinePacketHandler::Stop() 48 { 49 m_Connection->Close(); 50 } 51 WaitOnInferenceCompletion(unsigned int timeout)52void 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()72void 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)81void TestTimelinePacketHandler::ProcessDirectoryPacket(const arm::pipe::Packet& packet) 82 { 83 m_DirectoryDecoder(packet); 84 } 85 ProcessMessagePacket(const arm::pipe::Packet & packet)86void TestTimelinePacketHandler::ProcessMessagePacket(const arm::pipe::Packet& packet) 87 { 88 m_Decoder(packet); 89 } 90 91 // TimelineMessageDecoder functions CreateEntity(const Entity & entity)92arm::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)98arm::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)105arm::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)112arm::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)119arm::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