summaryrefslogtreecommitdiffstats
path: root/lib/libthr
diff options
context:
space:
mode:
authormtm <mtm@FreeBSD.org>2003-05-26 00:28:49 +0000
committermtm <mtm@FreeBSD.org>2003-05-26 00:28:49 +0000
commit3440accd67bef89b04b9c16c578fd05c6de445b3 (patch)
treedb7f7c2fddbe575b6d97a6bdca6e04924e0f8eb6 /lib/libthr
parentd8e0ed54e351db48278bd6693dde605fcda057df (diff)
downloadFreeBSD-src-3440accd67bef89b04b9c16c578fd05c6de445b3.zip
FreeBSD-src-3440accd67bef89b04b9c16c578fd05c6de445b3.tar.gz
Revise the unlock order in _pthread_join(). Also, if the joined
thread is not dead, the join loop is guaranteed to execute at least once, so there is no need to pick up the thread list lock after we return from suspenstion only to release it after the loop. Approved by: re/blanket libthr
Diffstat (limited to 'lib/libthr')
-rw-r--r--lib/libthr/thread/thr_join.c18
1 files changed, 6 insertions, 12 deletions
diff --git a/lib/libthr/thread/thr_join.c b/lib/libthr/thread/thr_join.c
index 061058a..63f37fa 100644
--- a/lib/libthr/thread/thr_join.c
+++ b/lib/libthr/thread/thr_join.c
@@ -82,13 +82,13 @@ _pthread_join(pthread_t pthread, void **thread_return)
_SPINLOCK(&pthread->lock);
break;
}
- THREAD_LIST_UNLOCK;
/* Check if the thread was not found or has been detached: */
if (thread == NULL ||
((pthread->attr.flags & PTHREAD_DETACHED) != 0)) {
if (thread != NULL)
_SPINUNLOCK(&pthread->lock);
+ THREAD_LIST_UNLOCK;
DEAD_LIST_UNLOCK;
ret = ESRCH;
goto out;
@@ -98,6 +98,7 @@ _pthread_join(pthread_t pthread, void **thread_return)
/* Multiple joiners are not supported. */
/* XXXTHR - support multiple joiners. */
_SPINUNLOCK(&pthread->lock);
+ THREAD_LIST_UNLOCK;
DEAD_LIST_UNLOCK;
ret = ENOTSUP;
goto out;
@@ -112,16 +113,16 @@ _pthread_join(pthread_t pthread, void **thread_return)
/* Keep track of which thread we're joining to: */
curthread->join_status.thread = pthread;
- _SPINUNLOCK(&pthread->lock);
while (curthread->join_status.thread == pthread) {
PTHREAD_SET_STATE(curthread, PS_JOIN);
/* Wait for our signal to wake up. */
_thread_critical_exit(curthread);
+ _SPINUNLOCK(&pthread->lock);
+ THREAD_LIST_UNLOCK;
DEAD_LIST_UNLOCK;
_thread_suspend(curthread, NULL);
- /* XXX - For correctness reasons. */
- DEAD_LIST_LOCK;
+
_thread_critical_enter(curthread);
}
@@ -133,14 +134,6 @@ _pthread_join(pthread_t pthread, void **thread_return)
if ((ret == 0) && (thread_return != NULL))
*thread_return = curthread->join_status.ret;
_thread_critical_exit(curthread);
- /*
- * XXX - Must unlock here, instead of doing it earlier,
- * because it could lead to a deadlock. If the thread
- * we are joining is waiting on this lock we would
- * deadlock if we released this lock before unlocking the
- * joined thread.
- */
- DEAD_LIST_UNLOCK;
} else {
/*
* The thread exited (is dead) without being detached, and no
@@ -158,6 +151,7 @@ _pthread_join(pthread_t pthread, void **thread_return)
_SPINUNLOCK(&pthread->lock);
if (pthread_cond_signal(&_gc_cond) != 0)
PANIC("Cannot signal gc cond");
+ THREAD_LIST_UNLOCK;
DEAD_LIST_UNLOCK;
}
OpenPOWER on IntegriCloud