diff -pruN glibc-2.17-c758a686/csu/libc-start.c glibc-2.17-c758a686.new/csu/libc-start.c --- glibc-2.17-c758a686/csu/libc-start.c 2012-12-25 08:32:13.000000000 +0530 +++ glibc-2.17-c758a686.new/csu/libc-start.c 2013-07-30 11:46:44.571901690 +0530 @@ -32,7 +32,7 @@ extern int __libc_multiple_libcs; #include #ifndef SHARED # include -extern void __pthread_initialize_minimal (void); +extern void __pthread_initialize_minimal (int, char **, char **); # ifndef THREAD_SET_STACK_GUARD /* Only exported for architectures that don't store the stack guard canary in thread local area. */ @@ -175,7 +175,7 @@ LIBC_START_MAIN (int (*main) (int, char /* Initialize the thread library at least a bit since the libgcc functions are using thread functions if these are available and we need to setup errno. */ - __pthread_initialize_minimal (); + __pthread_initialize_minimal (argc, argv, __environ); /* Set up the stack checker's canary. */ uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard (_dl_random); diff -pruN glibc-2.17-c758a686/csu/libc-tls.c glibc-2.17-c758a686.new/csu/libc-tls.c --- glibc-2.17-c758a686/csu/libc-tls.c 2012-12-25 08:32:13.000000000 +0530 +++ glibc-2.17-c758a686.new/csu/libc-tls.c 2013-07-30 11:46:44.572901690 +0530 @@ -243,7 +243,7 @@ _dl_tls_setup (void) not used. */ void __attribute__ ((weak)) -__pthread_initialize_minimal (void) +__pthread_initialize_minimal (int argc, char **argv, char **envp) { __libc_setup_tls (TLS_INIT_TCB_SIZE, TLS_INIT_TCB_ALIGN); } diff -pruN glibc-2.17-c758a686/nptl/Makefile glibc-2.17-c758a686.new/nptl/Makefile --- glibc-2.17-c758a686/nptl/Makefile 2013-07-30 11:46:34.909902026 +0530 +++ glibc-2.17-c758a686.new/nptl/Makefile 2013-07-30 11:46:44.573901690 +0530 @@ -201,7 +201,7 @@ CFLAGS-pt-system.c = -fexceptions tests = tst-typesizes \ - tst-attr1 tst-attr2 tst-attr3 \ + tst-attr1 tst-attr2 tst-attr3 tst-default-attr \ tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 tst-mutex5 tst-mutex6 \ tst-mutex7 tst-mutex8 tst-mutex9 tst-mutex5a tst-mutex7a \ tst-mutexpi1 tst-mutexpi2 tst-mutexpi3 tst-mutexpi4 tst-mutexpi5 \ @@ -276,6 +276,13 @@ gen-as-const-headers = pthread-errnos.sy LDFLAGS-pthread.so = -Wl,--enable-new-dtags,-z,nodelete,-z,initfirst +# The size is 1MB + 4KB. The extra 4KB has been added to prevent allocatestack +# from resizing the input size to avoid the 64K aliasing conflict on Intel +# processors. +DEFAULT_STACKSIZE=1052672 +CFLAGS-tst-default-attr.c = -DDEFAULT_STACKSIZE=$(DEFAULT_STACKSIZE) +tst-default-attr-ENV = GLIBC_PTHREAD_STACKSIZE=$(DEFAULT_STACKSIZE) + include ../Makeconfig ifeq ($(have-forced-unwind),yes) diff -pruN glibc-2.17-c758a686/nptl/nptl-init.c glibc-2.17-c758a686.new/nptl/nptl-init.c --- glibc-2.17-c758a686/nptl/nptl-init.c 2013-07-30 11:46:35.112902019 +0530 +++ glibc-2.17-c758a686.new/nptl/nptl-init.c 2013-07-30 11:46:44.601901689 +0530 @@ -35,6 +35,7 @@ #include #include #include +#include /* Size and alignment of static TLS block. */ @@ -276,8 +277,28 @@ extern void **__libc_dl_error_tsd (void) /* This can be set by the debugger before initialization is complete. */ static bool __nptl_initial_report_events __attribute_used__; +/* Validate and set the default stacksize. */ +static void +set_default_stacksize (size_t stacksize) +{ + if (stacksize < PTHREAD_STACK_MIN) + stacksize = PTHREAD_STACK_MIN; + + /* Make sure it meets the minimum size that allocate_stack + (allocatestack.c) will demand, which depends on the page size. */ + const uintptr_t pagesz = GLRO(dl_pagesize); + const size_t minstack = pagesz + __static_tls_size + MINIMAL_REST_STACK; + + if (stacksize < minstack) + stacksize = minstack; + + /* Round the resource limit up to page size. */ + stacksize = ALIGN_UP (stacksize, pagesz); + __default_pthread_attr.stacksize = stacksize; +} + void -__pthread_initialize_minimal_internal (void) +__pthread_initialize_minimal_internal (int argc, char **argv, char **envp) { #ifndef SHARED /* Unlike in the dynamically linked case the dynamic linker has not @@ -401,29 +422,44 @@ __pthread_initialize_minimal_internal (v __static_tls_size = roundup (__static_tls_size, static_tls_align); - /* Determine the default allowed stack size. This is the size used - in case the user does not specify one. */ - struct rlimit limit; - if (__getrlimit (RLIMIT_STACK, &limit) != 0 - || limit.rlim_cur == RLIM_INFINITY) - /* The system limit is not usable. Use an architecture-specific - default. */ - limit.rlim_cur = ARCH_STACK_DEFAULT_SIZE; - else if (limit.rlim_cur < PTHREAD_STACK_MIN) - /* The system limit is unusably small. - Use the minimal size acceptable. */ - limit.rlim_cur = PTHREAD_STACK_MIN; + /* Initialize the environment. libc.so gets initialized after us due to a + circular dependency and hence __environ is not available otherwise. */ + __environ = envp; - /* Make sure it meets the minimum size that allocate_stack - (allocatestack.c) will demand, which depends on the page size. */ - const uintptr_t pagesz = GLRO(dl_pagesize); - const size_t minstack = pagesz + __static_tls_size + MINIMAL_REST_STACK; - if (limit.rlim_cur < minstack) - limit.rlim_cur = minstack; +#ifndef SHARED + __libc_init_secure (); +#endif - /* Round the resource limit up to page size. */ - limit.rlim_cur = (limit.rlim_cur + pagesz - 1) & -pagesz; - __default_pthread_attr.stacksize = limit.rlim_cur; + /* Get the default stack size from the environment variable if it is set and + is valid. */ + size_t stacksize = 0; + char *envval = __libc_secure_getenv ("GLIBC_PTHREAD_STACKSIZE"); + + if (__builtin_expect (envval != NULL && envval[0] != '\0', 0)) + { + char *env_conv = envval; + size_t ret = strtoul (envval, &env_conv, 0); + + if (*env_conv == '\0' && env_conv != envval) + stacksize = ret; + } + + if (stacksize == 0) + { + /* Determine the default allowed stack size. */ + struct rlimit limit; + if (__getrlimit (RLIMIT_STACK, &limit) != 0 + || limit.rlim_cur == RLIM_INFINITY) + /* The system limit is not usable. Use an architecture-specific + default. */ + stacksize = ARCH_STACK_DEFAULT_SIZE; + else + stacksize = limit.rlim_cur; + } + + /* Finally, set the default stack size. This size is used when the user does + not specify a stack size during thread creation. */ + set_default_stacksize (stacksize); __default_pthread_attr.guardsize = GLRO (dl_pagesize); #ifdef SHARED diff -pruN glibc-2.17-c758a686/nptl/tst-default-attr.c glibc-2.17-c758a686.new/nptl/tst-default-attr.c --- glibc-2.17-c758a686/nptl/tst-default-attr.c 1970-01-01 05:30:00.000000000 +0530 +++ glibc-2.17-c758a686.new/nptl/tst-default-attr.c 2013-07-30 11:46:44.601901689 +0530 @@ -0,0 +1,109 @@ +/* Verify that default stack size gets set correctly from the environment + variable. + + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include +#include +#include + +#define RETURN_IF_FAIL(f, ...) \ + ({ \ + int ret = f (__VA_ARGS__); \ + if (ret != 0) \ + { \ + printf ("%s:%d: %s returned %d (errno = %d)\n", __FILE__, __LINE__, \ + #f, ret, errno); \ + return ret; \ + } \ + }) + +/* DEFAULT_STACKSIZE macro is defined in the Makefile. */ +static size_t stacksize = DEFAULT_STACKSIZE; + +static int +verify_stacksize_result (pthread_attr_t *attr) +{ + size_t stack; + + RETURN_IF_FAIL (pthread_attr_getstacksize, attr, &stack); + + if (stacksize != stack) + { + printf ("failed to set default stacksize (%zu, %zu)\n", stacksize, stack); + return 1; + } + + return 0; +} + +static void * +thr (void *unused __attribute__ ((unused))) +{ + pthread_attr_t attr; + int ret; + + memset (&attr, 0xab, sizeof attr); + /* To verify that the attributes actually got applied. */ + if ((ret = pthread_getattr_np (pthread_self (), &attr)) != 0) + { + printf ("pthread_getattr_np failed: %s\n", strerror (ret)); + goto out; + } + + ret = verify_stacksize_result (&attr); + +out: + return (void *) (uintptr_t) ret; +} + +static int +run_threads (void) +{ + pthread_t t; + void *tret = NULL; + + /* Run twice to ensure that the attributes do not get overwritten in the + first run somehow. */ + for (int i = 0; i < 2; i++) + { + RETURN_IF_FAIL (pthread_create, &t, NULL, thr, NULL); + RETURN_IF_FAIL (pthread_join, t, &tret); + + if (tret != NULL) + { + puts ("Thread failed"); + return 1; + } + } + + return 0; +} + +static int +do_test (void) +{ + RETURN_IF_FAIL (run_threads); + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c"