about summary refs log tree commit diff
path: root/nptl/allocatestack.c
diff options
context:
space:
mode:
authorCarlos O'Donell <carlos@systemhalted.org>2015-08-09 04:17:17 -0400
committerMike Frysinger <vapier@gentoo.org>2016-02-19 12:41:29 -0500
commitd615a47355699d29df01b28a120cef29c8a38091 (patch)
treea60b5cd1dddc6bb30e409601dad08f09a601993b /nptl/allocatestack.c
parent11fca9615fa7b98135d262066db5f4156dd72955 (diff)
downloadglibc-d615a47355699d29df01b28a120cef29c8a38091.tar.gz
glibc-d615a47355699d29df01b28a120cef29c8a38091.tar.xz
glibc-d615a47355699d29df01b28a120cef29c8a38091.zip
nptl: support thread stacks that grow up
Gentoo has been carrying this for all arches since 2.17.

URL: http://bugs.gentoo.org/301642
Diffstat (limited to 'nptl/allocatestack.c')
-rw-r--r--nptl/allocatestack.c20
1 files changed, 13 insertions, 7 deletions
diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c
index c044b205c8..6b42b11d5a 100644
--- a/nptl/allocatestack.c
+++ b/nptl/allocatestack.c
@@ -372,6 +372,13 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
   if (__glibc_unlikely (attr->flags & ATTR_FLAG_STACKADDR))
     {
       uintptr_t adj;
+      char *stackaddr = (char *) attr->stackaddr;
+
+      /* Assume the same layout as the _STACK_GROWS_DOWN case, with struct
+	 pthread at the top of the stack block.  Later we adjust the guard
+	 location and stack address to match the _STACK_GROWS_UP case.  */
+      if (_STACK_GROWS_UP)
+	stackaddr += attr->stacksize;
 
       /* If the user also specified the size of the stack make sure it
 	 is large enough.  */
@@ -381,11 +388,11 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
 
       /* Adjust stack size for alignment of the TLS block.  */
 #if TLS_TCB_AT_TP
-      adj = ((uintptr_t) attr->stackaddr - TLS_TCB_SIZE)
+      adj = ((uintptr_t) stackaddr - TLS_TCB_SIZE)
 	    & __static_tls_align_m1;
       assert (size > adj + TLS_TCB_SIZE);
 #elif TLS_DTV_AT_TP
-      adj = ((uintptr_t) attr->stackaddr - __static_tls_size)
+      adj = ((uintptr_t) stackaddr - __static_tls_size)
 	    & __static_tls_align_m1;
       assert (size > adj);
 #endif
@@ -395,10 +402,10 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
 	 the stack.  It is the user's responsibility to do this if it
 	 is wanted.  */
 #if TLS_TCB_AT_TP
-      pd = (struct pthread *) ((uintptr_t) attr->stackaddr
+      pd = (struct pthread *) ((uintptr_t) stackaddr
 			       - TLS_TCB_SIZE - adj);
 #elif TLS_DTV_AT_TP
-      pd = (struct pthread *) (((uintptr_t) attr->stackaddr
+      pd = (struct pthread *) (((uintptr_t) stackaddr
 				- __static_tls_size - adj)
 			       - TLS_PRE_TCB_SIZE);
 #endif
@@ -410,7 +417,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
       pd->specific[0] = pd->specific_1stblock;
 
       /* Remember the stack-related values.  */
-      pd->stackblock = (char *) attr->stackaddr - size;
+      pd->stackblock = (char *) stackaddr - size;
       pd->stackblock_size = size;
 
       /* This is a user-provided stack.  It will not be queued in the
@@ -634,7 +641,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
 	  char *guard = mem + (((size - guardsize) / 2) & ~pagesize_m1);
 #elif _STACK_GROWS_DOWN
 	  char *guard = mem;
-# elif _STACK_GROWS_UP
+#elif _STACK_GROWS_UP
 	  char *guard = (char *) (((uintptr_t) pd - guardsize) & ~pagesize_m1);
 #endif
 	  if (mprotect (guard, guardsize, PROT_NONE) != 0)
@@ -734,7 +741,6 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
 # endif
 #else
   *stack = pd->stackblock;
-  assert (*stack > 0);
 #endif
 
   return 0;