sched: fix the inaccurate cpuload statistics issue

Non-fixed clock source will lead to inaccurate cpuload statistics

before:
5     5 253 RR       Task      - Waiting  Signal    0000000000000000 0002000 0000624  31.2%   2.5% cpuload -p 50
6     6 253 RR       Task      - Waiting  Signal    0000000000000000 0002000 0000624  31.2%   0.7% cpuload -p 10
7     7 253 RR       Task      - Waiting  Signal    0000000000000000 0002000 0000624  31.2%   2.2% cpuload -p 20
after:
5     5 253 RR       Task      - Waiting  Signal    0000000000000000 0002000 0000624  31.2%  50.8% cpuload -p 50
6     6 253 RR       Task      - Waiting  Signal    0000000000000000 0002000 0000624  31.2%  10.8% cpuload -p 10
7     7 253 RR       Task      - Waiting  Signal    0000000000000000 0002000 0000624  31.2%  20.0% cpuload -p 20
Signed-off-by: yinshengkai <yinshengkai@xiaomi.com>
This commit is contained in:
yinshengkai 2024-08-07 21:46:39 +08:00 committed by Xiang Xiao
parent f88afa5825
commit 4685175617
6 changed files with 71 additions and 24 deletions

View file

@ -1027,7 +1027,6 @@ config SCHED_CPULOAD_NONE
config SCHED_CPULOAD_SYSCLK
bool "Use system clock"
depends on !SCHED_TICKLESS
---help---
If this option is enabled, the system clock is used for cpu load
measurement by default.
@ -1077,19 +1076,18 @@ config SCHED_CPULOAD_CRITMONITOR
endchoice
if SCHED_CPULOAD_EXTCLK
config SCHED_CPULOAD_TICKSPERSEC
int "External clock rate"
int "CPU load sampling clock frequency(HZ)"
default 100
---help---
If an external clock is used to drive the sampling for the CPU load
calculations, then this value must be provided. This value provides
the rate of the external clock interrupts in units of ticks per
second. The default value of 100 corresponds to a 100Hz clock. NOTE:
CPU load sampling clock frequency, in HZ. Use sysclk clock source,
use wdt, EXTCLK clock source, use an external timer.
The default value of 100 corresponds to a 100Hz clock. NOTE:
that 100Hz is the default frequency of the system time and, hence,
the worst possible choice in most cases.
if SCHED_CPULOAD_EXTCLK
choice
prompt "Select CPU load timer"
default CPULOAD_ONESHOT

View file

@ -87,4 +87,8 @@ void clock_timer(void);
void perf_init(void);
#ifdef CONFIG_SCHED_CPULOAD_SYSCLK
void cpuload_init(void);
#endif
#endif /* __SCHED_CLOCK_CLOCK_H */

View file

@ -231,6 +231,10 @@ void clock_initialize(void)
perf_init();
#ifdef CONFIG_SCHED_CPULOAD_SYSCLK
cpuload_init();
#endif
sched_trace_end();
}

View file

@ -31,6 +31,7 @@
#include <nuttx/clock.h>
#include <nuttx/irq.h>
#include <nuttx/wdog.h>
#include "sched/sched.h"
@ -61,6 +62,11 @@
CONFIG_SCHED_CPULOAD_TIMECONSTANT * \
CPULOAD_TICKSPERSEC)
/* The sampling period in system timer ticks */
#define CPULOAD_SAMPLING_PERIOD \
(TICK_PER_SEC / CONFIG_SCHED_CPULOAD_TICKSPERSEC)
/****************************************************************************
* Public Data
****************************************************************************/
@ -80,6 +86,34 @@
volatile clock_t g_cpuload_total;
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: cpuload_callback
*
* Description:
* This is the callback function that will be invoked when the watchdog
* timer expires.
*
* Input Parameters:
* argc - the argument passed with the timer when the timer was started.
*
* Returned Value:
* None
*
****************************************************************************/
#ifdef CONFIG_SCHED_CPULOAD_SYSCLK
static void cpuload_callback(wdparm_t arg)
{
FAR struct wdog_s *wdog = (FAR struct wdog_s *)arg;
nxsched_process_cpuload_ticks(CPULOAD_SAMPLING_PERIOD);
wd_start(wdog, CPULOAD_SAMPLING_PERIOD, cpuload_callback, arg);
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -221,3 +255,26 @@ int clock_cpuload(int pid, FAR struct cpuload_s *cpuload)
leave_critical_section(flags);
return ret;
}
/****************************************************************************
* Name: cpuload_init
*
* Description:
* Initialize the CPU load measurement logic.
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
#ifdef CONFIG_SCHED_CPULOAD_SYSCLK
void cpuload_init(void)
{
static struct wdog_s g_cpuload_wdog;
wd_start(&g_cpuload_wdog, CPULOAD_SAMPLING_PERIOD, cpuload_callback,
(wdparm_t)&g_cpuload_wdog);
}
#endif

View file

@ -182,14 +182,6 @@ void nxsched_process_timer(void)
clock_timer();
#ifdef CONFIG_SCHED_CPULOAD_SYSCLK
/* Perform CPU load measurements (before any timer-initiated context
* switches can occur)
*/
nxsched_process_cpuload();
#endif
/* Check if the currently executing task has exceeded its
* timeslice.
*/

View file

@ -339,14 +339,6 @@ static clock_t nxsched_timer_process(clock_t ticks, clock_t elapsed,
clock_update_wall_time();
#endif
#ifdef CONFIG_SCHED_CPULOAD_SYSCLK
/* Perform CPU load measurements (before any timer-initiated context
* switches can occur)
*/
nxsched_process_cpuload_ticks(elapsed);
#endif
/* Check for operations specific to scheduling policy of the currently
* active task.
*/