From 468517561715390d352a165ad3cab915764efa8a Mon Sep 17 00:00:00 2001 From: yinshengkai Date: Wed, 7 Aug 2024 21:46:39 +0800 Subject: [PATCH] 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 --- sched/Kconfig | 14 +++---- sched/clock/clock.h | 4 ++ sched/clock/clock_initialize.c | 4 ++ sched/sched/sched_cpuload.c | 57 +++++++++++++++++++++++++++++ sched/sched/sched_processtimer.c | 8 ---- sched/sched/sched_timerexpiration.c | 8 ---- 6 files changed, 71 insertions(+), 24 deletions(-) diff --git a/sched/Kconfig b/sched/Kconfig index 9eb2d266fd212..fe7cd0008af4b 100644 --- a/sched/Kconfig +++ b/sched/Kconfig @@ -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 diff --git a/sched/clock/clock.h b/sched/clock/clock.h index 366f26d8ddc86..9e49af0e9497a 100644 --- a/sched/clock/clock.h +++ b/sched/clock/clock.h @@ -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 */ diff --git a/sched/clock/clock_initialize.c b/sched/clock/clock_initialize.c index f61e9b783a227..079af0c10c82a 100644 --- a/sched/clock/clock_initialize.c +++ b/sched/clock/clock_initialize.c @@ -231,6 +231,10 @@ void clock_initialize(void) perf_init(); +#ifdef CONFIG_SCHED_CPULOAD_SYSCLK + cpuload_init(); +#endif + sched_trace_end(); } diff --git a/sched/sched/sched_cpuload.c b/sched/sched/sched_cpuload.c index c660a6238b2eb..1044fbd2b7321 100644 --- a/sched/sched/sched_cpuload.c +++ b/sched/sched/sched_cpuload.c @@ -31,6 +31,7 @@ #include #include +#include #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 diff --git a/sched/sched/sched_processtimer.c b/sched/sched/sched_processtimer.c index 89d8aba4c0705..0de54a4038ff9 100644 --- a/sched/sched/sched_processtimer.c +++ b/sched/sched/sched_processtimer.c @@ -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. */ diff --git a/sched/sched/sched_timerexpiration.c b/sched/sched/sched_timerexpiration.c index 8779f033110b9..bfa12099fe0c1 100644 --- a/sched/sched/sched_timerexpiration.c +++ b/sched/sched/sched_timerexpiration.c @@ -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. */