The thread attribute stack parameters are prototyped as follows:
int pthread_attr_setstack (pthread_attr_t *attr, void *addr, size_t ssize ); int pthread_attr_setstackaddr (pthread_attr_t *attr, void *addr); int pthread_attr_setguardsize (pthread_attr_t *attr, size_t gsize); int pthread_attr_setstacklazy (pthread_attr_t *attr, int lazystack); int pthread_attr_setstackprealloc (pthread_attr_t * attr, size_t psize); int pthread_attr_setstacksize (pthread_attr_t *attr, size_t ssize);
These functions all take the attribute structure as their first parameter; the other parameters are selected from the following:
The guard area is a memory area immediately after the stack that the thread can't write to. If it does (meaning that the stack was about to overflow), the thread will get hit with a SIGSEGV. If the guardsize is 0, it means that there's no guard area. This also implies that there's no stack overflow checking. If the guardsize is nonzero, then it's set to at least the system-wide default guardsize (which you can obtain with a call to sysconf() with the constant _SC_PAGESIZE). Note that the guardsize will be at least as big as a page (for example, 4 KB on an x86 processor). Also, note that the guard page doesn't take up any physical memory—it's done as a virtual address (MMU) trick.
The addr is the address of the stack, in case you're providing it. You can set it to NULL meaning that the system will allocate (and will free!) the stack for the thread. The advantage of specifying a stack is that you can do postmortem stack depth analysis. This is accomplished by allocating a stack area, filling it with a signature (for example, the string STACK repeated over and over), and letting the thread run. When the thread has completed, you'd look at the stack area and see how far the thread had scribbled over your signature, giving you the maximum depth of the stack used during this particular run.
The ssize parameter specifies how big the stack is. If you provide the stack in addr, then ssize should be the size of that data area. If you don't provide the stack in addr (meaning you passed a NULL), then the ssize parameter tells the system how big a stack it should allocate for you. If you specify a 0 for ssize, the system will select the default stack size for you. Obviously, it's bad practice to specify a 0 for ssize and specify a stack using addr—effectively you're saying Here's a pointer to an object, and the object is some default size. The problem is that there's no binding between the object size and the passed value.
Finally, the lazystack parameter indicates if the physical memory should be allocated as required (use the value PTHREAD_STACK_LAZY) or all up front (use the value PTHREAD_STACK_NOTLAZY). The advantage of allocating the stack on demand (as required) is that the thread won't use up more physical memory than it absolutely has to. The disadvantage (and hence the advantage of the all up front method) is that in a low-memory environment the thread won't mysteriously die some time during operating when it needs that extra bit of stack, and there isn't any memory left. If you are using PTHREAD_STACK_NOTLAZY, you'll most likely want to set the actual size of the stack instead of accepting the default, because the default is quite large.