Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
CpuLoad.cxx
1
35#include "CpuLoad.hxx"
36
37#ifdef OPENMRN_FEATURE_THREAD_FREERTOS
38
39#include "os/os.h"
40#include "freertos_includes.h"
41
42#ifdef ESP32
43#include "sdkconfig.h"
44#endif // ESP32
45
46extern "C"
47{
48
50static constexpr uint32_t SHIFT_ONE = 24;
51
53static constexpr uint32_t SHIFT_RATE = 8;
55static constexpr uint8_t AVG_RATE = 0xff;
57static constexpr uint32_t ADD_RATE = 0x1 << 24;
58
59void CpuLoad::record_value(bool busy, uintptr_t key)
60{
61 avg_ *= AVG_RATE;
62 ++countSinceUpdate_;
63 if (busy)
64 {
65 avg_ += ADD_RATE;
66 }
67 avg_ >>= SHIFT_RATE;
68 // Check streak
69 if (busy)
70 {
71 if (consecutive_ < 255)
72 {
73 ++consecutive_;
74 }
75 if (consecutive_ > maxConsecutive_)
76 {
77 maxConsecutive_ = consecutive_;
78 }
79 }
80 else
81 {
82 consecutive_ = 0;
83 }
84 // Check window of 16.
85 last16Bits_ <<= 1;
86 last16Bits_ |= (busy ? 1 : 0);
87 // sums up last 16 bits.
88 unsigned v = last16Bits_;
89 v = (v & 0x5555) + ((v & 0xaaaa) >> 1);
90 v = (v & 0x3333) + ((v & 0xcccc) >> 2);
91 v = (v & 0x0F0F) + ((v & 0xF0F0) >> 4);
92 v = (v & 0x00FF) + ((v & 0xFF00) >> 8);
93 if (v > peakOver16Counts_)
94 {
95 peakOver16Counts_ = v;
96 }
97 // Record per-key information
98 if (key == 0)
99 return;
100 bool found = false;
101 for (auto it = perKeyCost_.begin(); it != perKeyCost_.end(); ++it)
102 {
103 if (it->key == key)
104 {
105 found = true;
106 ++it->rolling_count;
107 break;
108 }
109 }
110 if (!found && newKey_ == 0)
111 {
112 newKey_ = key;
113 }
114}
115
116uint8_t CpuLoad::get_load() {
117 return (avg_ * 100) >> SHIFT_ONE;
118}
119
120void cpuload_tick(unsigned irq)
121{
123 return;
124// On the ESP32 it is necessary to use a slightly different approach for
125// recording CPU usage metrics since there may be additional CPU cores.
126#ifdef ESP32
127 if (irq != 0)
128 {
129 Singleton<CpuLoad>::instance()->record_value(true, (uintptr_t)irq);
130 }
131 else
132 {
133 // Record the first CPU core (PRO_CPU). NOTE: This assumes that OpenMRN
134 // is running on this core.
135 auto hdl = xTaskGetCurrentTaskHandleForCPU(PRO_CPU_NUM);
136 bool is_idle = xTaskGetIdleTaskHandleForCPU(PRO_CPU_NUM) == hdl;
137 Singleton<CpuLoad>::instance()->record_value(!is_idle, (uintptr_t)hdl);
138 }
139// NOTE: The ESP32-S2 and ESP32-C3 are single-core SoC and defines the
140// FREERTOS_UNICORE flag which we can use here to disable recording of the
141// APP_CPU.
142#ifndef CONFIG_FREERTOS_UNICORE
143 // Record the second CPU core (APP_CPU). NOTE: this is where application
144 // code typically runs.
145 auto hdl = xTaskGetCurrentTaskHandleForCPU(APP_CPU_NUM);
146 bool is_idle = xTaskGetIdleTaskHandleForCPU(APP_CPU_NUM) == hdl;
147 Singleton<CpuLoad>::instance()->record_value(!is_idle, (uintptr_t)hdl);
148#endif // CONFIG_FREERTOS_UNICORE
149#else // NOT ESP32
150 if (irq != 0)
151 {
152 Singleton<CpuLoad>::instance()->record_value(true, (uintptr_t)irq);
153 return;
154 }
155 auto hdl = xTaskGetCurrentTaskHandle();
156 bool is_idle = xTaskGetIdleTaskHandle() == hdl;
157 Singleton<CpuLoad>::instance()->record_value(!is_idle, (uintptr_t)hdl);
158#endif // ESP32
159}
160} // extern "C"
161
163
164#endif // OPENMRN_FEATURE_THREAD_FREERTOS
#define DEFINE_SINGLETON_INSTANCE(T)
Helper macro the the customer may (but is not required to) use for ensuring that the singleton instan...
Definition Singleton.hxx:98
Singleton class.
Definition Singleton.hxx:65
static T * instance()
Definition Singleton.hxx:77