This is the mail archive of the glibc-cvs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

GNU C Library master sources branch roland/nacl created. glibc-2.21-377-g5d1e814


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, roland/nacl has been created
        at  5d1e814d560986a17c63dd9c2651694f893b428f (commit)

- Log -----------------------------------------------------------------
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=5d1e814d560986a17c63dd9c2651694f893b428f

commit 5d1e814d560986a17c63dd9c2651694f893b428f
Author: Roland McGrath <roland@hack.frob.com>
Date:   Wed May 20 17:15:58 2015 -0700

    foo

diff --git a/ChangeLog b/ChangeLog
index 830d362..6dcb441 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
 2015-05-20  Roland McGrath  <roland@hack.frob.com>
 
+	* sysdeps/nacl/exit-thread.h (__exit_thread): Replace inline
+	function with extern declaration.
+	* sysdeps/nacl/exit-thread.c: New file.
+	* sysdeps/nacl/Makefile [$(subdir) = csu] (sysdep_routines): Add it.
+	* sysdeps/nacl/Versions (libc: GLIBC_PRIVATE): Add __exit_thread.
+
+	* sysdeps/generic/exit-thread.h (__exit_thread): Take new
+	argument DETACHED.
+	* sysdeps/unix/sysv/linux/exit-thread.h (__exit_thread): Likewise.
+	* csu/libc-start.c (LIBC_START_MAIN): Update caller.
+
 	* sysdeps/nacl/pthread-pids.h: New file.
 	* sysdeps/nacl/createthread.c: Include <pthread-pids.h>.
 	(create_thread): Use __nacl_get_tid to initialize PD->tid.
diff --git a/csu/libc-start.c b/csu/libc-start.c
index 0afa7c0..728769e 100644
--- a/csu/libc-start.c
+++ b/csu/libc-start.c
@@ -313,7 +313,7 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
 
       if (! atomic_decrement_and_test (ptr))
 	/* Not much left to do but to exit the thread, not the process.  */
-	__exit_thread ();
+	__exit_thread (false);
     }
 #else
   /* Nothing fancy, just call the function.  */
diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
index 71a5619..dcca1a5 100644
--- a/nptl/pthread_create.c
+++ b/nptl/pthread_create.c
@@ -433,8 +433,10 @@ START_THREAD_DEFN
   if (freesize > PTHREAD_STACK_MIN)
     __madvise (pd->stackblock, freesize - PTHREAD_STACK_MIN, MADV_DONTNEED);
 
+  const bool detached = IS_DETACHED (pd);
+
   /* If the thread is detached free the TCB.  */
-  if (IS_DETACHED (pd))
+  if (detached)
     /* Free the TCB.  */
     __free_tcb (pd);
   else if (__glibc_unlikely (pd->cancelhandling & SETXID_BITMASK))
@@ -457,7 +459,7 @@ START_THREAD_DEFN
 
      The exit code is zero since in case all threads exit by calling
      'pthread_exit' the exit status must be 0 (zero).  */
-  __exit_thread ();
+  __exit_thread (detached);
 
   /* NOTREACHED */
 }
diff --git a/sysdeps/nacl/exit-thread.h b/sysdeps/arm/nacl/exit-thread.c
similarity index 56%
copy from sysdeps/nacl/exit-thread.h
copy to sysdeps/arm/nacl/exit-thread.c
index a08a5b1..ed5fc7c 100644
--- a/sysdeps/nacl/exit-thread.h
+++ b/sysdeps/arm/nacl/exit-thread.c
@@ -1,4 +1,4 @@
-/* Call to terminate the current thread.  NaCl version.
+/* Call to terminate the current thread.  NaCl/ARM version.
    Copyright (C) 2015 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -16,20 +16,17 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <stddef.h>
-#include <nacl-interfaces.h>
-
-/* This causes the current thread to exit, without affecting other
-   threads in the process if there are any.  If there are no other
-   threads left, then this has the effect of _exit (0).  */
-
-static inline void __attribute__ ((noreturn, always_inline, unused))
-__exit_thread (void)
+/* This bit is machine-specific: Switch stacks to SP and call FUNC (ARG).  */
+static void __attribute__ ((noreturn))
+call_on_stack (void *sp, void *func, void *arg)
 {
-  __nacl_irt_thread.thread_exit (NULL);
-
-  /* That never returns unless something is severely and unrecoverably wrong.
-     If it ever does, try to make sure we crash.  */
-  while (1)
-    __builtin_trap ();
+  register void *r0 asm ("r0") = arg;
+  asm volatile ("bic sp, %[sp], %[dmask]\n"
+                "sfi_blx %[func]"
+                :
+                : [sp] "r" (sp), [func] "r" (func), "r" (r0),
+                  [dmask] "i" (0xc0000000));
+  __builtin_trap ();
 }
+
+#include <sysdeps/nacl/exit-thread.c>
diff --git a/sysdeps/generic/exit-thread.h b/sysdeps/generic/exit-thread.h
index 787029a..d0f1a46 100644
--- a/sysdeps/generic/exit-thread.h
+++ b/sysdeps/generic/exit-thread.h
@@ -16,12 +16,16 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-/* This causes the current thread to exit, without affecting other
-   threads in the process if there are any.  If there are no other
-   threads left, then this has the effect of _exit (0).  */
+#include <stdbool.h>
+
+/* This causes the current thread to exit, without affecting other threads
+   in the process if there are any.  If there are no other threads left,
+   then this has the effect of _exit (0).  If DETACHED is true, then the
+   TCB returned by THREAD_SELF has been reclaimed and must not be examined
+   or touched.  */
 
 static inline void __attribute__ ((noreturn, always_inline, unused))
-__exit_thread (void)
+__exit_thread (bool detached)
 {
   while (1)
     asm ("write me!");
diff --git a/sysdeps/nacl/Makefile b/sysdeps/nacl/Makefile
index b51156b..a8e737c 100644
--- a/sysdeps/nacl/Makefile
+++ b/sysdeps/nacl/Makefile
@@ -108,7 +108,7 @@ test-wrapper-env = $(test-wrapper-env-only)
 test-wrapper = $(test-wrapper-env) --
 
 ifeq ($(subdir),csu)
-sysdep_routines += nacl_interface_query \
+sysdep_routines += nacl_interface_query exit-thread \
 		   nacl-interfaces $(call nacl-routines-of,libc)
 endif
 
diff --git a/sysdeps/nacl/Versions b/sysdeps/nacl/Versions
index 4ac56c2..d2b361e 100644
--- a/sysdeps/nacl/Versions
+++ b/sysdeps/nacl/Versions
@@ -15,6 +15,7 @@ libc {
     __libc_open;
     __libc_close;
     __libc_fork;
+    __exit_thread;
 
     __nacl_irt_*;
   }
diff --git a/sysdeps/nacl/exit-thread.c b/sysdeps/nacl/exit-thread.c
new file mode 100644
index 0000000..6a1b60b
--- /dev/null
+++ b/sysdeps/nacl/exit-thread.c
@@ -0,0 +1,142 @@
+/* Call to terminate the current thread.  NaCl version.
+   Copyright (C) 2015 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
+   <http://www.gnu.org/licenses/>.  */
+
+#include <exit-thread.h>
+#include <lowlevellock.h>
+#include <nacl-interfaces.h>
+#include <pthread-functions.h>
+#include <stdbool.h>
+#include <sysdep.h>
+#include <tls.h>
+#include <atomic.h>
+
+
+/* A sysdeps/CPU/nacl/exit-thread.c file defines this function
+   and then #include's this file.  */
+static void call_on_stack (void *sp, void *func, void *arg)
+  __attribute__ ((noreturn));
+
+
+static void __attribute__ ((noreturn))
+do_thread_exit (volatile int32_t *stack_flag)
+{
+  __nacl_irt_thread.thread_exit ((int32_t *) stack_flag);
+
+  /* That never returns unless something is severely and unrecoverably
+     wrong.  If it ever does, try to make sure we crash.  */
+  while (1)
+    __builtin_trap ();
+}
+
+
+static bool
+multiple_threads (void)
+{
+#ifdef SHARED
+  unsigned int *ptr_nthreads = __libc_pthread_functions.ptr_nthreads;
+  PTR_DEMANGLE (ptr_nthreads);
+#else
+  extern unsigned int __nptl_nthreads __attribute ((weak));
+  unsigned int *const ptr_nthreads = &__nptl_nthreads;
+  if (ptr_nthreads == NULL)
+    return false;
+#endif
+  return *ptr_nthreads > 1;
+}
+
+
+union exit_stack
+{
+  char stack[256] __attribute__ ((aligned (16)));
+  struct
+  {
+    volatile int32_t flag;
+    bool initialized;
+  };
+};
+typedef union exit_stack exit_stack_t;
+
+static exit_stack_t initial_exit_stack;
+static int exit_stack_lock = LLL_LOCK_INITIALIZER;
+
+static exit_stack_t *
+get_exit_stack (void)
+{
+  exit_stack_t *result;
+
+  lll_lock (exit_stack_lock, LLL_PRIVATE);
+
+  if (!initial_exit_stack.initialized)
+    {
+      initial_exit_stack.initialized = true;
+      atomic_store_relaxed (&initial_exit_stack.flag, 1);
+    }
+
+  while (atomic_load_relaxed (&initial_exit_stack.flag) != 0)
+    {
+      lll_unlock (exit_stack_lock, LLL_PRIVATE);
+      __nacl_irt_basic.sched_yield ();
+      lll_lock (exit_stack_lock, LLL_PRIVATE);
+    }
+
+  result = &initial_exit_stack;
+
+  atomic_store_relaxed (&result->flag, 1);
+
+  lll_unlock (exit_stack_lock, LLL_PRIVATE);
+
+  return result;
+}
+
+
+static void __attribute__ ((noreturn))
+exit_on_exit_stack (exit_stack_t *stack)
+{
+  struct pthread *pd = THREAD_SELF;
+
+  /* Mark the thread as having exited and wake anybody waiting for it.
+     After this, both PD itself and its real stack will be reclaimed
+     and it's not safe to touch or examine them.  */
+  pd->tid = 0;
+  lll_futex_wake (&pd->tid, 1, LLL_PRIVATE);
+
+  /* Now we can exit for real, and get off this exit stack.  The system
+     will clear the flag some time after the exit stack is guaranteed not
+     to be in use.  */
+  do_thread_exit (&stack->flag);
+}
+
+static void __attribute__ ((noreturn))
+exit_off_stack (void)
+{
+  exit_stack_t *stack = get_exit_stack ();
+
+  call_on_stack (stack + 1, &exit_on_exit_stack, stack);
+}
+
+void
+__exit_thread (bool detached)
+{
+  if (detached || !multiple_threads ())
+    /* There is no other thread that cares when we exit, so life is simple.  */
+    do_thread_exit (NULL);
+  else
+    /* We must exit in a way that wakes up pthread_join,
+       i.e. clears and futex-wakes THREAD_SELF->tid.  */
+    exit_off_stack ();
+}
diff --git a/sysdeps/nacl/exit-thread.h b/sysdeps/nacl/exit-thread.h
index a08a5b1..b0cce7d 100644
--- a/sysdeps/nacl/exit-thread.h
+++ b/sysdeps/nacl/exit-thread.h
@@ -16,20 +16,12 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <stddef.h>
-#include <nacl-interfaces.h>
+#include <stdbool.h>
 
-/* This causes the current thread to exit, without affecting other
-   threads in the process if there are any.  If there are no other
-   threads left, then this has the effect of _exit (0).  */
+/* This causes the current thread to exit, without affecting other threads
+   in the process if there are any.  If there are no other threads left,
+   then this has the effect of _exit (0).  If DETACHED is true, then the
+   TCB returned by THREAD_SELF has been reclaimed and must not be examined
+   or touched.  */
 
-static inline void __attribute__ ((noreturn, always_inline, unused))
-__exit_thread (void)
-{
-  __nacl_irt_thread.thread_exit (NULL);
-
-  /* That never returns unless something is severely and unrecoverably wrong.
-     If it ever does, try to make sure we crash.  */
-  while (1)
-    __builtin_trap ();
-}
+extern void __exit_thread (bool detached) __attribute__ ((noreturn));
diff --git a/sysdeps/unix/sysv/linux/exit-thread.h b/sysdeps/unix/sysv/linux/exit-thread.h
index e5392f7..c342695 100644
--- a/sysdeps/unix/sysv/linux/exit-thread.h
+++ b/sysdeps/unix/sysv/linux/exit-thread.h
@@ -16,6 +16,7 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#include <stdbool.h>
 #include <sysdep.h>
 
 /* This causes the current thread to exit, without affecting other
@@ -23,7 +24,7 @@
    threads left, then this has the effect of _exit (0).  */
 
 static inline void __attribute__ ((noreturn, always_inline, unused))
-__exit_thread (void)
+__exit_thread (bool detached __attribute__ ((unused)))
 {
   /* Doing this in a loop is mostly just to satisfy the compiler that the
      function really qualifies as noreturn.  It also means that in some

-----------------------------------------------------------------------


hooks/post-receive
-- 
GNU C Library master sources


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]