Thread stacks are allocated using mmap when the thread starts (or even earlier - you can set the stack space in pthread_attr s). TLS data is stored at the beginning of the stream stack. The size of the stacks of streams is fixed, as a rule, from 2 to 8 MB. The stack size for each thread cannot be changed while the thread is active. (First thread - running main - still uses the main stack at the end of the address space, and this stack can grow and shrink.) The heap and code are shared between all threads. Mutexes can be anywhere in the data section - it's just a structure.
mmap stream stack is not fixed at any address:
Glibc Sources
mem = mmap (NULL, size, prot, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
PS modern GCC allows stream stack unlimited with SplitStacks function
source share