summary refs log tree commit diff
path: root/nptl/allocatestack.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2005-10-01 17:20:34 +0000
committerUlrich Drepper <drepper@redhat.com>2005-10-01 17:20:34 +0000
commitdff9a7a163e9f5e28f36f9a701acf74f8f9d7968 (patch)
treeff9dbb35ab56c666e5d3f2a22bd067a8cf1fd54b /nptl/allocatestack.c
parent2ff89ea46f2c817ad7dd5ce5dc0cc1119da861b6 (diff)
downloadglibc-dff9a7a163e9f5e28f36f9a701acf74f8f9d7968.tar.gz
glibc-dff9a7a163e9f5e28f36f9a701acf74f8f9d7968.tar.xz
glibc-dff9a7a163e9f5e28f36f9a701acf74f8f9d7968.zip
2005-10-01 Ulrich Drepper <drepper@redhat.com>
            Jakub Jelinek  <jakub@redhat.com>

	* descr.h: Define SETXID_BIT and SETXID_BITMASK.  Adjust
	CANCEL_RESTMASK.
	(struct pthread): Move specific_used field to avoid padding.
	Add setxid_futex field.
	* init.c (sighandler_setxid): Reset setxid flag and release the
	setxid futex.
	* allocatestack.c (setxid_signal_thread): New function.  Broken
	out of the bodies of the two loops in __nptl_setxid.  For undetached
	threads check whether they are exiting and if yes, don't send a signal.
	(__nptl_setxid): Simplify loops by using setxid_signal_thread.
	* pthread_create.c (start_thread): For undetached threads, check
	whether setxid bit is set.  If yes, wait until signal has been
	processed.

	* allocatestack.c (STACK_VARIABLES): Initialize them.
	* pthread_create.c (__pthread_create_2_1): Initialize pd.
Diffstat (limited to 'nptl/allocatestack.c')
-rw-r--r--nptl/allocatestack.c92
1 files changed, 49 insertions, 43 deletions
diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c
index fcb6c6e475..bb27c180e6 100644
--- a/nptl/allocatestack.c
+++ b/nptl/allocatestack.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2005
+   Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -33,7 +34,7 @@
 #ifndef NEED_SEPARATE_REGISTER_STACK
 
 /* Most architectures have exactly one stack pointer.  Some have more.  */
-# define STACK_VARIABLES void *stackaddr
+# define STACK_VARIABLES void *stackaddr = NULL
 
 /* How to pass the values to the 'create_thread' function.  */
 # define STACK_VARIABLES_ARGS stackaddr
@@ -52,7 +53,7 @@
 
 /* We need two stacks.  The kernel will place them but we have to tell
    the kernel about the size of the reserved address space.  */
-# define STACK_VARIABLES void *stackaddr; size_t stacksize
+# define STACK_VARIABLES void *stackaddr = NULL; size_t stacksize = 0
 
 /* How to pass the values to the 'create_thread' function.  */
 # define STACK_VARIABLES_ARGS stackaddr, stacksize
@@ -817,6 +818,45 @@ __find_thread_by_id (pid_t tid)
 }
 #endif
 
+
+static void
+internal_function
+setxid_signal_thread (struct xid_command *cmdp, struct pthread *t)
+{
+  if (! IS_DETACHED (t))
+    {
+      int ch;
+      do
+	{
+	  ch = t->cancelhandling;
+
+	  /* If the thread is exiting right now, ignore it.  */
+	  if ((ch & EXITING_BITMASK) != 0)
+	    return;
+	}
+      while (atomic_compare_and_exchange_val_acq (&t->cancelhandling,
+						  ch | SETXID_BITMASK, ch));
+    }
+
+  int val;
+#if __ASSUME_TGKILL
+  val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid),
+			  t->tid, SIGSETXID);
+#else
+# ifdef __NR_tgkill
+  val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid),
+			  t->tid, SIGSETXID);
+  if (INTERNAL_SYSCALL_ERROR_P (val, err)
+      && INTERNAL_SYSCALL_ERRNO (val, err) == ENOSYS)
+# endif
+    val = INTERNAL_SYSCALL (tkill, err, 2, t->tid, SIGSETXID);
+#endif
+
+  if (!INTERNAL_SYSCALL_ERROR_P (val, err))
+    atomic_increment (&cmdp->cntr);
+}
+
+
 int
 attribute_hidden
 __nptl_setxid (struct xid_command *cmdp)
@@ -836,54 +876,20 @@ __nptl_setxid (struct xid_command *cmdp)
   list_for_each (runp, &stack_used)
     {
       struct pthread *t = list_entry (runp, struct pthread, list);
-      if (t != self)
-	{
-	  int val;
-#if __ASSUME_TGKILL
-	  val = INTERNAL_SYSCALL (tgkill, err, 3,
-				  THREAD_GETMEM (THREAD_SELF, pid),
-				  t->tid, SIGSETXID);
-#else
-# ifdef __NR_tgkill
-	  val = INTERNAL_SYSCALL (tgkill, err, 3,
-				  THREAD_GETMEM (THREAD_SELF, pid),
-				  t->tid, SIGSETXID);
-	  if (INTERNAL_SYSCALL_ERROR_P (val, err)
-	      && INTERNAL_SYSCALL_ERRNO (val, err) == ENOSYS)
-# endif
-	    val = INTERNAL_SYSCALL (tkill, err, 2, t->tid, SIGSETXID);
-#endif
+      if (t == self)
+	continue;
 
-	  if (!INTERNAL_SYSCALL_ERROR_P (val, err))
-	    atomic_increment (&cmdp->cntr);
-	}
+      setxid_signal_thread (cmdp, t);
     }
 
   /* Now the list with threads using user-allocated stacks.  */
   list_for_each (runp, &__stack_user)
     {
       struct pthread *t = list_entry (runp, struct pthread, list);
-      if (t != self)
-	{
-	  int val;
-#if __ASSUME_TGKILL
-	  val = INTERNAL_SYSCALL (tgkill, err, 3,
-				  THREAD_GETMEM (THREAD_SELF, pid),
-				  t->tid, SIGSETXID);
-#else
-# ifdef __NR_tgkill
-	  val = INTERNAL_SYSCALL (tgkill, err, 3,
-				  THREAD_GETMEM (THREAD_SELF, pid),
-				  t->tid, SIGSETXID);
-	  if (INTERNAL_SYSCALL_ERROR_P (val, err)
-	      && INTERNAL_SYSCALL_ERRNO (val, err) == ENOSYS)
-# endif
-	    val = INTERNAL_SYSCALL (tkill, err, 2, t->tid, SIGSETXID);
-#endif
+      if (t == self)
+	continue;
 
-	  if (!INTERNAL_SYSCALL_ERROR_P (val, err))
-	    atomic_increment (&cmdp->cntr);
-	}
+      setxid_signal_thread (cmdp, t);
     }
 
   int cur = cmdp->cntr;