36#ifdef OPENMRN_FEATURE_THREAD_FREERTOS
38#ifndef _OS_CPULOAD_HXX_
39#define _OS_CPULOAD_HXX_
47#include "freertos_includes.h"
54 void cpuload_tick(
unsigned irq);
68class CpuLoad :
public Singleton<CpuLoad> {
74 while (!perKeyCost_.empty())
76 delete perKeyCost_.pop_front();
86 uint8_t get_max_consecutive() {
87 return maxConsecutive_;
91 void clear_max_consecutive() {
96 uint8_t get_peak_over_16_counts() {
97 return peakOver16Counts_;
101 void clear_peak_over_16_counts() {
102 peakOver16Counts_ = 0;
115 void set_key_description(uintptr_t key,
string description)
117 auto it = perKeyCost_.begin();
118 for (; it != perKeyCost_.end(); ++it)
122 it->description = std::move(description);
126 auto *kk =
new KeyInfo;
128 kk->description = std::move(description);
129 perKeyCost_.insert(it, kk);
135 uint32_t get_utilization_delta(
136 std::vector<pair<unsigned, string *>> *output)
140 for (
auto it = perKeyCost_.begin(); it != perKeyCost_.end(); ++it)
142 volatile unsigned curr = it->rolling_count;
143 unsigned diff = curr - it->last_count;
144 it->last_count = curr;
147 output->emplace_back(diff, &it->description);
150 uint32_t ret = countSinceUpdate_;
151 countSinceUpdate_ = 0;
156 friend void cpuload_tick(
unsigned);
161 inline void record_value(
bool busy, uintptr_t key);
169 uint32_t countSinceUpdate_{0};
172 uintptr_t newKey_{0};
174 struct KeyInfo :
public QMember
181 uint32_t last_count{0};
183 uint32_t rolling_count{0};
190 uint8_t consecutive_{0};
192 uint8_t maxConsecutive_{0};
194 uint16_t last16Bits_{0};
196 uint8_t peakOver16Counts_{0};
209 Action log_and_wait()
211 auto *l = CpuLoad::instance();
214 "Ex %d|FreeHeap %d|Buf %d|Load: avg %3d max streak %d max of 16 %d",
217 l->get_max_consecutive(), l->get_peak_over_16_counts());
218 executorLastCount_ = ex_count;
219 l->clear_max_consecutive();
220 l->clear_peak_over_16_counts();
221 vector<pair<unsigned, string *>> per_task_ticks;
222 unsigned c = l->get_utilization_delta(&per_task_ticks);
223 std::sort(per_task_ticks.begin(), per_task_ticks.end(),
224 std::greater<
decltype(per_task_ticks)::value_type>());
226 for (
volatile auto it : per_task_ticks)
228 int perc = it.first * 1000 / c;
229 details += StringPrintf(
" | %d.%d:", perc / 10, perc % 10);
230 details += *it.second;
232 log_output((
char *)details.data(), details.size());
233 auto k = l->new_key();
236 l->set_key_description(k, StringPrintf(
"irq-%u", (
unsigned)k));
240 l->set_key_description(
241 k, StringPrintf(
"ex 0x%x", (
unsigned)(k & ~1)));
245#if tskKERNEL_VERSION_MAJOR < 9
246 char *name = pcTaskGetTaskName((TaskHandle_t)k);
248 char *name = pcTaskGetName((TaskHandle_t)k);
250 l->set_key_description(k, name);
255 uint32_t executorLastCount_{0};
256 StateFlowTimer timer_{
this};
DynamicPool * mainBufferPool
main buffer pool instance
#define STATE(_fn)
Turns a function name into an argument to be supplied to functions expecting a state.
virtual uint32_t sequence()=0
Essentially a "next" pointer container.
Collection of related state machines that pend on incoming messages.
ExecutorBase * executor()
Base class for state machines.
Service * service()
Return a pointer to the service I am bound to.
void start_flow(Callback c)
Resets the flow to the specified state and starts it.
Action sleep_and_call(::Timer *timer, long long timeout_nsec, Callback c)
Suspends execution of this control flow for a specified time.
A simple, fast, type-safe single-linked queue class with non-virtual methods.
void log_output(char *buf, int size)
Prints a line of log to the log output destination.
#define LOG(level, message...)
Conditionally write a message to the logging output.
static const int INFO
Loglevel that is printed by default, reporting some status information.
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
ssize_t os_get_free_heap()
#define MSEC_TO_NSEC(_msec)
Convert a millisecond value to a nanosecond value.