]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
nptl: support thread stacks that grow up
authorCarlos O'Donell <carlos@systemhalted.org>
Sun, 9 Aug 2015 08:17:17 +0000 (04:17 -0400)
committerMike Frysinger <vapier@gentoo.org>
Fri, 19 Feb 2016 17:41:29 +0000 (12:41 -0500)
Gentoo has been carrying this for all arches since 2.17.

URL: http://bugs.gentoo.org/301642

ChangeLog
nptl/allocatestack.c
nptl/pthread_create.c
nptl/pthread_getattr_np.c

index 276334210004c7d6ab13a9b4b48f2b8e9eab012f..c9cdcf4e1a7d5bbf6b7ade2b75094639f00bd755 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2016-02-19  Carlos O'Donell  <carlos@systemhalted.org>
+
+       * nptl/allocatestack.c (allocate_stack): Declare new stackaddr,
+       assign attr->stackaddr to it, and adjust it down when
+       _STACK_GROWS_UP.  Change all attr->stackaddr to stackaddr.
+       [_STACK_GROWS_UP]: Delete assert.
+       * nptl/pthread_create.c (START_THREAD_DEFN) [!_STACK_GROWS_DOWN]:
+       Implement stack grows up logic.
+       * nptl/pthread_getattr_np.c (pthread_getattr_np): Implement
+       stack grows up logic.
+
 2016-02-19  Adhemerval Zanella  <adhemerval.zanella@linaro.org>
 
        * NEWS: Update with 2.24 template.
index c044b205c8777ca0bbe4359a634091d444968757..6b42b11d5a77848a15a557efddddf2205d95c2ca 100644 (file)
@@ -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;
index 521604173325fdc222599f2902f4c1d796b8ef5d..a834063ad51ebd63b582ffb8b12f30f56b6ddc97 100644 (file)
@@ -427,12 +427,25 @@ START_THREAD_DEFN
 #ifdef _STACK_GROWS_DOWN
   char *sp = CURRENT_STACK_FRAME;
   size_t freesize = (sp - (char *) pd->stackblock) & ~pagesize_m1;
-#else
-# error "to do"
-#endif
   assert (freesize < pd->stackblock_size);
   if (freesize > PTHREAD_STACK_MIN)
     __madvise (pd->stackblock, freesize - PTHREAD_STACK_MIN, MADV_DONTNEED);
+#else
+  /* Page aligned start of memory to free (higher than or equal
+     to current sp plus the minimum stack size).  */
+  void *freeblock = (void*)((size_t)(CURRENT_STACK_FRAME
+                                    + PTHREAD_STACK_MIN
+                                    + pagesize_m1)
+                                   & ~pagesize_m1);
+  char *free_end = (char *) (((uintptr_t) pd - pd->guardsize) & ~pagesize_m1);
+  /* Is there any space to free?  */
+  if (free_end > (char *)freeblock)
+    {
+      size_t freesize = (size_t)(free_end - (char *)freeblock);
+      assert (freesize < pd->stackblock_size);
+      __madvise (freeblock, freesize, MADV_DONTNEED);
+    }
+#endif
 
   /* If the thread is detached free the TCB.  */
   if (IS_DETACHED (pd))
index 8207cdca7b75dc6f506832427f2be8a779e1ff9e..fb906f0484f18184058b74e397cba92081870398 100644 (file)
@@ -58,7 +58,11 @@ pthread_getattr_np (pthread_t thread_id, pthread_attr_t *attr)
   if (__glibc_likely (thread->stackblock != NULL))
     {
       iattr->stacksize = thread->stackblock_size;
+#if _STACK_GROWS_DOWN
       iattr->stackaddr = (char *) thread->stackblock + iattr->stacksize;
+#else
+      iattr->stackaddr = (char *) thread->stackblock;
+#endif
     }
   else
     {
@@ -103,7 +107,9 @@ pthread_getattr_np (pthread_t thread_id, pthread_attr_t *attr)
 
              char *line = NULL;
              size_t linelen = 0;
+#if _STACK_GROWS_DOWN
              uintptr_t last_to = 0;
+#endif
 
              while (! feof_unlocked (fp))
                {
@@ -127,17 +133,24 @@ pthread_getattr_np (pthread_t thread_id, pthread_attr_t *attr)
                         stack extension request.  */
                      iattr->stacksize = (iattr->stacksize
                                          & -(intptr_t) GLRO(dl_pagesize));
-
+#if _STACK_GROWS_DOWN
                      /* The limit might be too high.  */
                      if ((size_t) iattr->stacksize
                          > (size_t) iattr->stackaddr - last_to)
                        iattr->stacksize = (size_t) iattr->stackaddr - last_to;
-
+#else
+                     /* The limit might be too high.  */
+                     if ((size_t) iattr->stacksize
+                         > to - (size_t) iattr->stackaddr)
+                       iattr->stacksize = to - (size_t) iattr->stackaddr;
+#endif
                      /* We succeed and no need to look further.  */
                      ret = 0;
                      break;
                    }
+#if _STACK_GROWS_DOWN
                  last_to = to;
+#endif
                }
 
              free (line);