Stack location

Where in memory (technically, where in the VAS of the given process) does the thread stack actually reside? The following points help us in this regard:

  • The stack of the main thread is always situated at the very top of the process VAS.
  • The stacks of all other threads in the process are located somewhere between the process heap segment and the stack of main; the precise location is not known in advance to the app developer; in any case, we should not need to know.
  • This is not directly related, but important: recall from Chapter 2, Virtual Memory, that, for most processors, the stack(s) conform to the stack-grows-down semantic; that is, the direction of growth of the stack segment is toward lower virtual addresses.

Though we should not need to, is there a way to specify the location of the thread stack? Well, yes, if you insist: the pthread_attr_[get|set]stack(3) APIs can be used for this purpose, as well as to set and/or query the thread stack's size:

#include <pthread.h>
int pthread_attr_setstack(pthread_attr_t *attr,
void *stackaddr, size_t stacksize);
int pthread_attr_getstack(const pthread_attr_t *attr,
void **stackaddr, size_t *stacksize);

Although you can use pthread_attr_setstack to set the stack location, it's recommended that this be left to the OS. Also, if you do use it, it's again recommended that both the stack location, stackaddr, and the stack size, stacksize, be a multiple of the system page size (and that the location is aligned to a page boundary). Aligning the thread stack to a page boundary can be easily achieved via the posix_memalign(3) API (we have covered example usage of this API in Chapter 4, Dynamic Memory Allocation).

Be careful: if you are specifying the stack location within the thread attribute structure, and creating threads in a loop (as is the normal fashion), you must ensure that each thread receives a unique stack location (this is often done by allocating the stack memory via the aforementioned posix_memalign(3) and then passing its return value as the stack location). Also, of course, the memory pages that will be used for the thread stack(s) must have both read-write permission (recall mprotect(2) from Chapter 4, Dynamic Memory Allocation).

After all is said and done, the mechanics of setting and querying the thread stack is straightforward; the really key point is this: (stress) test your application to ensure that the provided thread stack memory is sufficient. As we saw in the Chapters 11Signaling - Part I, overflowing the stack is a serious defect and will cause undefined behavior.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset