blob: 5ba1318a776563eda48f1b69d4dadda1c8f8a2a9 [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.
33 m_PeriodCaptureThread = std::thread(&PeriodicCounterCapture::Capture,
34 this,
35 std::ref(m_ReadCounterValues));
36}
37
38void PeriodicCounterCapture::Stop()
39{
Matteo Martincighe8485382019-10-10 14:08:21 +010040 // Signal the capture thread to stop
Matteo Martincighe0e6efc2019-10-04 17:17:42 +010041 m_KeepRunning.store(false);
42
Matteo Martincighe8485382019-10-10 14:08:21 +010043 // Check that the capture thread is running
Matteo Martincighe0e6efc2019-10-04 17:17:42 +010044 if (m_PeriodCaptureThread.joinable())
45 {
Matteo Martincighe8485382019-10-10 14:08:21 +010046 // Wait for the capture thread to complete operations
Matteo Martincighe0e6efc2019-10-04 17:17:42 +010047 m_PeriodCaptureThread.join();
48 }
Finn Williamsf4d59a62019-10-14 15:55:18 +010049
50 m_IsRunning = false;
Matteo Martincighe0e6efc2019-10-04 17:17:42 +010051}
Francis Murtaghfcb8ef62019-09-20 15:40:09 +010052
53CaptureData PeriodicCounterCapture::ReadCaptureData()
54{
55 return m_CaptureDataHolder.GetCaptureData();
56}
57
Matteo Martincighe0e6efc2019-10-04 17:17:42 +010058void PeriodicCounterCapture::Capture(const IReadCounterValues& readCounterValues)
Francis Murtaghfcb8ef62019-09-20 15:40:09 +010059{
Finn Williamsf4d59a62019-10-14 15:55:18 +010060 do
Francis Murtaghfcb8ef62019-09-20 15:40:09 +010061 {
Matteo Martincighe8485382019-10-10 14:08:21 +010062 // Check if the current capture data indicates that there's data capture
Francis Murtaghfcb8ef62019-09-20 15:40:09 +010063 auto currentCaptureData = ReadCaptureData();
Matteo Martincighe8485382019-10-10 14:08:21 +010064 const std::vector<uint16_t>& counterIds = currentCaptureData.GetCounterIds();
Finn Williamsf4d59a62019-10-14 15:55:18 +010065
Francis Murtaghfcb8ef62019-09-20 15:40:09 +010066 if (currentCaptureData.GetCapturePeriod() == 0 || counterIds.empty())
67 {
Finn Williamsf4d59a62019-10-14 15:55:18 +010068 // No data capture, wait the indicated capture period (milliseconds)
69 std::this_thread::sleep_for(std::chrono::milliseconds(5));
70 continue;
Francis Murtaghfcb8ef62019-09-20 15:40:09 +010071 }
Matteo Martincighe0e6efc2019-10-04 17:17:42 +010072
73 std::vector<std::pair<uint16_t, uint32_t>> values;
74 auto numCounters = counterIds.size();
75 values.reserve(numCounters);
76
Matteo Martincighe8485382019-10-10 14:08:21 +010077 // Create a vector of pairs of CounterIndexes and Values
Matteo Martincighe0e6efc2019-10-04 17:17:42 +010078 for (uint16_t index = 0; index < numCounters; ++index)
Francis Murtaghfcb8ef62019-09-20 15:40:09 +010079 {
Matteo Martincighe0e6efc2019-10-04 17:17:42 +010080 auto requestedId = counterIds[index];
Matteo Martincighe8485382019-10-10 14:08:21 +010081 uint32_t counterValue = 0;
82 try
83 {
84 counterValue = readCounterValues.GetCounterValue(requestedId);
85 }
86 catch (const Exception& e)
87 {
88 // Report the error and continue
89 BOOST_LOG_TRIVIAL(warning) << "An error has occurred when getting a counter value: "
90 << e.what() << std::endl;
91 continue;
92 }
Matteo Martincighe0e6efc2019-10-04 17:17:42 +010093 values.emplace_back(std::make_pair(requestedId, counterValue));
94 }
Francis Murtaghfcb8ef62019-09-20 15:40:09 +010095
Matteo Martincighe0e6efc2019-10-04 17:17:42 +010096 #if USE_CLOCK_MONOTONIC_RAW
97 using clock = MonotonicClockRaw;
98 #else
99 using clock = std::chrono::steady_clock;
100 #endif
Francis Murtaghfcb8ef62019-09-20 15:40:09 +0100101
Matteo Martincighe0e6efc2019-10-04 17:17:42 +0100102 // Take a timestamp
103 auto timestamp = clock::now();
Francis Murtaghfcb8ef62019-09-20 15:40:09 +0100104
Matteo Martincighe8485382019-10-10 14:08:21 +0100105 // Write a Periodic Counter Capture packet to the Counter Stream Buffer
Matteo Martincighe0e6efc2019-10-04 17:17:42 +0100106 m_SendCounterPacket.SendPeriodicCounterCapturePacket(
Francis Murtaghfcb8ef62019-09-20 15:40:09 +0100107 static_cast<uint64_t>(timestamp.time_since_epoch().count()), values);
Matteo Martincighe8485382019-10-10 14:08:21 +0100108
109 // Notify the Send Thread that new data is available in the Counter Stream Buffer
110 m_SendCounterPacket.SetReadyToRead();
111
112 // Wait the indicated capture period (microseconds)
113 std::this_thread::sleep_for(std::chrono::microseconds(currentCaptureData.GetCapturePeriod()));
Francis Murtaghfcb8ef62019-09-20 15:40:09 +0100114
Finn Williamsf4d59a62019-10-14 15:55:18 +0100115 }
116 while (m_KeepRunning.load());
117
Francis Murtaghfcb8ef62019-09-20 15:40:09 +0100118}
119
120} // namespace profiling
121
122} // namespace armnn