aboutsummaryrefslogtreecommitdiff
path: root/nptl/pthread_join.c
diff options
context:
space:
mode:
Diffstat (limited to 'nptl/pthread_join.c')
-rw-r--r--nptl/pthread_join.c80
1 files changed, 37 insertions, 43 deletions
diff --git a/nptl/pthread_join.c b/nptl/pthread_join.c
index c88d85b52f..f94128dd96 100644
--- a/nptl/pthread_join.c
+++ b/nptl/pthread_join.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
@@ -20,18 +20,14 @@
#include <errno.h>
#include <stdlib.h>
-#include <atomic.h>
+#include "atomic.h"
#include "pthreadP.h"
static void
cleanup (void *arg)
{
- /* If we already changed the waiter ID, reset it. The call cannot
- fail for any reason but the thread not having done that yet so
- there is no reason for a loop. */
- atomic_compare_and_exchange_bool_acq ((struct pthread **) arg, NULL,
- THREAD_SELF);
+ *(void **) arg = NULL;
}
@@ -40,6 +36,7 @@ pthread_join (threadid, thread_return)
pthread_t threadid;
void **thread_return;
{
+ struct pthread *self;
struct pthread *pd = (struct pthread *) threadid;
/* Make sure the descriptor is valid. */
@@ -52,23 +49,12 @@ pthread_join (threadid, thread_return)
/* We cannot wait for the thread. */
return EINVAL;
- struct pthread *self = THREAD_SELF;
- int result = 0;
-
- /* During the wait we change to asynchronous cancellation. If we
- are canceled the thread we are waiting for must be marked as
- un-wait-ed for again. */
- pthread_cleanup_push (cleanup, &pd->joinid);
-
- /* Switch to asynchronous cancellation. */
- int oldtype = CANCEL_ASYNC ();
-
- if ((pd == self
- || (self->joinid == pd
- && (pd->cancelhandling
- & (CANCELING_BITMASK | CANCELED_BITMASK | EXITING_BITMASK
- | TERMINATED_BITMASK)) == 0))
- && !CANCEL_ENABLED_AND_CANCELED (self->cancelhandling))
+ self = THREAD_SELF;
+ if (pd == self
+ || (self->joinid == pd
+ && (pd->cancelhandling
+ & (CANCELING_BITMASK | CANCELED_BITMASK | EXITING_BITMASK
+ | TERMINATED_BITMASK)) == 0))
/* This is a deadlock situation. The threads are waiting for each
other to finish. Note that this is a "may" error. To be 100%
sure we catch this error we would have to lock the data
@@ -76,17 +62,28 @@ pthread_join (threadid, thread_return)
two threads are really caught in this situation they will
deadlock. It is the programmer's problem to figure this
out. */
- result = EDEADLK;
+ return EDEADLK;
+
/* Wait for the thread to finish. If it is already locked something
is wrong. There can only be one waiter. */
- else if (__builtin_expect (atomic_compare_and_exchange_bool_acq (&pd->joinid,
- self,
- NULL), 0))
+ if (__builtin_expect (atomic_compare_and_exchange_bool_acq (&pd->joinid,
+ self,
+ NULL), 0))
/* There is already somebody waiting for the thread. */
- result = EINVAL;
- else
- /* Wait for the child. */
- lll_wait_tid (pd->tid);
+ return EINVAL;
+
+
+ /* During the wait we change to asynchronous cancellation. If we
+ are cancelled the thread we are waiting for must be marked as
+ un-wait-ed for again. */
+ pthread_cleanup_push (cleanup, &pd->joinid);
+
+ /* Switch to asynchronous cancellation. */
+ int oldtype = CANCEL_ASYNC ();
+
+
+ /* Wait for the child. */
+ lll_wait_tid (pd->tid);
/* Restore cancellation mode. */
@@ -96,19 +93,16 @@ pthread_join (threadid, thread_return)
pthread_cleanup_pop (0);
- if (__builtin_expect (result == 0, 1))
- {
- /* We mark the thread as terminated and as joined. */
- pd->tid = -1;
+ /* We mark the thread as terminated and as joined. */
+ pd->tid = -1;
- /* Store the return value if the caller is interested. */
- if (thread_return != NULL)
- *thread_return = pd->result;
+ /* Store the return value if the caller is interested. */
+ if (thread_return != NULL)
+ *thread_return = pd->result;
- /* Free the TCB. */
- __free_tcb (pd);
- }
+ /* Free the TCB. */
+ __free_tcb (pd);
- return result;
+ return 0;
}