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