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 ... ]
C synopsis target-domain sourced in ti/sysbios/utils/Load.xdc
#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 Log_Event 
extern const Log_Event 
extern const Log_Event 
extern const Log_Event 
extern const Load_FuncPtr 
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 2 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, taskEnable 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). For the MSP430, however, with the CPU running at 8MHz, when the 32KHz ACLK is used for the timestamp counter, the CPU load is only a very rough approximation, due to the courseness of the timestamp. 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 (taskEnable = 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
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.
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
  1. 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.
  2. 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
  3. If the updateInIdle option is disabled, the user is then responsible for calling update more often than the above time interval.
  4. 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.
  5. 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.
  6. 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.
  7. 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.
  8. 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

C synopsis target-domain
typedef Void (*Load_FuncPtr)();
 
 
struct Load_Stat

Load statistics info

C synopsis target-domain
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

C synopsis target-domain
extern const Log_Event Load_LS_cpuLoad;
 
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

C synopsis target-domain
extern const Log_Event Load_LS_hwiLoad;
 
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

C synopsis target-domain
extern const Log_Event Load_LS_swiLoad;
 
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

C synopsis target-domain
extern const Log_Event Load_LS_taskLoad;
 
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

C synopsis target-domain
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

C synopsis target-domain
extern const Load_FuncPtr Load_postUpdate;
 
DETAILS
If non-NULL, postUpdate is run immediately after each update.
 
config Load_swiEnabled  // module-wide

Enables Swi time monitoring

C synopsis target-domain
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

C synopsis target-domain
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

C synopsis target-domain
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

C synopsis target-domain
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

C synopsis target-domain
UInt32 Load_calculateLoad(Load_Stat *stat);
 
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

C synopsis target-domain
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

C synopsis target-domain
Bool Load_getGlobalHwiLoad(Load_Stat *stat);
 
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

C synopsis target-domain
Bool Load_getGlobalSwiLoad(Load_Stat *stat);
 
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

C synopsis target-domain
Bool Load_getTaskLoad(Task_Handle task, Load_Stat *stat);
 
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

C synopsis target-domain
Void Load_reset();
 
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

C synopsis target-domain
UInt32 Load_setMinIdle(UInt32 newMinIdleTime);
 
SEE
 
Load_update()  // module-wide

Record thread statistics and reset all counters

C synopsis target-domain
Void Load_update();
 
DETAILS
If taskEnabled is set to true, this function can only be called in task context.
Module-Wide Built-Ins

C synopsis target-domain
Types_ModuleId Load_Module_id();
// Get this module's unique id
 
Bool Load_Module_startupDone();
// Test if this module has completed startup
 
IHeap_Handle Load_Module_heap();
// 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
 
Configuration settings sourced in ti/sysbios/utils/Load.xdc
var Load = xdc.useModule('ti.sysbios.utils.Load');
module-wide constants & types
    var obj = new Load.Stat// Load statistics info;
        obj.threadTime = UInt32  ...
        obj.totalTime = UInt32  ...
module-wide config parameters
        mask: Diags.USER4,
        msg: "LS_cpuLoad: %d%%"
    };
        mask: Diags.USER4,
        msg: "LS_hwiLoad: %d,%d"
    };
        mask: Diags.USER4,
        msg: "LS_swiLoad: %d,%d"
    };
        mask: Diags.USER4,
        msg: "LS_taskLoad: 0x%x,%d,%d,0x%x"
    };
 
 
 
struct Load.Stat

Load statistics info

Configuration settings
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

Configuration settings
Load.LS_cpuLoad = Log.EventDesc {
    mask: Diags.USER4,
    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

Configuration settings
Load.LS_hwiLoad = Log.EventDesc {
    mask: Diags.USER4,
    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

Configuration settings
Load.LS_swiLoad = Log.EventDesc {
    mask: Diags.USER4,
    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

Configuration settings
Load.LS_taskLoad = Log.EventDesc {
    mask: Diags.USER4,
    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

Configuration settings
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

Configuration settings
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

Configuration settings
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

Configuration settings
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

Configuration settings
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

Configuration settings
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

Configuration settings
Load.common$ = Types.Common$ undefined;
 
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.minIdle  // module-wide

Specifies the minimum time used to compute idle time

Configuration settings
Load.minIdle = UInt32 0;
 
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 Wed, 15 Apr 2015 00:20:09 GMT