blob: f888bc045e16e4be15fef017a65281a0be58fe61 [file] [log] [blame]
Francis Murtaghfcb8ef62019-09-20 15:40:09 +01001//
2// Copyright © 2019 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#include "PeriodicCounterCapture.hpp"
7
Matteo Martincighe8485382019-10-10 14:08:21 +01008#include <boost/log/trivial.hpp>
Finn Williamsf4d59a62019-10-14 15:55:18 +01009#include <iostream>
Matteo Martincighe8485382019-10-10 14:08:21 +010010
Francis Murtaghfcb8ef62019-09-20 15:40:09 +010011namespace armnn
12{
13
14namespace profiling
15{
16
Matteo Martincighe0e6efc2019-10-04 17:17:42 +010017void PeriodicCounterCapture::Start()
18{
19 // Check if the capture thread is already running
Finn Williamsf4d59a62019-10-14 15:55:18 +010020 if (m_IsRunning)
Matteo Martincighe0e6efc2019-10-04 17:17:42 +010021 {
22 // The capture thread is already running
23 return;
24 }
25
26 // Mark the capture thread as running
Finn Williamsf4d59a62019-10-14 15:55:18 +010027 m_IsRunning = true;
Matteo Martincighe0e6efc2019-10-04 17:17:42 +010028
29 // Keep the capture procedure going until the capture thread is signalled to stop
30 m_KeepRunning.store(true);
31
32 // Start the new capture thread.
Matteo Martincigh8d9590e2019-10-15 09:35:29 +010033 m_PeriodCaptureThread = std::thread(&PeriodicCounterCapture::Capture, this, std::ref(m_ReadCounterValues));
Matteo Martincighe0e6efc2019-10-04 17:17:42 +010034}
35
36void PeriodicCounterCapture::Stop()
37{
Matteo Martincighe8485382019-10-10 14:08:21 +010038 // Signal the capture thread to stop
Matteo Martincighe0e6efc2019-10-04 17:17:42 +010039 m_KeepRunning.store(false);
40
Matteo Martincighe8485382019-10-10 14:08:21 +010041 // Check that the capture thread is running
Matteo Martincighe0e6efc2019-10-04 17:17:42 +010042 if (m_PeriodCaptureThread.joinable())
43 {
Matteo Martincighe8485382019-10-10 14:08:21 +010044 // Wait for the capture thread to complete operations
Matteo Martincighe0e6efc2019-10-04 17:17:42 +010045 m_PeriodCaptureThread.join();
46 }
Finn Williamsf4d59a62019-10-14 15:55:18 +010047
Matteo Martincigh8d9590e2019-10-15 09:35:29 +010048 // Mark the capture thread as not running
Finn Williamsf4d59a62019-10-14 15:55:18 +010049 m_IsRunning = false;
Matteo Martincighe0e6efc2019-10-04 17:17:42 +010050}
Francis Murtaghfcb8ef62019-09-20 15:40:09 +010051
52CaptureData PeriodicCounterCapture::ReadCaptureData()
53{
54 return m_CaptureDataHolder.GetCaptureData();
55}
56
Matteo Martincighe0e6efc2019-10-04 17:17:42 +010057void PeriodicCounterCapture::Capture(const IReadCounterValues& readCounterValues)
Francis Murtaghfcb8ef62019-09-20 15:40:09 +010058{
Finn Williamsf4d59a62019-10-14 15:55:18 +010059 do
Francis Murtaghfcb8ef62019-09-20 15:40:09 +010060 {
Matteo Martincighe8485382019-10-10 14:08:21 +010061 // Check if the current capture data indicates that there's data capture
Francis Murtaghfcb8ef62019-09-20 15:40:09 +010062 auto currentCaptureData = ReadCaptureData();
Matteo Martincighe8485382019-10-10 14:08:21 +010063 const std::vector<uint16_t>& counterIds = currentCaptureData.GetCounterIds();
Finn Williamsf4d59a62019-10-14 15:55:18 +010064
Francis Murtaghfcb8ef62019-09-20 15:40:09 +010065 if (currentCaptureData.GetCapturePeriod() == 0 || counterIds.empty())
66 {
Finn Williamsf4d59a62019-10-14 15:55:18 +010067 // No data capture, wait the indicated capture period (milliseconds)
68 std::this_thread::sleep_for(std::chrono::milliseconds(5));
69 continue;
Francis Murtaghfcb8ef62019-09-20 15:40:09 +010070 }
Matteo Martincighe0e6efc2019-10-04 17:17:42 +010071
72 std::vector<std::pair<uint16_t, uint32_t>> values;
73 auto numCounters = counterIds.size();
74 values.reserve(numCounters);
75
Matteo Martincighe8485382019-10-10 14:08:21 +010076 // Create a vector of pairs of CounterIndexes and Values
Matteo Martincighe0e6efc2019-10-04 17:17:42 +010077 for (uint16_t index = 0; index < numCounters; ++index)
Francis Murtaghfcb8ef62019-09-20 15:40:09 +010078 {
Matteo Martincighe0e6efc2019-10-04 17:17:42 +010079 auto requestedId = counterIds[index];
Matteo Martincighe8485382019-10-10 14:08:21 +010080 uint32_t counterValue = 0;
81 try
82 {
83 counterValue = readCounterValues.GetCounterValue(requestedId);
84 }
85 catch (const Exception& e)
86 {
87 // Report the error and continue
88 BOOST_LOG_TRIVIAL(warning) << "An error has occurred when getting a counter value: "
89 << e.what() << std::endl;
90 continue;
91 }
Matteo Martincighe0e6efc2019-10-04 17:17:42 +010092 values.emplace_back(std::make_pair(requestedId, counterValue));
93 }
Francis Murtaghfcb8ef62019-09-20 15:40:09 +010094
Matteo Martincighe0e6efc2019-10-04 17:17:42 +010095 #if USE_CLOCK_MONOTONIC_RAW
96 using clock = MonotonicClockRaw;
97 #else
98 using clock = std::chrono::steady_clock;
99 #endif
Francis Murtaghfcb8ef62019-09-20 15:40:09 +0100100
Matteo Martincighe0e6efc2019-10-04 17:17:42 +0100101 // Take a timestamp
102 auto timestamp = clock::now();
Francis Murtaghfcb8ef62019-09-20 15:40:09 +0100103
Matteo Martincighe8485382019-10-10 14:08:21 +0100104 // Write a Periodic Counter Capture packet to the Counter Stream Buffer
Matteo Martincighe0e6efc2019-10-04 17:17:42 +0100105 m_SendCounterPacket.SendPeriodicCounterCapturePacket(
Francis Murtaghfcb8ef62019-09-20 15:40:09 +0100106 static_cast<uint64_t>(timestamp.time_since_epoch().count()), values);
Matteo Martincighe8485382019-10-10 14:08:21 +0100107
108 // Notify the Send Thread that new data is available in the Counter Stream Buffer
109 m_SendCounterPacket.SetReadyToRead();
110
111 // Wait the indicated capture period (microseconds)
112 std::this_thread::sleep_for(std::chrono::microseconds(currentCaptureData.GetCapturePeriod()));
Francis Murtaghfcb8ef62019-09-20 15:40:09 +0100113
Finn Williamsf4d59a62019-10-14 15:55:18 +0100114 }
115 while (m_KeepRunning.load());
Francis Murtaghfcb8ef62019-09-20 15:40:09 +0100116}
117
118} // namespace profiling
119
120} // namespace armnn