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
This commit is contained in:
Mike Makonnen 2004-10-13 11:42:20 +00:00
parent 43b42e0a71
commit 5dbd7addb0
2 changed files with 10 additions and 4 deletions

View File

@ -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);

View File

@ -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);