Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practices to determine stack usage in Ravenscar program

Tags:

memory

gcc

ada

I am writing an Ada program using the Ravenscar subset (thus, I am aware of the number of running tasks at execution time). The code is compiled by gcc with the -fstack-check switch enabled. This should cause the program raise a STORAGE_ERROR at runtime if any of my tasks exceed their stack.

Ada allows to set the upper limit for those (task-specific) stacks during the specification of the respective task like so:

pragma Storage_Size (Some_Value);

Now I was wondering what options I have to determine Some_Value. What I have heard of so far:

  1. Do wild guesses until no STORAGE_ERROR is raised anymore. This is more or less what the OP suggests here.
  2. Feed the output of -fstack-usage in there.
  3. Use some gnat specific extensions as outlined here (how does this technically differ from item #2?).
  4. Get a stack analyzer like gnatstack and let it do the work for you.

If I understand this correctly all the above techniques are dynamic (i.e. they require the program to run in order to work). Are static approaches also conceivable? E.g. by restricting myself further through some of Ada's high integrity options (such as No_Recursion, what else?).

Perhaps any of you can name some best practices to tackle this problem and/or extend/comment on my (surely incomplete) list.

Bonus question: What is the default size of a task's stack when the above pragma is not specified? GCC's docs only state this value depends on the runtime, without giving any concrete numbers.

like image 201
morido Avatar asked Jan 13 '16 11:01

morido


People also ask

How do I check my stack usage?

The most common way to determine the deepest stack usage is to initialize the stack memory with some known but unusual value, then periodically (or at the end of a big test run) see where that pattern stops. This is exactly how the IAR IDE determines the amount of stack used.

How is stack usage calculated in embedded systems?

To calculate stack depth, the address of the current stack pointer can be used. This requires simply taking the address of a function's argument or local variable. It should be done at the beginning of the main function and for each of the functions that are potentially using the most stack.

How do you calculate Max stack size?

You can query the maximum process and stack sizes using getrlimit . Stack frames don't have a fixed size; it depends on how much local data (i.e., local variables) each frame needs. To do this on the command-line, you can use ulimit.

How do I reduce stack usage?

Methods of reducing stack usage Avoiding the use of large local structures or arrays. Avoiding recursion, for example, by using an alternative algorithm. Minimizing the number of variables that are in use at any given time at each point in a function.

What is the result of stack usage analysis?

For simple applications, the result of stack usage analysis is plain and easy to understand. In usual, the program entry and interrupt handlers would be regarded as call graph root since they are not called by any other functions.

What is the path of the stack usage control file?

The stack usage control file is a text file which has *.suc as its suffix. The path of stack usage control file can be set in the Advanced tab of Linker options: There are several types of directive that can be used in the stack usage control file, such as function, exclude, possible calls, call graph root, max recursion depth, no calls from, etc.

How to track stack usage at runtime in RX?

IAR Embedded Workbench for RX provides another approach to track the stack usage at runtime, implemented by the C-SPY debugger. C-SPY can fill the entire stack area with a magic data pattern, for example 0xCD, before the application starts to execute.

How to identify functions with a high stack requirement?

Upon analysis, functions with a high stack requirement should be examined to determine if the size requirements are required. A method of detecting stack overflows is to create a canary space at the end of each task. This space is filled with some known data. If this data is ever modified, then the application has written past the end of the stack.


1 Answers

You can generally check the stack space required by individual types with the 'Storage_Size attribute (which counts in bits).

Once you have tabulated this (you may need to round it up to whole words/double words), you can add up how much stack space is used by each declarative region, and then walk through your calls to find the maximum stack usage.

like image 190
Jacob Sparre Andersen Avatar answered Oct 07 '22 07:10

Jacob Sparre Andersen