StackUsage

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).

Output Terminal

See Set-up, one-terminal set-up.

Build and Run

Repository

  • libv2: for RP2040/Pico and RP2350/Pico2: StackUsage
  • lib (v1): this version is no longer being maintained: StackUsage

  1. Currently: the “magic” value is the address of the 32 bit memory location plus 3. This may change. ↩︎