Skip to content

Commit 3886abc

Browse files
committed
Improve accuracy
1 parent 0a34caf commit 3886abc

2 files changed

Lines changed: 23 additions & 7 deletions

File tree

include/f_core/os/tenants/c_cpu_monitor_tenant.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@ class CCpuMonitorTenant : public CTenant {
2828

2929
private:
3030
CMessagePort<CpuMonitorData>& outputPort;
31-
uint64_t prevExecutionCycles = 0;
32-
uint64_t prevTotalCycles = 0;
31+
uint64_t prevExecutionCycles = 0; // All cycles (active + idle) - Based on Zephyr naming
32+
uint64_t prevTotalCycles = 0; // Active cycles only - Based on Zephyr naming
33+
uint32_t prevUptime = 0;
3334

3435
#if DT_NODE_EXISTS(DT_ALIAS(die_temp))
3536
const device *dieTempSensor = DEVICE_DT_GET(DT_ALIAS(die_temp));

lib/f_core/os/tenants/c_cpu_monitor_tenant.cpp

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ void CCpuMonitorTenant::Startup() {
1212

1313
prevExecutionCycles = stats.execution_cycles;
1414
prevTotalCycles = stats.total_cycles;
15+
prevUptime = k_uptime_get_32();
1516
}
1617

1718
void CCpuMonitorTenant::PostStartup() {
@@ -55,17 +56,31 @@ uint32_t CCpuMonitorTenant::getUptime() {
5556
uint8_t CCpuMonitorTenant::getUtilization() {
5657
k_thread_runtime_stats stats{0};
5758
k_thread_runtime_stats_all_get(&stats);
59+
uint32_t currentUptime = k_uptime_get_32();
5860

59-
uint64_t deltaExecution = stats.execution_cycles - prevExecutionCycles;
60-
uint64_t deltaTotal = stats.total_cycles - prevTotalCycles;
61+
// Zephyr's naming is confusing! Based on kernel/thread.h comments:
62+
// execution_cycles = total # of cycles (cpu: non-idle + idle) = ALL cycles
63+
// total_cycles = total # of non-idle cycles = ACTIVE/BUSY cycles only
64+
uint64_t deltaAllCycles = stats.execution_cycles - prevExecutionCycles; // All cycles (active + idle)
65+
uint64_t deltaActiveCycles = stats.total_cycles - prevTotalCycles; // Active cycles only
66+
uint32_t deltaTime = currentUptime - prevUptime;
6167

6268
prevExecutionCycles = stats.execution_cycles;
6369
prevTotalCycles = stats.total_cycles;
70+
prevUptime = currentUptime;
6471

65-
if (deltaExecution == 0) {
72+
if (deltaAllCycles == 0 || deltaTime == 0) {
6673
return 0; // Avoid division by zero
6774
}
6875

69-
// Utilization is the percentage of non-idle cycles in the interval
70-
return static_cast<uint8_t>((deltaTotal * 100) / deltaExecution);
76+
if (deltaTime < 10) {
77+
LOG_WRN_ONCE("CPU utilization measurement interval too short for accuracy");
78+
}
79+
80+
// CPU Utilization = (Active cycles / All cycles) × 100
81+
// gives the percentage of time the CPU is NOT idle
82+
uint64_t utilization = (deltaActiveCycles * 100) / deltaAllCycles;
83+
84+
// Clamp to 100% in case of any edge cases
85+
return static_cast<uint8_t>(utilization > 100 ? 100 : utilization);
7186
}

0 commit comments

Comments
 (0)