]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - nptl/allocatestack.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / nptl / allocatestack.c
index 8364406b1bd007aa35aeb3ac1346d1b5fe01f1f4..670cb8ffe65c4ee93e65f79c036229362da03f55 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002-2017 Free Software Foundation, Inc.
+/* Copyright (C) 2002-2019 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -251,8 +251,8 @@ get_cached_stack (size_t *sizep, void **memp)
 
 
 /* Free stacks until cache size is lower than LIMIT.  */
-void
-__free_stacks (size_t limit)
+static void
+free_stacks (size_t limit)
 {
   /* We reduce the size of the cache.  Remove the last entries until
      the size is below the limit.  */
@@ -278,7 +278,7 @@ __free_stacks (size_t limit)
 
          /* Remove this block.  This should never fail.  If it does
             something is really wrong.  */
-         if (munmap (curr->stackblock, curr->stackblock_size) != 0)
+         if (__munmap (curr->stackblock, curr->stackblock_size) != 0)
            abort ();
 
          /* Maybe we have freed enough.  */
@@ -288,6 +288,12 @@ __free_stacks (size_t limit)
     }
 }
 
+/* Free all the stacks on cleanup.  */
+void
+__nptl_stacks_freeres (void)
+{
+  free_stacks (0);
+}
 
 /* Add a stack frame which is not used anymore to the stack.  Must be
    called with the cache lock held.  */
@@ -302,12 +308,11 @@ queue_stack (struct pthread *stack)
 
   stack_cache_actsize += stack->stackblock_size;
   if (__glibc_unlikely (stack_cache_actsize > stack_cache_maxsize))
-    __free_stacks (stack_cache_maxsize);
+    free_stacks (stack_cache_maxsize);
 }
 
 
 static int
-internal_function
 change_stack_perm (struct pthread *pd
 #ifdef NEED_SEPARATE_REGISTER_STACK
                   , size_t pagemask
@@ -328,7 +333,7 @@ change_stack_perm (struct pthread *pd
 #else
 # error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP"
 #endif
-  if (mprotect (stack, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
+  if (__mprotect (stack, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
     return errno;
 
   return 0;
@@ -356,22 +361,49 @@ setup_stack_prot (char *mem, size_t size, char *guard, size_t guardsize,
                  const int prot)
 {
   char *guardend = guard + guardsize;
-#if _STACK_GROWS_DOWN
+#if _STACK_GROWS_DOWN && !defined(NEED_SEPARATE_REGISTER_STACK)
   /* As defined at guard_position, for architectures with downward stack
      the guard page is always at start of the allocated area.  */
-  if (mprotect (guardend, size - guardsize, prot) != 0)
+  if (__mprotect (guardend, size - guardsize, prot) != 0)
     return errno;
 #else
   size_t mprots1 = (uintptr_t) guard - (uintptr_t) mem;
-  if (mprotect (mem, mprots1, prot) != 0)
+  if (__mprotect (mem, mprots1, prot) != 0)
     return errno;
   size_t mprots2 = ((uintptr_t) mem + size) - (uintptr_t) guardend;
-  if (mprotect (guardend, mprots2, prot) != 0)
+  if (__mprotect (guardend, mprots2, prot) != 0)
     return errno;
 #endif
   return 0;
 }
 
+/* Mark the memory of the stack as usable to the kernel.  It frees everything
+   except for the space used for the TCB itself.  */
+static inline void
+__always_inline
+advise_stack_range (void *mem, size_t size, uintptr_t pd, size_t guardsize)
+{
+  uintptr_t sp = (uintptr_t) CURRENT_STACK_FRAME;
+  size_t pagesize_m1 = __getpagesize () - 1;
+#if _STACK_GROWS_DOWN && !defined(NEED_SEPARATE_REGISTER_STACK)
+  size_t freesize = (sp - (uintptr_t) mem) & ~pagesize_m1;
+  assert (freesize < size);
+  if (freesize > PTHREAD_STACK_MIN)
+    __madvise (mem, 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).  */
+  uintptr_t freeblock = (sp + PTHREAD_STACK_MIN + pagesize_m1) & ~pagesize_m1;
+  uintptr_t free_end = (pd - guardsize) & ~pagesize_m1;
+  if (free_end > freeblock)
+    {
+      size_t freesize = free_end - freeblock;
+      assert (freesize < size);
+      __madvise ((void*) freeblock, freesize, MADV_DONTNEED);
+    }
+#endif
+}
+
 /* Returns a usable stack for a new thread either by allocating a
    new stack or reusing a cached stack of sufficient size.
    ATTR must be non-NULL and point to a valid pthread_attr.
@@ -460,12 +492,6 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
       __pthread_multiple_threads = *__libc_multiple_threads_ptr = 1;
 #endif
 
-#ifndef __ASSUME_PRIVATE_FUTEX
-      /* The thread must know when private futexes are supported.  */
-      pd->header.private_futex = THREAD_GETMEM (THREAD_SELF,
-                                               header.private_futex);
-#endif
-
 #ifdef NEED_DL_SYSINFO
       SETUP_THREAD_SYSINFO (pd);
 #endif
@@ -506,6 +532,10 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
       /* 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 (guardsize < attr->guardsize || size + guardsize < guardsize)
+       /* Arithmetic overflow.  */
+       return EINVAL;
+      size += guardsize;
       if (__builtin_expect (size < ((guardsize + __static_tls_size
                                     + MINIMAL_REST_STACK + pagesize_m1)
                                    & ~pagesize_m1),
@@ -530,8 +560,8 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
          /* If a guard page is required, avoid committing memory by first
             allocate with PROT_NONE and then reserve with required permission
             excluding the guard page.  */
-         mem = mmap (NULL, size, (guardsize == 0) ? prot : PROT_NONE,
-                     MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
+         mem = __mmap (NULL, size, (guardsize == 0) ? prot : PROT_NONE,
+                       MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
 
          if (__glibc_unlikely (mem == MAP_FAILED))
            return errno;
@@ -557,7 +587,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
                                            pagesize_m1);
              if (setup_stack_prot (mem, size, guard, guardsize, prot) != 0)
                {
-                 munmap (mem, size);
+                 __munmap (mem, size);
                  return errno;
                }
            }
@@ -580,12 +610,6 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
          __pthread_multiple_threads = *__libc_multiple_threads_ptr = 1;
 #endif
 
-#ifndef __ASSUME_PRIVATE_FUTEX
-         /* The thread must know when private futexes are supported.  */
-         pd->header.private_futex = THREAD_GETMEM (THREAD_SELF,
-                                                   header.private_futex);
-#endif
-
 #ifdef NEED_DL_SYSINFO
          SETUP_THREAD_SYSINFO (pd);
 #endif
@@ -600,7 +624,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
              assert (errno == ENOMEM);
 
              /* Free the stack memory we just allocated.  */
-             (void) munmap (mem, size);
+             (void) __munmap (mem, size);
 
              return errno;
            }
@@ -630,7 +654,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
              if (err != 0)
                {
                  /* Free the stack memory we just allocated.  */
-                 (void) munmap (mem, size);
+                 (void) __munmap (mem, size);
 
                  return err;
                }
@@ -650,7 +674,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
        {
          char *guard = guard_position (mem, size, guardsize, pd,
                                        pagesize_m1);
-         if (mprotect (guard, guardsize, PROT_NONE) != 0)
+         if (__mprotect (guard, guardsize, PROT_NONE) != 0)
            {
            mprot_error:
              lll_lock (stack_cache_lock, LLL_PRIVATE);
@@ -668,7 +692,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
                 of memory caused problems we better do not use it
                 anymore.  Uh, and we ignore possible errors.  There
                 is nothing we could do.  */
-             (void) munmap (mem, size);
+             (void) __munmap (mem, size);
 
              return errno;
            }
@@ -685,20 +709,26 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
          char *oldguard = mem + (((size - pd->guardsize) / 2) & ~pagesize_m1);
 
          if (oldguard < guard
-             && mprotect (oldguard, guard - oldguard, prot) != 0)
+             && __mprotect (oldguard, guard - oldguard, prot) != 0)
            goto mprot_error;
 
-         if (mprotect (guard + guardsize,
+         if (__mprotect (guard + guardsize,
                        oldguard + pd->guardsize - guard - guardsize,
                        prot) != 0)
            goto mprot_error;
 #elif _STACK_GROWS_DOWN
-         if (mprotect ((char *) mem + guardsize, pd->guardsize - guardsize,
+         if (__mprotect ((char *) mem + guardsize, pd->guardsize - guardsize,
                        prot) != 0)
            goto mprot_error;
 #elif _STACK_GROWS_UP
-         if (mprotect ((char *) pd - pd->guardsize,
-                       pd->guardsize - guardsize, prot) != 0)
+         char *new_guard = (char *)(((uintptr_t) pd - guardsize)
+                                    & ~pagesize_m1);
+         char *old_guard = (char *)(((uintptr_t) pd - pd->guardsize)
+                                    & ~pagesize_m1);
+         /* The guard size difference might be > 0, but once rounded
+            to the nearest page the size difference might be zero.  */
+         if (new_guard > old_guard
+             && __mprotect (old_guard, new_guard - old_guard, prot) != 0)
            goto mprot_error;
 #endif
 
@@ -721,7 +751,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
                                  - offsetof (pthread_mutex_t,
                                              __data.__list.__next));
   pd->robust_head.list_op_pending = NULL;
-#ifdef __PTHREAD_MUTEX_HAVE_PREV
+#if __PTHREAD_MUTEX_HAVE_PREV
   pd->robust_prev = &pd->robust_head;
 #endif
   pd->robust_head.list = &pd->robust_head;
@@ -754,7 +784,6 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
 
 
 void
-internal_function
 __deallocate_stack (struct pthread *pd)
 {
   lll_lock (stack_cache_lock, LLL_PRIVATE);
@@ -778,7 +807,6 @@ __deallocate_stack (struct pthread *pd)
 
 
 int
-internal_function
 __make_stacks_executable (void **stack_endp)
 {
   /* First the main thread's stack.  */
@@ -984,7 +1012,6 @@ __find_thread_by_id (pid_t tid)
 
 #ifdef SIGSETXID
 static void
-internal_function
 setxid_mark_thread (struct xid_command *cmdp, struct pthread *t)
 {
   int ch;
@@ -1022,7 +1049,6 @@ setxid_mark_thread (struct xid_command *cmdp, struct pthread *t)
 
 
 static void
-internal_function
 setxid_unmark_thread (struct xid_command *cmdp, struct pthread *t)
 {
   int ch;
@@ -1043,7 +1069,6 @@ setxid_unmark_thread (struct xid_command *cmdp, struct pthread *t)
 
 
 static int
-internal_function
 setxid_signal_thread (struct xid_command *cmdp, struct pthread *t)
 {
   if ((t->cancelhandling & SETXID_BITMASK) == 0)
@@ -1078,8 +1103,13 @@ __nptl_setxid_error (struct xid_command *cmdp, int error)
       if (olderror == error)
        break;
       if (olderror != -1)
-       /* Mismatch between current and previous results.  */
-       abort ();
+       {
+         /* Mismatch between current and previous results.  Save the
+            error value to memory so that is not clobbered by the
+            abort function and preserved in coredumps.  */
+         volatile int xid_err __attribute__((unused)) = error;
+         abort ();
+       }
     }
   while (atomic_compare_and_exchange_bool_acq (&cmdp->error, error, -1));
 }