forked from Imagelibrary/rtems
In uniprocessor and SMP configurations, the context switch extensions
were called during _Thread_Do_dispatch():
void _Thread_Do_dispatch( Per_CPU_Control *cpu_self, ISR_Level level )
{
Thread_Control *executing;
executing = cpu_self->executing;
...
do {
Thread_Control *heir;
heir = _Thread_Get_heir_and_make_it_executing( cpu_self );
...
_User_extensions_Thread_switch( executing, heir );
...
_Context_Switch( &executing->Registers, &heir->Registers );
...
} while ( cpu_self->dispatch_necessary );
...
}
In uniprocessor configurations, this is fine and the context switch
extensions are called for all thread switches except the very first
thread switch to the initialization thread. However, in SMP
configurations, the context switch may be invalidated and updated in the
low-level _Context_Switch() routine. See:
https://docs.rtems.org/branches/master/c-user/symmetric_multiprocessing_services.html#thread-dispatch-details
In case such an update happens, a thread will execute on the processor
which was not seen in the previous call of the context switch
extensions. This can confuse for example event record consumers which
use events generated by a context switch extension.
Fixing this is not straight forward. The context switch extensions call
must move after the low-level context switch. The problem here is that
we may end up in _Thread_Handler(). Adding the context switch
extensions call to _Thread_Handler() covers now also the thread switch
to the initialization thread. We also have to save the last executing
thread (ancestor) of the processor. Registers or the stack cannot be
used for this purpose. We have to add it to the per-processor
information. Existing extensions may be affected, since now context
switch extensions use the stack of the heir thread. The stack checker
is affected by this.
Calling the thread switch extensions in the low-level context switch is
difficult since at this point an intermediate stack is used which is
only large enough to enable servicing of interrupts.
Update #3885.
Introduction
============
This directory contains a stack bounds checker. It provides two
primary features:
+ check for stack overflow at each context switch
+ provides an educated guess at each task's stack usage
Enabling
========
Add the stack checker extension to the initial user extension set.
If using confdefs.h to build your configuration table, this is
as simple as adding -DSTACK_CHECK_ON to the gcc command line which
compiles the file defining the configuration table. In the RTEMS
test suites and samples, this is always init.c
Background
==========
The stack overflow check at context switch works by looking for
a 16 byte pattern at the logical end of the stack to be corrupted.
The "guesser" assumes that the entire stack was prefilled with a known
pattern and assumes that the pattern is still in place if the memory
has not been used as a stack.
Both of these can be fooled by pushing large holes onto the stack
and not writing to them... or (much more unlikely) writing the
magic patterns into memory.
This code has not been extensively tested. It is provided as a tool
for RTEMS users to catch the most common mistake in multitasking
systems ... too little stack space. Suggestions and comments are appreciated.
NOTES:
1. Stack usage information is questionable on CPUs which push
large holes on stack.
2. The stack checker has a tendency to generate a fault when
trying to print the helpful diagnostic message. If it comes
out, congratulations. If not, then the variable Stack_check_Blown_task
contains a pointer to the TCB of the offending task. This
is usually enough to go on.
FUTURE:
1. Determine how/if gcc will generate stack probe calls and support that.