This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 468517561715390d352a165ad3cab915764efa8a
Author: yinshengkai <[email protected]>
AuthorDate: Wed Aug 7 21:46:39 2024 +0800

    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 <[email protected]>
---
 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 9eb2d266fd..fe7cd0008a 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 366f26d8dd..9e49af0e94 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 f61e9b783a..079af0c10c 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 c660a6238b..1044fbd2b7 100644
--- a/sched/sched/sched_cpuload.c
+++ b/sched/sched/sched_cpuload.c
@@ -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
diff --git a/sched/sched/sched_processtimer.c b/sched/sched/sched_processtimer.c
index 89d8aba4c0..0de54a4038 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 8779f03311..bfa12099fe 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.
    */

Reply via email to