8. スレッド属性(サンプル)
8.3 サンプル
前述しましたが、スタックサイズの最小値はPTHREAD_STACK_MINによって定義されています。しかし最大値は定義されていません。PTHREAD_STACK_MAXなどといったものはありません。
これはつまり、環境によってスタックサイズが変わる事を意味していると思われ、その環境における最大値を認識してからスタックサイズを変更した方が良いでしょう。
以下のサンプルプログラムは初期値と最小値のスタックサイズを取り出し、初期値に数値を掛け合わせた値をスタックサイズにしてスレッドを実行し、実行可能最大数を割り出しています。また、pthread_attr_setstackを使用し、ヒープから確保したメモリをスレッドのスタックとして利用しています。
私の環境ではプログラムにGNU固有の拡張を有効にする必要がありました(#define _GNU_SOURCEの一文を追記します)。
/* gcc stackaddr.c -o stackaddr -W -Wall -g -lpthread */ #define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <string.h> #include <pthread.h> #include <errno.h> #include <limits.h> void * thread_func1( void * arg ); void * thread_func2( void * arg ); int main( ) { pthread_t thread_id; pthread_attr_t thread_attr; size_t stack_size = 0; size_t guard_size = 0; char * thread_stack = 0; int mul = 0; int status = 0; pthread_attr_init( &thread_attr ); pthread_attr_getstacksize( &thread_attr, &stack_size ); pthread_attr_getguardsize( &thread_attr, &guard_size ); printf( "Default stack size %zd[%zdM]; guard size %zd " "minimum is %u[%uK]\n", stack_size, stack_size >> 20, guard_size, PTHREAD_STACK_MIN, PTHREAD_STACK_MIN >> 10 ); for( mul = 1;; mul ++ ) { status = pthread_attr_setstacksize( &thread_attr, stack_size * mul ); if( status ) { printf( "pthread_attr_setstacksize:[%d][%s]\n", status, strerror( status )); break; } status = pthread_create( &thread_id, &thread_attr, thread_func1, 0 ); if( status ) { printf( "set stack size is %zd [%zdM] " "pthread_create error. [%d][%s]\n", stack_size * mul, stack_size * mul >> 20, status, strerror( status )); break; } pthread_join( thread_id, 0 ); } for( mul = 1;; mul ++ ) { thread_stack = malloc( stack_size * mul ); if( thread_stack == 0 ) { printf( "memory allocate is %zd [%zdM] " "malloc error. [%d][%s]\n", stack_size * mul, stack_size * mul >> 20, errno, strerror( errno )); break; } status = pthread_attr_setstack( &thread_attr, ( void * )thread_stack, stack_size ); if( status ) { printf( "pthread_attr_setstacksize:[%d][%s]\n", status, strerror( status )); break; } status = pthread_create( &thread_id, &thread_attr, thread_func1, ( void * )&stack_size ); if( status ) { printf( "pthread_create:[%d][%s]\n", status, strerror( status )); break; } pthread_join( thread_id, 0 ); free( thread_stack ); } pthread_attr_init( &thread_attr ); pthread_attr_setstacksize( &thread_attr, stack_size ); pthread_create( &thread_id, &thread_attr, thread_func2, 0 ); pthread_join( thread_id, 0 ); thread_stack = malloc( stack_size ); pthread_attr_setstack( &thread_attr, ( void * )thread_stack, stack_size ); pthread_create( &thread_id, &thread_attr, thread_func2, 0 ); pthread_join( thread_id, 0 ); return 0; } void * thread_func1( void * arg ) { ( void )arg; return arg; } void * thread_func2( void * arg ) { ( void )arg; char tmp[0]; printf( "inner thread : [%p]\n", tmp ); return 0; }
私の環境では、下記の通りとなりました。
guest $ ./stack_addr Default stack size 10485760[10M]; guard size 4096 minimum is16384[16k] set stack size is 2023751680 [1930M] pthread_create error.
[12][Cannot allocate memory] memory allocate is 2023751680 [1930M] malloc error.
[12][Cannot allocate memory] inner thread : [0xb7dff3c8] inner thread : [0xb73fd3c8] guest $
上記から、デフォルトスタックサイズは10M、最小スタックサイズは16Kです。最大スタックサイズは1.9G。ヒープも同値となります。

16384[16k]
set stack size is 2023751680 [1930M] pthread_create error.