aboutsummaryrefslogtreecommitdiff
path: root/src/profiling/PeriodicCounterCapture.cpp
blob: 5fbaa5d035bce1249c43de43cf7385e8a6158213 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
//
// Copyright © 2019 Arm Ltd. All rights reserved.
// SPDX-License-Identifier: MIT
//

#include "PeriodicCounterCapture.hpp"

namespace armnn
{

namespace profiling
{

PeriodicCounterCapture::PeriodicCounterCapture(const Holder& data, ISendCounterPacket& packet,
                                               const IReadCounterValue& readCounterValue)
    : m_CaptureDataHolder(data)
    , m_IsRunning(false)
    , m_ReadCounterValue(readCounterValue)
    , m_SendCounterPacket(packet)
{}

CaptureData PeriodicCounterCapture::ReadCaptureData()
{
    return m_CaptureDataHolder.GetCaptureData();
}

void PeriodicCounterCapture::Functionality(const IReadCounterValue& readCounterValue)
{
    bool threadRunning = true;

    while(threadRunning)
    {
        auto currentCaptureData = ReadCaptureData();
        std::vector<uint16_t> counterIds = currentCaptureData.GetCounterIds();
        if (currentCaptureData.GetCapturePeriod() == 0 || counterIds.empty())
        {
            threadRunning = false;
            m_IsRunning.store(false, std::memory_order_relaxed);
        }
        else
        {
            std::vector<std::pair<uint16_t, uint32_t>> values;
            auto numCounters = counterIds.size();
            values.reserve(numCounters);

            // Create vector of pairs of CounterIndexes and Values
            uint32_t counterValue;
            for (uint16_t index = 0; index < numCounters; ++index)
            {
                auto requestedId = counterIds[index];
                readCounterValue.GetCounterValue(requestedId, counterValue);
                values.emplace_back(std::make_pair(requestedId, counterValue));
            }

            #if USE_CLOCK_MONOTONIC_RAW
                using clock = MonotonicClockRaw;
            #else
                using clock = std::chrono::steady_clock;
            #endif
            // Take a timestamp
            auto timestamp = clock::now();

            m_SendCounterPacket.SendPeriodicCounterCapturePacket(
                    static_cast<uint64_t>(timestamp.time_since_epoch().count()), values);
            std::this_thread::sleep_for(std::chrono::milliseconds(currentCaptureData.GetCapturePeriod()));
        }
    }
}

void PeriodicCounterCapture::Start()
{
    bool tstVal = false;

    if (m_IsRunning.compare_exchange_strong(tstVal, true, std::memory_order_relaxed))
    {
        // Check that the thread execution is finished.
        if (m_PeriodCaptureThread.joinable())
        {
            m_PeriodCaptureThread.join();
        }
        // Starts the new thread.
        m_PeriodCaptureThread = std::thread(&PeriodicCounterCapture::Functionality, this,
                                            std::ref(m_ReadCounterValue));
    }
}

void PeriodicCounterCapture::Join()
{
    m_PeriodCaptureThread.join();
}

} // namespace profiling

} // namespace armnn