Power Programming Languages

Power Programming Languages

IBM Power, including the AIX, IBM i, and Linux operating systems, support a wide range of programming languages, catering to both traditional enterprise applications and modern development needs.


#Power

 View Only

Don't forget about stack size limits for multi-threaded applications on AIX

By Archive User posted Fri September 06, 2013 03:09 PM

  

Originally posted by: BasilTK


Have you ever wondered why your child threads in a multi-threaded application on AIX fail to acquire a large amount of memory from the stack (even though your ulimits are set to unlimited) ?
 
The reason is simple. For a 32-bit compiled application on AIX, the default pthread stacksize is 96 KB; and for a 64-bit compiled application on AIX, 
the default stacksize is 192 KB. Both of these default values are defined in the pthread.h header file. 
 
Let's use the following test case as an example. 
$ cat test.c                                                                                                                          
1      #include <stdio.h>                                                                                                                 
2      #include <pthread.h>                                                                                                                  
3                                                                             
4      void *TestThread();                                                          
5                                                                             
6      main(int Argc,char *Argv[])                                                  
7      {                                                                            
8          int     i;                                                           
9          pthread_t tid; 
10        
11        //Main thread memory allocation                                                       
12        //char Buf[4096*30+1];                                               
13        //memset(Buf, 0x00, sizeof(Buf));                                    
14                                                                             
15        pthread_create(&tid, NULL, TestThread, NULL);                        
16                                                                                                                                                                                                        
17     }                                                                            
18                                                                             
19     void *TestThread()                                                           
20     {                                                                            
21         int     i;                                                           
22         //Child thread memory allocation                              
23         char Buf[4096*30+1];                                                 
24         printf("sizeof Buf = %d \n",sizeof(Buf));                                
25         memset(Buf, 0x00, sizeof(Buf)); //<---Segfaults here                 
26         usleep(50);                                                          
27                                                                             
28         while(1) sleep(1);                                                   
29                                                                             
30      }                                                                            
$                            
 
Line 25 of test.c tries to allocate (within the child thread) a buffer of size 122881 bytes on the stack; but it will segfault at runtime (as shown in the output below) because it is greater than 32 KB.
$ xlc_r test.c
$ ./a.out
sizeof Buf = 122881
Segmentation fault(coredump)
$
 
Now, if you comment out line 25 and un-comment lines 12 & 13, the test case will succeed at allocating it because the main parent thread uses the stack value that is set via the "ulimit -s" setting. ie, the ulimit stack size is only for the main thread.
 
You may now be wondering, "How can I allocate more than 32 KB for the child threads?". 
 
There are a few ways to achieve this: 
1. Compile your application with -q64 instead of -q32. This will give you 192 KB of stack.
 
eg:
$ xlc_r test.c -q64
$ ./a.out
sizeof Buf = 122881
$
 
                                           
2. Use "malloc()" to allocate the required memory on the heap instead of the stack.
 
eg:
//Replace Line 23 & 25 in test.c with the following respectively:
char* Buf2;
Buf2 = (char*) malloc((4096*30+1) * sizeof(char));
 
 
3. Use the "AIXTHREAD_STK" environment variable to set a bigger pthread stack size
 
eg:
$ export AIXTHREAD_STK=130000; 
$ ./a.out
sizeof Buf = 122881
$
 
Note - More info on AIXTHREAD_STK can be obtained here:
 
                                                                 
4. Use "pthread_attr_setstacksize" to set bigger pthread stack.                                                                                         
 
eg:
//The modified test case would look something like:
$ cat test_mod.c
#include <stdio.h>                                                                                                                 
#include <pthread.h> 
 
void *TestThread();
 
main(int Argc,char *Argv[])
{
        int     i;
        pthread_t tid;
        pthread_attr_t attr;
        size_t  stacksize = 0;
 
        pthread_attr_init( &attr );
        pthread_attr_getstacksize( &attr, &stacksize );
        printf("before stacksize : [%d]\n", stacksize);
        pthread_attr_setstacksize( &attr, 99800000 );
        pthread_attr_getstacksize( &attr, &stacksize );
        printf("after  stacksize : [%d]\n", stacksize);
 
        pthread_create(&tid, &attr, TestThread, NULL);
 
}
void *TestThread()
{
        int     i;
        char Buf[4096*30+1]; 
        printf("sizeof Buf = %d \n",sizeof(Buf)); 
        memset(Buf, 0x20, 4096*40);
 
        while(1) sleep(1);
 
}
$ xlc_r test_mod.c
$ ./a.out
before stacksize : [98304]
after  stacksize : [99800000]
size of Buff=122881
$
 
So next time, keep this in mind before allocating memory from the stack for your multi-threaded application. Feel free to comment if you have any questions/concerns about this topic.

#C/C++-compilers-for-AIX
#C/C++andFortran
1 comment
0 views

Permalink

Comments

Mon July 20, 2015 08:56 AM

Originally posted by: Simon Davitt


I found this a bit late (2 years!) but it is an excellent article. PBC1 stuff.