/************************************************ Written by NAKAMURA Minoru, 2004.03.12 ************************************************/ #define _GNU_SOURCE #include #include #include #include #include #include typedef int (*PTHR_GETATTR_NP_FUNC)(pthread_t, pthread_attr_t *); typedef int (*PTHR_ATTR_GETSTACKBASE_FUNC)(pthread_attr_t *, void**); typedef int (*PTHR_ATTR_GETSTACKSIZE_FUNC)(pthread_attr_t *, size_t*); typedef int (*PTHR_ATTR_GETSTACK_FUNC)(pthread_attr_t *, void** stackaddr, size_t* stacksize); PTHR_GETATTR_NP_FUNC pthr_getattr_np_func; PTHR_ATTR_GETSTACKBASE_FUNC pthr_attr_getstackaddr_func; PTHR_ATTR_GETSTACKSIZE_FUNC pthr_attr_getstacksize_func; PTHR_ATTR_GETSTACK_FUNC pthr_attr_getstack_func; #define INITIAL_THREAD_STACK_END ((char*)0xC0000000) int get_linux_stack_info(void** stackaddr, size_t* stacksize) { char dummy; char* p = &dummy; struct rlimit rlim; getrlimit(RLIMIT_STACK, &rlim); size_t default_stack_size = (size_t)rlim.rlim_cur ; if (INITIAL_THREAD_STACK_END - default_stack_size <= p && p <= INITIAL_THREAD_STACK_END) { *stackaddr = (void*)(INITIAL_THREAD_STACK_END - default_stack_size); *stacksize = default_stack_size; return 0; } else { pthr_getattr_np_func = (PTHR_GETATTR_NP_FUNC) dlsym( NULL, "pthread_getattr_np" ); if (!pthr_getattr_np_func) { *stackaddr = (void*)( (size_t)p & (2 * 1024 * 1024 - 1)); *stacksize = 2 * 1024 * 1024; return 0; } else { pthread_attr_t attr; pthread_attr_init(&attr); if (!pthr_getattr_np_func(pthread_self(), &attr)) { pthr_attr_getstackaddr_func = (PTHR_ATTR_GETSTACKBASE_FUNC) dlsym(NULL, "pthread_attr_getstackaddr" ); pthr_attr_getstacksize_func = (PTHR_ATTR_GETSTACKSIZE_FUNC) dlsym(NULL, "pthread_attr_getstacksize" ); pthr_attr_getstack_func = (PTHR_ATTR_GETSTACK_FUNC) dlsym(NULL, "pthread_attr_getstack" ); if (pthr_attr_getstack_func) { int ret; ret = pthr_attr_getstack_func(&attr, stackaddr, stacksize); pthread_attr_destroy(&attr); return ret; } else if (pthr_attr_getstackaddr_func && pthr_attr_getstacksize_func) { int ret = 0; ret = pthr_attr_getstackaddr_func(&attr, stackaddr) || pthr_attr_getstacksize_func(&attr, stacksize); pthread_attr_destroy(&attr); return ret; } } pthread_attr_destroy(&attr); } } return EACCES; } #if 0 /* for test */ #include static void* thread_routine(void*) { void* stackbase = 0; size_t stacksize = 0; get_linux_stack_info( &stackbase, &stacksize ); printf("base = %p size = %uK\n", stackbase, (int)stacksize / 1024); return 0; } int main(int argc, char** argv) { pthread_t pid; pthread_create( &pid, NULL, thread_routine, NULL ); void* data; pthread_join( pid, &data); } #endif