Each thread has its own stack that you can allocate yourself or have the system manage.
The pthread_attr_t structure includes members that specify a new thread's stack address and size; pthread_attr_init() sets the default values, and you can use pthread_attr_setstackaddr() and pthread_attr_setstacksize() to override them. The values of the stack address and size members of this structure control the type of stack allocation that occurs when you create a thread:
Stack address | Stack size | Allocation |
---|---|---|
NULL | 0 | Automatic (the default) |
NULL | Desired size | Partly automatic |
Non-NULL | Size of the allocated area | Manual |
Let's compare the types of allocation:
Architecture | Stack size |
---|---|
32-bit x86 | 128 KB |
x86_64 | 256 KB |
32-bit ARM | 128 KB |
AArch64 | 512 KB |
The stack is followed by an inaccessible guard page that the process manager uses to detect stack overflow. Initially, only part of the stack is allocated in physical memory. This portion contains the thread local storage (TLS) and other system data that's specific to the thread. The process manager allocates additional 4 KB pages of physical memory when required. The guard page exists only in virtual memory; there's no physical memory allocated for it.
When the thread exits, the process manager automatically deallocates the stack.
A process’s main thread starts with an automatically allocated 512 KB stack, but it isn’t deleted when the main thread goes away (e.g., calls pthread_exit() or is cancelled). The main thread’s stack includes the command-line arguments and environment variables, which other threads might still need. To specify the stack size for the main thread, use qcc's -N option.
The output of the pidin mem command uses an asterisk (*) to indicate a stack that isn't automatically returned to the system heap when the thread exits.