Stack Management

Routines:

pthread_attr_getstacksize(attr, stacksize)

pthread_attr_setstacksize(attr, addr, stacksize)

pthread_attr_getstackaddr(attr, stackaddr)

pthread_attr_setstackaddr(attr, stackaddr)

Preventing Stack Problems:

The POSIX standard does not dictate the size of a thread’s stack. This is implementation dependent and varies.

Exceeding the default stack limit is often very easy to do, with the usual results: program termination and/or corrupted data.

Safe and portable programs do not depend upon the default stack limit, but instead, explicitly allocate enough stack for each thread by using the pthread_attr_setstacksize routine.

The pthread_attr_getstackaddr and pthread_attr_setstackaddr routines can be used by applications in an environment where the stack for a thread must be placed in some particular region of memory.

Some Practical Examples at LC:

Default thread stack size varies greatly. The maximum size that can be obtained also varies greatly, and may depend upon the number of threads per node.

Both past and present architectures are shown to demonstrate the wide variation in default thread stack size.

Node
Architecture
#CPUsMemory (GB)Default Size
(bytes)
Intel Xeon E5-267016322,097,152
Intel Xeon 566012242,097,152
AMD Opteron8162,097,152
Intel IA644833,554,432
Intel IA32242,097,152
IBM Power5832196,608
IBM Power4816196,608
IBM Power3161698,304

Example: Stack Management

This example demonstrates how to query and set a thread’s stack size.

#include <pthread.h>
#include <stdio.h>

#define NTHREADS 4
#define N 1000
#define MEGEXTRA 1000000

pthread_attr_t attr;

void *dowork(void *threadid)
{
   double A[N][N];
   int i, j;
   long tid;
   size_t mystacksize;

   tid = (long)threadid;
   pthread_attr_getstacksize(&attr, &mystacksize);
   printf("Thread %ld: stack size = %li bytes \n", tid, mystacksize);
   for (i = 0; i < N; i++) {
      for (j = 0; j < N; j++) {
         A[i][j] = ((i * j) / 3.452) + (N - i);
      }
   }
   pthread_exit(NULL);
}

int main(int argc, char *argv[])
{
   pthread_t threads[NTHREADS];
   size_t stacksize;
   int rc;
   long t;

   pthread_attr_init(&attr);
   pthread_attr_getstacksize(&attr, &stacksize);
   printf("Default stack size = %li\n", stacksize);

   stacksize = sizeof(double)*N*N+MEGEXTRA;
   printf("Amount of stack needed per thread = %li\n", stacksize);
   pthread_attr_setstacksize (&attr, stacksize);

   printf("Creating threads with stack size = %li bytes\n", stacksize);
   for(t=0; t<NTHREADS; t++){
      rc = pthread_create(&threads[t], &attr, dowork, (void *)t);
      if (rc){
         printf("ERROR; return code from pthread_create() is %d\n", rc);
         exit(-1);
      }
   }
   printf("Created %ld threads.\n", t);
   pthread_exit(NULL);
}