summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authormtm <mtm@FreeBSD.org>2004-10-13 11:42:20 +0000
committermtm <mtm@FreeBSD.org>2004-10-13 11:42:20 +0000
commitce193bdc46e79c71e7c9070a71fe8317ed3dfbaa (patch)
tree8483c07b545b86140bcdf0b51159f6be244af2bc /lib
parent0ed0f178d85740eea1e38f7cf3ae316ac811fccb (diff)
downloadFreeBSD-src-ce193bdc46e79c71e7c9070a71fe8317ed3dfbaa.zip
FreeBSD-src-ce193bdc46e79c71e7c9070a71fe8317ed3dfbaa.tar.gz
1. Now that it's a thread's state is changed from within the kernel, where
no userland locks are heald, the dead thread lock can no longer protect access to it. Therefore, instead of using an if (!dead)...else clause after walking the active threads list test the thread pointer before deciding not to walk the dead threads list. If the thread pointer is null it means it was not found in the active threads list and the dead threads list should be checked. 2. Do not free the stack of a thread that is not marked dead. This is the 2nd and final part of eliminating the race to free a thread's stack. MFC after: 3 days
Diffstat (limited to 'lib')
-rw-r--r--lib/libthr/thread/thr_exit.c3
-rw-r--r--lib/libthr/thread/thr_join.c11
2 files changed, 10 insertions, 4 deletions
diff --git a/lib/libthr/thread/thr_exit.c b/lib/libthr/thread/thr_exit.c
index 6a45687..f74b5e1 100644
--- a/lib/libthr/thread/thr_exit.c
+++ b/lib/libthr/thread/thr_exit.c
@@ -195,7 +195,8 @@ deadlist_free_threads()
TAILQ_FOREACH_SAFE(ptd, &_dead_list, dle, ptdTemp) {
/* Don't destroy the initial thread or non-detached threads. */
if (ptd == _thread_initial ||
- (ptd->attr.flags & PTHREAD_DETACHED) == 0)
+ (ptd->attr.flags & PTHREAD_DETACHED) == 0 ||
+ !ptd->isdead)
continue;
TAILQ_REMOVE(&_dead_list, ptd, dle);
deadlist_free_onethread(ptd);
diff --git a/lib/libthr/thread/thr_join.c b/lib/libthr/thread/thr_join.c
index 8ff4c1a..29dd421 100644
--- a/lib/libthr/thread/thr_join.c
+++ b/lib/libthr/thread/thr_join.c
@@ -41,7 +41,7 @@ __weak_reference(_pthread_join, pthread_join);
int
_pthread_join(pthread_t pthread, void **thread_return)
{
- int ret = 0;
+ int ret, dead;
pthread_t thread;
/* Check if the caller has specified an invalid thread: */
@@ -60,6 +60,9 @@ _pthread_join(pthread_t pthread, void **thread_return)
* the searches in _thread_list and _dead_list (as well as setting up
* join/detach state) have to be done atomically.
*/
+ ret = 0;
+ dead = 0;
+ thread = NULL;
_thread_sigblock();
DEAD_LIST_LOCK;
THREAD_LIST_LOCK;
@@ -70,10 +73,12 @@ _pthread_join(pthread_t pthread, void **thread_return)
break;
}
}
- } else {
+ }
+ if (thread == NULL) {
TAILQ_FOREACH(thread, &_dead_list, dle) {
if (thread == pthread) {
PTHREAD_LOCK(pthread);
+ dead = 1;
break;
}
}
@@ -109,7 +114,7 @@ _pthread_join(pthread_t pthread, void **thread_return)
}
/* Check if the thread is not dead: */
- if (!pthread->isdead) {
+ if (!dead) {
/* Set the running thread to be the joiner: */
pthread->joiner = curthread;
PTHREAD_UNLOCK(pthread);
OpenPOWER on IntegriCloud