As far as the Linux kernel is concerned, threads are processes with some more sharing than usual (e.g. their address space, their signal handling, and their process id, which is really their thread group id).
When a process starts, it has a single thread, with a stack etc. When that thread starts another thread, it’s up to the creating thread to provide a stack for the new thread; that is typically done using mmap
, because mmap
supports various flags which help ensure that the allocated memory is suitable for use as a stack. See the example program in man 2 clone
. However there is no requirement to use mmap
, any allocated block of memory meeting the requirements for a stack can be used.
Stacks set up for threads aren’t private: they are visible to other threads sharing the same address space. However, they must be reserved for a single thread’s use as a stack (multiple threads sharing a single stack won’t work well, to say the least).
See Are threads implemented as processes on Linux? for more context and history.