How to properly allocate memory for a pthread stack
c, mmap, pthreads
Solution
What do you mean by "monitor"? If you just want to ensure that not too much space is wasted for the stack (which would prevent you from having lots of threads on a 32-bit system or system with low ram+swap), you should simply use the `pthread_attr_setstacksize` function rather than `pthread_attr_setstack`. This way you are not responsible for allocating the stack yourself. You could also optionally use `pthread_attr_setguardsize` to ensure a larger zone of guard pages as protection if you're worried the thread will allocate more than one page at a time on the stack, but be aware that this will consume your virtual address space.
If you really want to measure stack usage, `pthread_attr_setstack` probably is the right tool, but it's not at all straightforward. I would allocate the memory with `mmap`, and make it read-only. Then install a `SIGSEGV` handler to `mprotect` the faulting page writable, increment a counter, and return. That will give you a count of the number of actual pages the thread touches. And since the signal handler will run in the faulting thread (this is guaranteed since it's a synchronous signal), you can keep the count in a thread-local storage variable to perform the counting on multiple threads.
You might actually need to make the last page or two writable before calling `pthread_create`, though, since the first write attempts will probably happen from the parent thread, and you probably don't want the signal handler running there if you're trying to store the results in thread-local storage.
To access your specific questions at the end:
You do not want `MAP_SHARED`. That flag is for memory that will be shared between processes. It probably won't hurt in your case, but it's misleading. Use `MAP_PRIVATE`.
The memory will not be released, and formally, can never be released. POSIX states quite explicitly that it's undefined behavior to ever reuse or free a stack given to a thread, since you cannot determine the lifetime reliably (even after `pthread_join` returns, it's conceptually possible that the thread is still executing its last few instructions to exit and thus still touching the stack, and it's possible that it remain stalled like that indefinitely long). I believe this is not possible on glibc/NPTL due to the way they use a kernel-generated futex wake event on thread exit to signal `pthread_join` atomically with the thread exit, but NPTL may cache and reuse stacks that you donated to a thread like this (since you're not allowed to reuse/free them yourself anyway). To be sure you'd have to check the source. As such, I would recommend NOT using `pthread_attr_setstack` at all in production code. Use `pthread_attr_setstacksize`. `pthread_attr_setstack` should be used only for development-time hacks like what you might be doing now.
Problem
I am trying to monitor the stack usage of my threads. To do that I need to know the address of the threads stack, and the only way I have found to do that is to set the stack using `pthread_attr_setstack()`. I'm currently using mmap to allocate the memory: ``` pthread_attr_t ptAttr; pthread_t pth; pthread_attr_init(&ptAttr); void *stack = mmap(NULL, stksize, PROT_WRITE|PROT_READ, MAP_ANONYMOUS|MAP_SHARED, -1, 0); pthread_attr_setstack(&ptAttr, stack, stksize); pthread_create(&pth,&ptAttr,threadFunc,&info); ``` So first question, is this a good way of allocating the memory with `mmap`? Are the flags correct? Should I be using `malloc` instead? This will run on an low-resource device with no virtual/swap memory. Second question, will this memory be released automatically when the thread dies? If you are not sure, is there a way to find out if it has been released?