Description
This example program shows the measurement of the threads’ stack usage, using utilities in framework module Memory
.
The program utilises one core. Apart from the mandatory heartbeat blinker, it instantiates
- twelve threads that use a counter to achieve different stack depths;
- a monitoring thread that measures and prints the stack usage of all threads, including the kernel’s scheduler, using the corresponding utility procedures in module
Memory
.
Remarks
- Measuring stack usage must be enabled in the program. It’s off by default. This facility is intended to be a development tool, not for run-time monitoring of a deployed control program.
- When enabled, each newly allocated stack is filled with “magic” values.1 To measure the usage, the stack is scanned from its bottom address upwards, until a value other than as filled-in is found. This simple technique can result in wrong values, should the stack have held a “magic” value as part of the actual processing. Unlikely, but possible.
- As demonstrated in the example program, also declared, but unused local variables in procedures can result in wrong measurements, since these unused variables can still contain the filled-in values.
PROCEDURE do2(VAR cnt: INTEGER; lim: INTEGER); CONST Asize = 32; VAR i: INTEGER; a: ARRAY Asize OF INTEGER; BEGIN i := 0; WHILE i < Asize DO a[i] := 0; INC(i) END; (* init or use! *) WHILE cnt < lim DO INC(cnt) END; END do2;
- Remember to always allow for exception stacking in the thread stacks. Exception handling will happen in the main stack (MSP), but stacking in the thread stack (PSP).
Program Module
StackUsage
: core 0 program
Output Terminal
See Set-up, one-terminal set-up.
Build and Run
Build module StackUsage
with Astrobe, and create and upload the UF2 file using abin2uf2
.
Set Astrobe’s memory options as listed, and the library search path as explained.
Repository
-
Currently: the “magic” value is the address of the 32 bit memory location plus 3. This may change. ↩︎