module ti.sysbios.utils.Load |
|
The Load module reports execution times and load information for threads
in a system
SYS/BIOS manages four distinct levels of execution threads: hardware
interrupt service routines, software interrupt routines, tasks, and
background idle functions. This module reports execution time and load on a
per-task basis, and also provides information globally for hardware
interrupt service routines, software interrupt routines and idle functions
(in the form of the idle task). It can also report an estimate of the
global CPU load.
[
more ... ]
#include <ti/sysbios/utils/Load.h>
Functions |
UInt32 | |
UInt32 | |
Bool | |
Bool | |
Bool | |
Void | |
UInt32 | |
Void | |
Functions common to all target modules |
|
|
Typedefs |
typedef Void | |
typedef struct | |
Constants |
extern const Bool | |
| |
| |
| |
| |
| |
extern const Bool | |
extern const Bool | |
extern const Bool | |
extern const UInt | |
DETAILS
SYS/BIOS manages four distinct levels of execution threads: hardware
interrupt service routines, software interrupt routines, tasks, and
background idle functions. This module reports execution time and load on a
per-task basis, and also provides information globally for hardware
interrupt service routines, software interrupt routines and idle functions
(in the form of the idle task). It can also report an estimate of the
global CPU load.
Execution time is reported in units of
Timestamp counts, and load is reported
in percentages.
By default, load data is gathered for Task threads.
hwiEnabled,
swiEnabled
and
taskEnabled can be used to select which
type(s) of threads are monitored. These statistics are automatically
recorded to the load module's logger instance. Users can also choose
to call
getTaskLoad,
getGlobalSwiLoad,
getGlobalHwiLoad and
getCPULoad at any time to obtain the
statistics at runtime.
The module relies on
update to be called to compute load and
execution times from the time when
update was last called. This
is automatically done for every period specified by
windowInMs in an
Idle
function when
updateInIdle is
set to true. The time between two calls to
update is called the
benchmark time window.
By passing in a function pointer of type
Void(*
postUpdate)(Void) through the
postUpdate config parameter, one can specify a
postUpdate function that is
automatically called by
update immediately after the statistics
have been computed at the end of a benchmark time window. Setting this
function allows the user to optionally post-process the thread statistics
once and only once per benchmark window.
Advanced users could optionally omit calling
update in the idle
loop by setting
updateInIdle to false. They can
then call
update somewhere else (e.g. in a periodic higher
priority Task) instead to ensure statistics are computed even when the
system is never idle.
CPU LOAD CALCULATION METHODS
The CPU load is computed in three different ways,
depending on what threads are monitored, and whether or not Power
management is used to idle the CPU when no threads are running.
Task Load Disabled and No Power Management
The first method of calculating CPU load is used when
Task load logging is disabled, ie,
taskEnabled
is false, and Power management is not used. The CPU load is computed as
the percentage of time in the benchmark window which was NOT spent in the
idle loop. More specifically, the load is computed as follows:
global CPU load = 100 * (1 - (min. time for a trip around idle loop *
# times in idle loop)/(benchmark time window))
Any work done in the idle loop is included in the CPU load - in other
words, any time spent in the loop beyond the shortest trip around the idle
loop is counted as non-idle time.
This method works fairly well if the timestamp frequency is
sufficiently high (for example, if it's equal to the CPU frequency).
The CPU load accuracy can also be affected by caching and user idle functions.
Task Load Enabled and No Power Management
The second method of calculating CPU load is used when Task load logging
is enabled (
taskEnabled = true) and Power management is not used.
In this case the CPU load is calculted as
global CPU load = 100 - (Idle task load)
This prevents any discrepancy between the calculated CPU load had we
used the first method, and 100 - the Idle task load. If Swi and
Hwi load logging are not enabled, however, time spent in a Swi
or Hwi will be charged to the task in which it ran. This will
affect the accuracy of the CPU (and Task) load, but the trade off
is more overhead to do the Hwi and Swi load logging.
Power Management Enabled
This method applies to targets that have a SYS/BIOS Power
module. It does not apply to targets
where Power management is part of TI-RTOS (e.g., CC3200).
The third method of calculating CPU load is used when Power
management is enabled. In this case, the idle loop has a
function brought in by the Power module that idles the CPU.
The timestamp timer must continue to run during idle, in order
to measure idle and non-idle time, however. This method of
calculating CPU load plugs a Hwi hook function which is run
at the beginning of every Hwi. An idle function will call
Timestamp_get32() to mark the beginning of idle time, and
when the first Hwi causes the CPU to come out of idle, the
Hwi hook function will call Timestamp_get32() to mark the end
of idle time. The idle function accumulates the idle time
and total time elapsed, and the CPU load is calculated as:
global CPU load = 100 * (1 - idle time / time elapsed)
With this method of CPU load calculation, all idle functions are
included in the CPU load. When Power is enabled, Task, Swi, and
Hwi load logging can be enabled, but you may find that the
CPU load does not equal (100 - idle task load), since the CPU load
is calculated as the percentage of time that the processor is not
powered down, while the idle task load includes powered down time
plus time executing idle functions.
Power Management Enabled outside of SYS/BIOS
Some targets have Power management support outside of SYS/BIOS. For
example, CC3200 and CC26XX devices have Power management in TI-RTOS.
In these cases, the best way to get CPU load is to make sure that
taskEnabled is set to true. Then the CPU load will be
calculated as 100 - the idle task load. However, for BIOS in ROM builds,
this method will not work, as Task hooks are not allowed. So to
use Load for any devices that support BIOS in ROM builds, make
sure the ROM build is disabled.
EXAMPLES
Configuration example: The following statements configure the Load module
to obtain output in the CCS output window. This is useful for early
development without RTA tools support in SYS/BIOS:
var System = xdc.useModule('xdc.runtime.System');
var SysStd = xdc.useModule('xdc.runtime.SysStd');
System.SupportProxy = SysStd;
var Load = xdc.useModule('ti.sysbios.utils.Load');
var LoggerSys = xdc.useModule('xdc.runtime.LoggerSys');
var Defaults = xdc.useModule('xdc.runtime.Defaults');
var Diags = xdc.useModule('xdc.runtime.Diags');
// Turn on statistics log messages for Load module
Load.common$.diags_USER4 = Diags.ALWAYS_ON;
// Define a program-wide logger to be the System Logger
Defaults.common$.logger = LoggerSys.create();
Notes on above example:
- When using the System Logger,
System_printf calls are made to produce
the output in the output window. These calls are highly intrusive
and are only suited for early development.
- Also make sure your task stack sizes are large enough when using the
System Logger - particularly the idle task
stack size since logging is done in the idle task by default.
CAVEATS
- For the module to return accurate load values, the update
function must be run at least once before the Timestamp count gets to
wrap around. This means on a platform with a 32-bit
Timestamp frequency that runs at 200 MHz,
the function must be called at least once every 21 sec. With faster
Timestamp frequencies it would have to be
called even more frequently.
- If the updateInIdle option is enabled, the
module will call update periodically according to
windowInMs. The latter must be set to a time
interval that is below
(2^32) * 1000 / (Timestamp Frequency)
milliseconds
- If the updateInIdle option is disabled, the user is
then responsible for calling update more often than the above
time interval.
- Load values might not add up to 100%. Because the module minimizes
its interrupt latency and avoids locking up the system to compute all
thread loads at once, each thread's execution time is evaluated separately
over its own time window, which could be slightly different to that of
another thread.
- When disabling monitoring of a thread type of higher priority, the
time spent in that thread type will be counted towards time spent in
threads of lower priority. E.g. if hwiEnabled and
swiEnabled are both false, then time spent in Hwi's and
Swi's will be counted towards the Tasks in which the interrupts happened.
Thus, for better accuracy, it is best to leave monitoring on for threads of
a higher priority relative to the thread type of interest.
- When Task load logging is not enabled and Power management is not used,
the implementation of getCPULoad() self-calibrates the shortest
path through the idle loop. It does this by keeping track of the shortest
time between invocations of an idle function automatically inserted by the
Load module, and assumes that to be the time it takes for one iteration
through the idle loop. Because of this, the CPU load value is only an
estimate since the idle loop might occasionally take longer to run
(e.g. due to caching effects, stalls). The reported CPU load tends to be
slightly higher than reality, especially when the load is low.
- If taskEnabled is set to true,
task name support will be automatically turned on so that the Load module
can print out the task names in its log output.
- Currently does not support Timestamp
frequencies over 4 GHz.
Calling Context
Function | Hwi | Swi |
Task | Main | Startup |
getCPULoad | Y | Y |
Y | N | N |
getGlobalHwiLoad | Y | Y |
Y | N | N |
getGlobalSwiLoad | Y | Y |
Y | N | N |
getTaskLoad | Y | Y |
Y | N | N |
reset | Y* | Y* |
Y | Y | N |
update | Y* | Y* |
Y | N | N |
Definitions:
- Hwi: API is callable from a Hwi thread.
- Swi: API is callable from a Swi thread.
- Task: API is callable from a Task thread.
- Main: API is callable during any of these phases:
- In your module startup after this module is started
(e.g. Load_Module_startupDone() returns TRUE).
- During xdc.runtime.Startup.lastFxns.
- During main().
- During BIOS.startupFxns.
- Startup: API is callable during any of these phases:
- During xdc.runtime.Startup.firstFxns.
- In your module startup before this module is started
(e.g. Load_Module_startupDone() returns FALSE).
- *: Indicates only when taskEnabled
is set to false.
|
typedef Load_FuncPtr |
|
Callback function type
typedef Void (*Load_FuncPtr)();
struct Load_Stat |
|
Load statistics info
typedef struct Load_Stat {
UInt32 threadTime;
UInt32 totalTime;
} Load_Stat;
config Load_LS_cpuLoad // module-wide |
|
This event logs the global CPU load as a percentage
DETAILS
This event is logged whenever the Diags.USER4 level is enabled
and the load is measured.
config Load_LS_hwiLoad // module-wide |
|
This event logs the Hwi load
DETAILS
This event is logged whenever the Diags.USER4 level is enabled
hwiEnabled is true, and the load is measured.
This event logs the Hwi load, with the form:
<load time>,<measurement time>
Percentage load = <load time> / <measurement time> x 100%
config Load_LS_swiLoad // module-wide |
|
This event logs the Swi load
DETAILS
This event is logged whenever the Diags.USER4 level is enabled
swiEnabled is true, and the load is measured.
This event logs the Swi load, with the form:
<load time>,<measurement time>
Percentage load = <load time> / <measurement time> x 100%
config Load_LS_taskLoad // module-wide |
|
This event logs Task thread loads
DETAILS
This event is logged whenever the Diags.USER4 level is enabled,
taskEnabled is true, and the load is measured.
This event logs Task thread loads, with the form:
<Task handle>,<load time>,<measurement time>,<Task function pointer>
Percentage load = <load time> / <measurement time> x 100%
config Load_hwiEnabled // module-wide |
|
Enables Hwi time monitoring
extern const Bool Load_hwiEnabled;
DETAILS
When this parameter is set to
true,
Hwi
processing time is accumulated between successive calls of
update and, as part of Load_update, an
event with this cumulative time is logged. This
time, together with the total elapsed time, is used to estimate the
CPU load due to any Hwi instances run between these updates.
config Load_postUpdate // module-wide |
|
User function called after each load update
DETAILS
If non-NULL, postUpdate is run immediately after each update.
config Load_swiEnabled // module-wide |
|
Enables Swi time monitoring
extern const Bool Load_swiEnabled;
DETAILS
When this parameter is set to
true, Swi processing time is
accumulated between successive calls of
update and, as
part of Load_update, an
event with this
cumulative time is logged. This time together with the total
elapsed time is used to estimate the CPU load due to any Swi
instances run between these updates.
config Load_taskEnabled // module-wide |
|
Enables Task time monitoring
extern const Bool Load_taskEnabled;
DETAILS
When this parameter is set to
true, each Task's processing time is
accumulated between successive calls of
update and, as
part of Load_update, an
event with this
cumulative time is logged for each task. This time together with the
total elapsed time is used to estimate the CPU load due to each Task
run between these updates.
config Load_updateInIdle // module-wide |
|
Automatically call update in Idle loop
extern const Bool Load_updateInIdle;
DETAILS
If this parameter is set to
true, an
Idle
function, which computes and updates the CPU load, is added to the
Idle loop.
config Load_windowInMs // module-wide |
|
Load averaging period
extern const UInt Load_windowInMs;
DETAILS
When
updateInIdle is enabled, this period determines the
minimum elapsed time between updates of the load statistics in the
idle loop.
Load_calculateLoad() // module-wide |
|
Compute total CPU load from a Load_Stat structure
DETAILS
This function computes percent load from the
values in a Load_Stat structure.
RETURNS
Load value of a Load_Stat structure in %.
Load_getCPULoad() // module-wide |
|
Return an estimate of the global CPU load
UInt32 Load_getCPULoad();
RETURNS
CPU load in %
DETAILS
This function returns an estimate of CPU load (% utilization of the
CPU), with the idle time determined based on number of trips through
the idle loop multiplied by the shortest amount of time through the
loop.
This function requires the idle loop to be run during a benchmark time
window.
Note: Time spent in kernel while switching to a Hwi/Swi/Task is
considered non-idle time.
Load_getGlobalHwiLoad() // module-wide |
|
Return the load and time spent in hwi's
ARGUMENTS
stat
Load and time statistics info
RETURNS
TRUE if success, FALSE if failure
DETAILS
This function computes the load and time spent in Hwi's along
with the time duration over which the measurement was done. Numbers
are reported in
Timestamp counts.
Load_getGlobalSwiLoad() // module-wide |
|
Return the load and time spent in Swi's
ARGUMENTS
stat
Load and time statistics info
RETURNS
TRUE if success, FALSE if failure
DETAILS
This function returns the load and time spent in Swi's along with
the time duration over which the measurement was done. Numbers are
reported in
Timestamp counts.
Load_getTaskLoad() // module-wide |
|
Return the load and time spent in a specific task
ARGUMENTS
task
Handle of the Task which time we are interested in.
stat
Load and time statistics info
RETURNS
TRUE if success, FALSE if failure
DETAILS
This function returns the load and time spent in a specific task
along with the duration over which the measurement was done. Numbers
are reported in
Timestamp counts.
Task handle must be valid and have been registered with Load.
Load_reset() // module-wide |
|
Reset all internal load counters
DETAILS
If
taskEnabled is set to true, this function can
only be called in task context.
Load_setMinIdle() // module-wide |
|
Set lower bound on idle loop time used to compute CPU load
UInt32 Load_setMinIdle(UInt32 newMinIdleTime);
SEE
Load_update() // module-wide |
|
Record thread statistics and reset all counters
DETAILS
If
taskEnabled is set to true, this function can
only be called in task context.
Module-Wide Built-Ins |
|
// Get this module's unique id
Bool Load_Module_startupDone();
// Test if this module has completed startup
// The heap from which this module allocates memory
Bool Load_Module_hasMask();
// Test whether this module has a diagnostics mask
Bits16 Load_Module_getMask();
// Returns the diagnostics mask for this module
Void Load_Module_setMask(Bits16 mask);
// Set the diagnostics mask for this module
var Load = xdc.useModule('ti.sysbios.utils.Load');
module-wide constants & types
module-wide config parameters
msg: "LS_cpuLoad: %d%%"
};
msg: "LS_hwiLoad: %d,%d"
};
msg: "LS_swiLoad: %d,%d"
};
msg: "LS_taskLoad: 0x%x,%d,%d,0x%x"
};
struct Load.Stat |
|
Load statistics info
var obj = new Load.Stat;
obj.threadTime = UInt32 ...
obj.totalTime = UInt32 ...
C SYNOPSIS
config Load.LS_cpuLoad // module-wide |
|
This event logs the global CPU load as a percentage
msg: "LS_cpuLoad: %d%%"
};
DETAILS
This event is logged whenever the Diags.USER4 level is enabled
and the load is measured.
C SYNOPSIS
config Load.LS_hwiLoad // module-wide |
|
This event logs the Hwi load
msg: "LS_hwiLoad: %d,%d"
};
DETAILS
This event is logged whenever the Diags.USER4 level is enabled
hwiEnabled is true, and the load is measured.
This event logs the Hwi load, with the form:
<load time>,<measurement time>
Percentage load = <load time> / <measurement time> x 100%
C SYNOPSIS
config Load.LS_swiLoad // module-wide |
|
This event logs the Swi load
msg: "LS_swiLoad: %d,%d"
};
DETAILS
This event is logged whenever the Diags.USER4 level is enabled
swiEnabled is true, and the load is measured.
This event logs the Swi load, with the form:
<load time>,<measurement time>
Percentage load = <load time> / <measurement time> x 100%
C SYNOPSIS
config Load.LS_taskLoad // module-wide |
|
This event logs Task thread loads
msg: "LS_taskLoad: 0x%x,%d,%d,0x%x"
};
DETAILS
This event is logged whenever the Diags.USER4 level is enabled,
taskEnabled is true, and the load is measured.
This event logs Task thread loads, with the form:
<Task handle>,<load time>,<measurement time>,<Task function pointer>
Percentage load = <load time> / <measurement time> x 100%
C SYNOPSIS
config Load.hwiEnabled // module-wide |
|
Enables Hwi time monitoring
Load.hwiEnabled = Bool false;
DETAILS
When this parameter is set to
true,
Hwi
processing time is accumulated between successive calls of
update and, as part of Load_update, an
event with this cumulative time is logged. This
time, together with the total elapsed time, is used to estimate the
CPU load due to any Hwi instances run between these updates.
C SYNOPSIS
config Load.postUpdate // module-wide |
|
User function called after each load update
Load.postUpdate = Void(*)() null;
DETAILS
If non-NULL, postUpdate is run immediately after each update.
C SYNOPSIS
config Load.swiEnabled // module-wide |
|
Enables Swi time monitoring
Load.swiEnabled = Bool false;
DETAILS
When this parameter is set to
true, Swi processing time is
accumulated between successive calls of
update and, as
part of Load_update, an
event with this
cumulative time is logged. This time together with the total
elapsed time is used to estimate the CPU load due to any Swi
instances run between these updates.
C SYNOPSIS
config Load.taskEnabled // module-wide |
|
Enables Task time monitoring
Load.taskEnabled = Bool true;
DETAILS
When this parameter is set to
true, each Task's processing time is
accumulated between successive calls of
update and, as
part of Load_update, an
event with this
cumulative time is logged for each task. This time together with the
total elapsed time is used to estimate the CPU load due to each Task
run between these updates.
C SYNOPSIS
config Load.updateInIdle // module-wide |
|
Automatically call update in Idle loop
Load.updateInIdle = Bool true;
DETAILS
If this parameter is set to
true, an
Idle
function, which computes and updates the CPU load, is added to the
Idle loop.
C SYNOPSIS
config Load.windowInMs // module-wide |
|
Load averaging period
Load.windowInMs = UInt 500;
DETAILS
When
updateInIdle is enabled, this period determines the
minimum elapsed time between updates of the load statistics in the
idle loop.
C SYNOPSIS
metaonly config Load.common$ // module-wide |
|
Common module configuration parameters
DETAILS
All modules have this configuration parameter. Its name
contains the '$' character to ensure it does not conflict with
configuration parameters declared by the module. This allows
new configuration parameters to be added in the future without
any chance of breaking existing modules.
metaonly config Load.enableCPULoadCalc // module-wide |
|
Automatically update the Load module's CPU load value in
update
Load.enableCPULoadCalc = Bool true;
DETAILS
If this parameter is set to true, Load_update() will calculate
the CPU load for the elapsed time. In some cases, the user may
prefer to use the statistics gathered by the Load module and do
the CPU load calculation themself. Set this parameter to false,
to disable the Load module's CPU load calculations. This can
improve performance of the Load_update() call.
metaonly config Load.minIdle // module-wide |
|
Specifies the minimum time used to compute idle time
DETAILS
During CPU load measurement, the minimum time observed executing
the idle loop together with the count of the number of times the idle
loop runs id used to compute the total idle time. However, since the
_actual_ time spent in the idle loop will almost always be greater
then the observed minimum, the idle time is almost always under
estimated.
This configuration parameter can be used to compensate for this
underestimate by placing a lower bound on the minimum time used in
the CPU measurements. The minimum idle time used to compute CPU
load is guarenteed to be greater than or equal to minIdle.
generated on Thu, 23 May 2019 00:23:10 GMT