Chapter 204. CPU Load Measurements
Table of Contents
204.1. CPU Load API
The package allows the CPU load to be estimated. The measurement code must first be calibrated to the target it is running on. Once this has been performed the measurement process can be started. This is a continuous process, so always providing the most up to data measurements. The process can be stopped at any time if required. Once the process is active, the results can be retrieved.
Note that if the target/processor performs any power saving actions, such as reducing the clock speed, or halting until the next interrupt etc, these will interfere with the CPU load measurement. Under these conditions the measurement results are undefined. The synthetic target is one such system. See the implementation details at the foot of this page for further information.
SMP systems are supported and are described later.
The API for load measuring functions can be
found in the file cyg/cpuload/cpuload.h
.
204.1.1. cyg_cpuload_calibrate
This function is used to calibrate the cpu load measurement code. It makes a measurement to determine the CPU properties while idle.
void cyg_cpuload_calibrate(cyg_uint32 *calibration);
The function returns the calibration value at the location pointed to
by calibration
.
This function is quite unusual. For it to work correctly a few conditions must be met. The function makes use of the two highest thread priorities. No other threads must be using these priorities while the function is being used. The kernel scheduler must be started and not disabled. The function takes 100ms to complete during which time no other threads will be run.
204.1.2. cyg_cpuload_create
This function starts the CPU load measurments.
void cyg_cpuload_create(cyg_cpuload_t *cpuload, cyg_uint32 calibrate, cyg_handle_t *handle);
The measurement process is started and a handle to it is returned in
*handle
. This handle is used to access the
results and the stop the measurement process.
204.1.3. cyg_cpuload_delete
This function stops the measurement process.
void cyg_cpuload_delete(cyg_handle_t handle);
handle
should be the value returned by the create function.
204.1.4. cyg_cpuload_get
This function returns the latest measurements.
void cyg_cpuload_get(cyg_handle_t handle, cyg_uint32 *average_point1s, cyg_uint32 *average_1s, cyg_uint32 *average_10s);
handle
should be the value returned by the
create function. The load measurements for the last 100ms, 1s and 10s
are returned in
*average_point1s
,*average_1s
and *average_10s
respectively.
204.1.5. Implementation details
This section gives a few details of how the measurements are made. This should help to understand what the results mean.
When there are no other threads runnable, eCos will execute the idle
thread. This thread is always runnable and uses the lowest thread
priority. The idle thread does little. It is an endless loop which
increments the variable, idle_thread_loops
and
executes the macro HAL_IDLE_THREAD_ACTION
. The cpu
load measurement code makes use of the variable. It periodically
examines the value of the variable and sees how much it has
changed. The idler the system, the more it will have incremented. From
this it is simple to determine the load of the system.
The function cyg_cpuload_calibrate
executes the
idle thread for 100ms to determine how much
idle_thread_loops
is incremented on a system idle
for 100ms. cyg_cpuload_create
starts an alarm which
every 100ms calls an alarm function. This function looks at the
difference in idle_thread_loops
since the last
invocation of the alarm function and so calculated how idle or busy
the system has been. The structure cyg_cpuload
is
updated during the alarm functions with the new results. The 100ms
result is simply the result from the last measurement period. A simple
filter is used to average the load over a period of time, namely 1s
and 10s. Due to rounding errors, the 1s and 10s value will probably
never reach 100% on a fully loaded system, but 99% is often seen.
As stated above, clever power management code will interfere with these measurements. The basic assumption is that the idle thread will be executed un-hindered and under the same conditions as when the calibration function was executed. If the CPU clock rate is reduced, the idle thread counter will be incremented less and so the CPU load measurements will give values too high. If the CPU is halted entirely, 100% cpu load will be measured.
204.1.6. SMP Support
This section described how CPU load is measured on SMP
systems. SMP support has been introduced without changing or
extending the existing API. To achieve this, both
cyg_cpuload_calibrate()
and
cyg_cpuload_create()
query the CPU that
they are running on and bind the cyg_cpuload_t
object to that CPU. The remaining API calls,
cyg_cpuload_delete()
and
cyg_cpuload_get()
, can be called from
any CPU.
To gather load information for each CPU in the system, a separate cyg_cpuload_t object must be allocated, calibrated and created for each CPU. The following example shows how this might be done during application initialization:
static cyg_uint32 calibration[HAL_SMP_CPU_COUNT]; static cyg_cpuload_t cpuload[HAL_SMP_CPU_COUNT]; static cyg_handle_t handle[HAL_SMP_CPU_COUNT]; static void create_cpuload( void ) { HAL_SMP_CPU_TYPE cpu; HAL_SMP_CPU_MASK old_affinity; // Get current thread affinity. cyg_thread_get_affinity( cyg_thread_self(), &old_affinity ); for( cpu = 0; cpu < HAL_SMP_CPU_COUNT; cpu++ ) { // Set this thread's affinity to single CPU. cyg_thread_set_affinity( cyg_thread_self(), 1<<cpu ); // Calibrate and create cpuload object. cyg_cpuload_calibrate(&calibration[cpu]); cyg_cpuload_create(&cpuload[cpu],calibration[cpu],&handle[cpu]); } // Restore thread's original affinity. cyg_thread_set_affinity( cyg_thread_self(), old_affinity ); }
Following this, the following call, from any CPU, will return the load for the given CPU:
cyg_cpuload_get(handle[cpu],&average_point1s,&average_1s,&average_10s);
2024-03-18 | Open Publication License |