[previous]
[index]
[next]
Example 10: Determining Stack Size
This example shows how to determine the stack size needed for your
real-time tasks. So far, we've just used a 1K stack. In general you'll
need to determine just how much stack to allocate. Too little, and
you'll crash your system when your functions nest too deeply. Here's
what you see when that happens:
The "Black Screen of Death". Normal Linux applications won't cause
this, since they run in protected mode. RT code runs in privileged
kernel space. Too little stack and you'll clobber the kernel, and see
this screen. Time to reboot.
Refer to the commented
source code of the example for the details.
Principle of Operation
The Gory Details
(This section shows the analysis that led to the example code. You
can skip this; the example code contains the functions you'll need.)
- To apply this technique to RTAI, we need to know how the stack is
allocated and initialized, so we don't clobber anything RTAI has
set up for us on our stack. Recall that a task's stack is allocated
and initialized in 'rt_task_init()':
rt_task_init(RT_TASK *task, void *rt_thread, int data,
int stack_size, /* here's the size, in bytes */
int priority, int uses_fpu, void *signal);
- If you inspect the RTAI scheduler header file
<rtai_sched.h>,
you'll see that the RT_TASK structure contains, among other things,
the pointers to the top and bottom of the stack:
typedef struct rt_task_struct {
...
int *stack;
int *stack_bottom;
...
}
- Further inspecting the RTAI source code, specifically
<rtai_sched.c> and <asm/rtai_sched.h>, we can see the
details of how RTAI sets up the task stack.
- In 'rt_task_init()', RTAI allocates 'stack_size' bytes with
'sched_malloc()', and sets the bottom of the stack,
task->stack_bottom, to this memory.
- The top of the stack,
task->stack, is set to the bottom plus stack_size bytes minus 16
bytes, rounded down to the nearest integer boundary.
- 5 integers are
then pushed onto the stack.
The top integer (4 bytes) of the stack
is set to 0.
The next integer down is set to the initial 'data'
argument for the task.
The next integer down is set to the
'rt_thread' code for the task.
The next integer down is set to
0.
The next integer down is set to some RTAI startup code, and the
stack is left pointing to this. When initializing the stack, we must
stop short of this.
- In our examples, we start with a stack size of 1K. If this is not enough,
we will have strange problems which defy debugging, at which point we
can try increasing stack size and hope the problem goes away.
- In the example program, the hex output (from the console, or
/var/log/messages) shows the part of the stack used by our code when
it is stopped:
DCC2034C: 76
DCC20348: 75
DCC20344: 74
DCC20340: 73
DCC2033C: 72
DCC20338: 71
DCC20334: 70
DCC20330: 6F
DCC2032C: 6E
DCC20328: 6D
DCC20324: 6C
DCC20320: 6B
DCC2031C: 6A
DCC20318: 69
DCC20314: 68
DCC20310: 67
DCC2030C: 66
DCC20308: 65
DCC20304: 64
DCC20300: DEADBEEF
...
DCC20020: DEADBEEF
740 unused stack bytes
- The bottom of the stack is at address 0xDCC20020, and it grows upward
toward 0xDCC2034C, which is close to the top of the stack.
- Here we see
the unused stack portion at the bottom, from integers at 0xDCC20020
through 0xDCC20300, inclusive, or 740 bytes. This is corroborated by
a count made from the bottom of the stack up to the first non-DEADBEEF
occurrence.
-
The problem with this technique is that all the code paths may not
be exercised during the run, and later your code may enter a deeper
area that was not entered before.
- Since there is no performance impact
on the task with this technique, it may be wise to leave the stack
initialization and checking intact in init_module() and cleanup_module(),
respectively.
Running the Demo
To run the demo, change to the 'ex10_stack' subdirectory of the
top-level tutorial directory, and run the 'run' script by typing
./run
Alternatively, change to the top-level tutorial directory and run the
'runall' script there by typing
./runall
and selecting the "Stack Testing" button.
You'll see diagnostics messages printing out.
See the Code
Next: Example 11, Measuring Timing Jitter
Back: Example 9, Displaying Messages on an LED Wand Clock