summary refs log tree commit diff
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
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.
-rw-r--r--nptl/ChangeLog20
-rw-r--r--nptl/allocatestack.c92
-rw-r--r--nptl/descr.h16
-rw-r--r--nptl/init.c11
-rw-r--r--nptl/pthread_create.c13
5 files changed, 102 insertions, 50 deletions
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index 8e48cfde66..555df8311d 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,3 +1,23 @@
+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.
+
 2004-09-02  Jakub Jelinek  <jakub@redhat.com>
 
 	* pthread_cond_destroy.c (__pthread_cond_destroy): If there are
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;
diff --git a/nptl/descr.h b/nptl/descr.h
index 77251d5e45..aaef9bc621 100644
--- a/nptl/descr.h
+++ b/nptl/descr.h
@@ -1,4 +1,4 @@
-/* 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.
 
@@ -161,8 +161,11 @@ struct pthread
   /* Bit set if thread terminated and TCB is freed.  */
 #define TERMINATED_BIT		5
 #define TERMINATED_BITMASK	0x20
+  /* Bit set if thread is supposed to change XID.  */
+#define SETXID_BIT		6
+#define SETXID_BITMASK		0x40
   /* Mask for the rest.  Helps the compiler to optimize.  */
-#define CANCEL_RESTMASK		0xffffffc0
+#define CANCEL_RESTMASK		0xffffff80
 
 #define CANCEL_ENABLED_AND_CANCELED(value) \
   (((value) & (CANCELSTATE_BITMASK | CANCELED_BITMASK | EXITING_BITMASK	      \
@@ -185,12 +188,12 @@ struct pthread
     void *data;
   } specific_1stblock[PTHREAD_KEY_2NDLEVEL_SIZE];
 
-  /* Flag which is set when specific data is set.  */
-  bool specific_used;
-
   /* Two-level array for the thread-specific data.  */
   struct pthread_key_data *specific[PTHREAD_KEY_1STLEVEL_SIZE];
 
+  /* Flag which is set when specific data is set.  */
+  bool specific_used;
+
   /* True if events must be reported.  */
   bool report_events;
 
@@ -203,6 +206,9 @@ struct pthread
   /* Lock to synchronize access to the descriptor.  */
   lll_lock_t lock;
 
+  /* Lock for synchronizing setxid calls.  */
+  lll_lock_t setxid_futex;
+
 #if HP_TIMING_AVAIL
   /* Offset of the CPU clock at start thread start time.  */
   hp_timing_t cpuclock_offset;
diff --git a/nptl/init.c b/nptl/init.c
index 86745af8d1..de704122d1 100644
--- a/nptl/init.c
+++ b/nptl/init.c
@@ -1,4 +1,4 @@
-/* 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.
 
@@ -211,6 +211,15 @@ sighandler_setxid (int sig, siginfo_t *si, void *ctx)
 
   if (atomic_decrement_val (&__xidcmd->cntr) == 0)
     lll_futex_wake (&__xidcmd->cntr, 1);
+
+  /* Reset the SETXID flag.  */
+  struct pthread *self = THREAD_SELF;
+  int flags = THREAD_GETMEM (self, cancelhandling);
+  THREAD_SETMEM (self, cancelhandling, flags & ~SETXID_BITMASK);
+
+  /* And release the futex.  */
+  self->setxid_futex = 1;
+  lll_futex_wake (&self->setxid_futex, 1);
 }
 
 
diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
index 122778bddf..f2f206be5a 100644
--- a/nptl/pthread_create.c
+++ b/nptl/pthread_create.c
@@ -314,6 +314,17 @@ start_thread (void *arg)
   if (IS_DETACHED (pd))
     /* Free the TCB.  */
     __free_tcb (pd);
+  else if (__builtin_expect (pd->cancelhandling & SETXID_BITMASK, 0))
+    {
+      /* Some other thread might call any of the setXid functions and expect
+	 us to reply.  In this case wait until we did that.  */
+      do
+	lll_futex_wait (&pd->setxid_futex, 0);
+      while (pd->cancelhandling & SETXID_BITMASK);
+
+      /* Reset the value so that the stack can be reused.  */
+      pd->setxid_futex = 0;
+    }
 
   /* We cannot call '_exit' here.  '_exit' will terminate the process.
 
@@ -354,7 +365,7 @@ __pthread_create_2_1 (newthread, attr, start_routine, arg)
        accessing far-away memory.  */
     iattr = &default_attr;
 
-  struct pthread *pd;
+  struct pthread *pd = NULL;
   int err = ALLOCATE_STACK (iattr, &pd);
   if (__builtin_expect (err != 0, 0))
     /* Something went wrong.  Maybe a parameter of the attributes is