summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-02-27 14:13:53 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-02-27 14:13:53 -0600
commit4253771d12771c6beb157d4ebc530931d489eae8 (patch)
treed1ef697901e4090b9e80084c59f804faa549e53c
parentb663158cea2f68ed101f569a7fe08ddf7a7dfa32 (diff)
downloadnuttx-4253771d12771c6beb157d4ebc530931d489eae8.tar.gz
nuttx-4253771d12771c6beb157d4ebc530931d489eae8.tar.bz2
nuttx-4253771d12771c6beb157d4ebc530931d489eae8.zip
Support an asynchronous, 'external' clock to get better CPU load measurements
-rw-r--r--nuttx/ChangeLog4
-rw-r--r--nuttx/sched/Kconfig41
-rw-r--r--nuttx/sched/sched_cpuload.c16
-rw-r--r--nuttx/sched/sched_processtimer.c4
4 files changed, 60 insertions, 5 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index 400173b4e..d71a05a1e 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -6680,3 +6680,7 @@
* fs/procfs/fs_procfscpuload.c and fs_procfsproc.c: Remove the newline
at the end of the percentage so that the returned strings can be
printed on the same line as other values (2014-2-27).
+ * sched/Kconfig, sched_cpuload.c, and nuttx/sched/sched_processtimer.c:
+ An asynchronous, "external" clock may now be used to drive the CPU
+ load calculations for more accurate load measurements when needed
+ (2014-2-27).
diff --git a/nuttx/sched/Kconfig b/nuttx/sched/Kconfig
index a6b661e05..cd6b200e7 100644
--- a/nuttx/sched/Kconfig
+++ b/nuttx/sched/Kconfig
@@ -75,12 +75,51 @@ config SCHED_CPULOAD
if SCHED_CPULOAD
+config SCHED_CPULOAD_EXTCLK
+ bool "Use external clock"
+ default n
+ ---help---
+ The CPU load measurements are determined by sampling the active
+ tasks periodically at the occurrence to a timer expiration. By
+ default, the system clock is used to do that sampling.
+
+ There is a serious issue for the accuracy of measurements if the
+ system clock is used, however. NuttX threads are often started at
+ the time of the system timer expiration. Others may be stopped at
+ the time of the system timer expiration (if round-robin time-slicing
+ is enabled). Such thread behavior occurs synchronously with the
+ system timer and, hence, is not randomly sampled. As a consequence,
+ the CPU load attributed to these threads that run synchronously with
+ they system timer may be grossly in error.
+
+ The solution is to use some other clock that runs at a different
+ rate and has timer expirations that are asynchronous with the
+ system timer. Then truly accurate load measurements can be
+ achieved. This option enables use of such an "external" clock. The
+ implementation of the clock must be provided by platform-specific
+ logic; that platform-specific logic must call the system function
+ sched_process_cpuload() at each timer expiration with interrupts
+ disabled.
+
+config SCHED_CPULOAD_TICKSPERSEC
+ int "External clock rate"
+ default 100
+ depends on SCHED_CPULOAD_EXTCLK
+ ---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 in units of ticks per second. The
+ default value of 100 corresponds to 100Hz clock. NOTE: that 100Hz
+ is the default frequency of the system time and, hence, the worst
+ possible choice in most cases.
+
config SCHED_CPULOAD_TIMECONSTANT
int "CPU load time constant"
default 2
---help---
The accumulated CPU count is divided by two when the accumulated
- tick count exceeds this time constant.
+ tick count exceeds this time constant. This time constant is in
+ units of seconds.
endif # SCHED_CPULOAD
diff --git a/nuttx/sched/sched_cpuload.c b/nuttx/sched/sched_cpuload.c
index 0f5495750..95a8b59e2 100644
--- a/nuttx/sched/sched_cpuload.c
+++ b/nuttx/sched/sched_cpuload.c
@@ -52,7 +52,19 @@
/************************************************************************
* Pre-processor Definitions
************************************************************************/
-
+/* Are we using the system timer, or an external clock? Get the rate
+ * of the sampling in ticks per second for the selected timer.
+ */
+
+#ifdef CONFIG_SCHED_CPULOAD_EXTCLK
+# ifndef CONFIG_SCHED_CPULOAD_TICKSPERSEC
+# error CONFIG_SCHED_CPULOAD_TICKSPERSEC is not defined
+# endif
+# define CPULOAD_TICKSPERSEC CONFIG_SCHED_CPULOAD_TICKSPERSEC
+#else
+# define CPULOAD_TICKSPERSEC CLOCKS_PER_SEC
+#endif
+
/************************************************************************
* Private Type Declarations
************************************************************************/
@@ -119,7 +131,7 @@ void weak_function sched_process_cpuload(void)
* constant, then shift the accumulators.
*/
- if (++g_cpuload_total > (CONFIG_SCHED_CPULOAD_TIMECONSTANT * CLOCKS_PER_SEC))
+ if (++g_cpuload_total > (CONFIG_SCHED_CPULOAD_TIMECONSTANT * CPULOAD_TICKSPERSEC))
{
uint32_t total = 0;
diff --git a/nuttx/sched/sched_processtimer.c b/nuttx/sched/sched_processtimer.c
index d65112948..6ca5981fb 100644
--- a/nuttx/sched/sched_processtimer.c
+++ b/nuttx/sched/sched_processtimer.c
@@ -182,9 +182,9 @@ static inline void sched_process_timeslice(void)
void sched_process_timer(void)
{
+#ifndef CONFIG_DISABLE_CLOCK
/* Increment the system time (if in the link) */
-#ifndef CONFIG_DISABLE_CLOCK
#ifdef CONFIG_HAVE_WEAKFUNCTIONS
if (clock_timer != NULL)
#endif
@@ -193,11 +193,11 @@ void sched_process_timer(void)
}
#endif
+#if defined(CONFIG_SCHED_CPULOAD) && !defined(CONFIG_SCHED_CPULOAD_EXTCLK)
/* Perform CPU load measurements (before any timer-initiated context switches
* can occur)
*/
-#ifdef CONFIG_SCHED_CPULOAD
#ifdef CONFIG_HAVE_WEAKFUNCTIONS
if (sched_process_cpuload != NULL)
#endif