about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>2004-11-09 21:52:49 +0000
committerRoland McGrath <roland@gnu.org>2004-11-09 21:52:49 +0000
commitfd5d6a6294b0db3f2143d2735b78bffa284b4259 (patch)
treee4d2b7b0e42cce8a8bdb4dac37e6232b8e6b68c8
parentd1e0c700244fd322cc0d11031d1007fd05e883f1 (diff)
downloadglibc-fd5d6a6294b0db3f2143d2735b78bffa284b4259.tar.gz
glibc-fd5d6a6294b0db3f2143d2735b78bffa284b4259.tar.xz
glibc-fd5d6a6294b0db3f2143d2735b78bffa284b4259.zip
[BZ #530]
2004-11-09  Roland McGrath  <roland@redhat.com>
	[BZ #530]
	* sysdeps/pthread/createthread.c (do_clone): Increment __nptl_nthreads
	here, before calling clone.
	* pthread_create.c (start_thread): Don't do it here.
-rw-r--r--nptl/pthread_create.c3
-rw-r--r--nptl/sysdeps/pthread/createthread.c12
2 files changed, 12 insertions, 3 deletions
diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
index 7293f4c71c..82a3c683aa 100644
--- a/nptl/pthread_create.c
+++ b/nptl/pthread_create.c
@@ -222,9 +222,6 @@ __free_tcb (struct pthread *pd)
 static int
 start_thread (void *arg)
 {
-  /* One more thread.  */
-  atomic_increment (&__nptl_nthreads);
-
   struct pthread *pd = (struct pthread *) arg;
 
 #if HP_TIMING_AVAIL
diff --git a/nptl/sysdeps/pthread/createthread.c b/nptl/sysdeps/pthread/createthread.c
index 8620519887..25a2703ae1 100644
--- a/nptl/sysdeps/pthread/createthread.c
+++ b/nptl/sysdeps/pthread/createthread.c
@@ -64,9 +64,21 @@ do_clone (struct pthread *pd, const struct pthread_attr *attr,
        until we tell it to.  */
     lll_lock (pd->lock);
 
+  /* One more thread.  We cannot have the thread do this itself, since it
+     might exist but not have been scheduled yet by the time we've returned
+     and need to check the value to behave correctly.  We must do it before
+     creating the thread, in case it does get scheduled first and then
+     might mistakenly think it was the only thread.  In the failure case,
+     we momentarily store a false value; this doesn't matter because there
+     is no kosher thing a signal handler interrupting us right here can do
+     that cares whether the thread count is correct.  */
+  atomic_increment (&__nptl_nthreads);
+
   if (ARCH_CLONE (fct, STACK_VARIABLES_ARGS, clone_flags,
 		  pd, &pd->tid, TLS_VALUE, &pd->tid) == -1)
     {
+      atomic_decrement (&__nptl_nthreads); /* Oops, we lied for a second.  */
+
       /* Failed.  If the thread is detached, remove the TCB here since
 	 the caller cannot do this.  The caller remembered the thread
 	 as detached and cannot reverify that it is not since it must