Stacks

When a process is created, a chunk is allocated to hold the process executable's .data section (initialised data) and .bss section (zero filled data). Sufficient space (default 2Mb) is also reserved as user-side stack space for threads that run in that process.

By default, each thread is allocated 8k of user-side stack space. A guard of 8k is also allocated.

The stack area follows the .data and .bss sections, and each thread's user side stack follows. On ARM processors the stack is descending, so that as items are added to the stack, the stack pointer is decremented. This means that if the stack overflows, the stack pointer points into the guard area and causes a processor exception, with the result that the kernel panics the thread.

Return addresses are stored by pushing them on to the stack so at any point you can trace through the stack looking at the saved return addresses to see the chain of function calls up to the present function.

The size of the user-side stack space has an indirect effect on the number of of threads that a process can have. There are other factors involved, but this is an important one. The limit is a consequence of the fact that a process can have a maximum of 8 chunks. This means that if threads within a process can share a heap (allocated from a single chunk), then it is possible to have a maximum of 128 threads per process [2Mb/(8K + 8K)]. More threads may be possible if you allow only 4K of stack per thread.

Apart from the kernel stack attached to each thread, the kernel also maintains stacks that are used during processing of interrupts, exceptions and certain CPU states. Interrupts and exceptions can occur at any time, with the system in any state, and it would be dangerous to allow them to use the current stack which may not even be valid or may overflow and panic the kernel. The kernel stacks are guaranteed to be large enough for all interrupt and exception processing.