This is the mail archive of the libc-hacker@sourceware.org mailing list for the glibc project.
Note that libc-hacker is a closed list. You may look at the archives of this list, but subscription and posting are not open.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
The recently announced POWER5+ hardware now supports 4KB, 64KB, and 16KB pages sizes. For large systems used in High Performance Computing or large scale data base applications a larger page size makes the TLB more effective and boosts performance. At this year's OLS there was discussion of adding a kernel option to support 64KB (vs 4KB) as the base page size in these environments. I suspect that a larger base page is an issue for IA64 as well. This raises the possibility that the page size may change depending on which kernel was booted for that machine. This page size will be reported via AT_PAGESZ but currently NPTL pthread_create does not handle the larger pagesize. The attached patch allows PTHREAD_STACK_MIN to remain unchanged and still apply when stackaddr is supplied. But allow the default case to allocate the minimum 2 * pagesize stack (plus guardpage), even when PTHREAD_STACK_MIN is < (2 * pagesize).
2005-10-05 Steven Munroe <sjmunroe@us.ibm.com> * allocatestack.c (allocate_stack): Add support for large page kernels. Handled cases where __default_stacksize is less than 2 * pagesize. * init.c (__pthread_initialize_minimal_internal): Insure that __default_stacksize is at least the greater of PTHREAD_STACK_MIN or (2 * pagesz). * tst-stack2.c (do_test): pthread_create may fail when stacksize is PTHREAD_STACK_MIN, stackaddr is not specified, and PTHREAD_STACK_MIN is < (2 * pagesize). pthread_create should succeed when, stacksize >= PTHREAD_STACK_MIN and stackaddr is supplied. pthread_create() should always succeed with the default pthread_attr_t. diff -urN libc24-cvstip-20050926/nptl/allocatestack.c libc24/nptl/allocatestack.c --- libc24-cvstip-20050926/nptl/allocatestack.c 2005-01-06 16:40:24.000000000 -0600 +++ libc24/nptl/allocatestack.c 2005-10-05 11:31:42.000000000 -0500 @@ -291,7 +291,8 @@ { struct pthread *pd; size_t size; - size_t pagesize_m1 = __getpagesize () - 1; + size_t pagesize = __getpagesize (); + size_t pagesize_m1 = pagesize - 1; void *stacktop; assert (attr != NULL); @@ -390,6 +391,16 @@ void *mem; const int prot = (PROT_READ | PROT_WRITE | ((GL(dl_stack_flags) & PF_X) ? PROT_EXEC : 0)); + + /* Handle the case where the system page size is not the default + and is larger then the default stack size. If so we bump size + up to 2 pages and set the __default_stacksize to be two pages. */ + if ((attr->stacksize == 0) && (size < (2 * pagesize))) + { + size = 2 * pagesize; + if (size > __default_stacksize) + __default_stacksize = size; + } #if COLORING_INCREMENT != 0 /* Add one more page for stack coloring. Don't do it for stacks @@ -406,8 +417,9 @@ /* Make sure the size of the stack is enough for the guard and eventually the thread descriptor. */ guardsize = (attr->guardsize + pagesize_m1) & ~pagesize_m1; - if (__builtin_expect (size < (guardsize + __static_tls_size - + MINIMAL_REST_STACK + pagesize_m1 + 1), + if (__builtin_expect (size < ((guardsize + __static_tls_size + + MINIMAL_REST_STACK + + pagesize_m1) & ~pagesize_m1), 0)) /* The stack is too small (or the guard too large). */ return EINVAL; diff -urN libc24-cvstip-20050926/nptl/init.c libc24/nptl/init.c --- libc24-cvstip-20050926/nptl/init.c 2004-12-27 19:39:50.000000000 -0600 +++ libc24/nptl/init.c 2005-09-28 16:43:20.000000000 -0500 @@ -284,19 +284,25 @@ /* Determine the default allowed stack size. This is the size used in case the user does not specify one. */ struct rlimit limit; + const uintptr_t pagesz = __sysconf (_SC_PAGESIZE); if (getrlimit (RLIMIT_STACK, &limit) != 0 || limit.rlim_cur == RLIM_INFINITY) /* The system limit is not usable. Use an architecture-specific default. */ __default_stacksize = ARCH_STACK_DEFAULT_SIZE; - else if (limit.rlim_cur < PTHREAD_STACK_MIN) - /* The system limit is unusably small. - Use the minimal size acceptable. */ - __default_stacksize = PTHREAD_STACK_MIN; + else if (limit.rlim_cur < PTHREAD_STACK_MIN + || limit.rlim_cur < (2 * pagesz)) + { + /* The system limit is unusably small. + Use the minimal size acceptable. */ + if (PTHREAD_STACK_MIN < (2 * pagesz)) + __default_stacksize = (2 * pagesz); + else + __default_stacksize = PTHREAD_STACK_MIN; + } else { /* Round the resource limit up to page size. */ - const uintptr_t pagesz = __sysconf (_SC_PAGESIZE); __default_stacksize = (limit.rlim_cur + pagesz - 1) & -pagesz; } diff -urN libc24-cvstip-20050926/nptl/tst-stack2.c libc24/nptl/tst-stack2.c --- libc24-cvstip-20050926/nptl/tst-stack2.c 2003-09-03 00:06:52.000000000 -0500 +++ libc24/nptl/tst-stack2.c 2005-10-05 15:42:12.487259896 -0500 @@ -23,6 +23,7 @@ #include <pthread.h> #include <stdlib.h> #include <stdio.h> +#include <unistd.h> static int seen; @@ -38,9 +39,15 @@ { pthread_attr_t attr; pthread_attr_init (&attr); + long pagesize; int result = 0; - int res = pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN); + int res; + + pagesize = sysconf(_SC_PAGESIZE); + printf ("sysconf(_SC_PAGESIZE) = %ld\n", pagesize); + + res = pthread_attr_setstacksize (&attr, PTHREAD_STACK_MIN); if (res) { printf ("pthread_attr_setstacksize failed %d\n", res); @@ -53,6 +60,74 @@ if (res) { printf ("pthread_create failed %d\n", res); + + if ((PTHREAD_STACK_MIN) < (2 * pagesize)) + { + /* This is OK because the system has multiple pages sizes and + it is currently running with pagesize >= PTHREAD_STACK_MIN. */ + puts("PTHREAD_STACK_MIN < (2 * pagesize)"); + seen++; + } + else + result = 1; + } + else + { + res = pthread_join (th, NULL); + if (res) + { + printf ("pthread_join failed %d\n", res); + result = 1; + } + } + + /* However PTHREAD_STACK_MIN should always be valid when stackaddr is set. */ + + void *stack; + size_t size = PTHREAD_STACK_MIN; + + + if (posix_memalign (&stack, getpagesize (), size) != 0) + { + puts ("out of memory while allocating the stack memory"); + return (1); + } + + if (pthread_attr_init (&attr) != 0) + { + puts ("attr_init failed"); + return (1); + } + + if (pthread_attr_setstack (&attr, stack, size) != 0) + { + puts ("attr_setstack failed"); + return (1); + } + + res = pthread_create (&th, &attr, tf, NULL); + if (res) + { + printf ("pthread_create failed %d\n", res); + result = 1; + } + else + { + res = pthread_join (th, NULL); + if (res) + { + printf ("pthread_join failed %d\n", res); + result = 1; + } + } + + /* The default pthread_attr_t should always work, even if the page + size is larger then expected. */ + + res = pthread_create (&th, NULL, tf, NULL); + if (res) + { + printf ("pthread_create failed %d\n", res); result = 1; } else @@ -65,9 +140,9 @@ } } - if (seen != 1) + if (seen != 3) { - printf ("seen %d != 1\n", seen); + printf ("seen %d != 3\n", seen); result = 1; }
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |