fix a race between pthread_exit and pthread_create.

inefficient, but better than crashing.
This commit is contained in:
yamt 2007-02-15 15:39:33 +00:00
parent f8fe10ea6a
commit 4cdc2ed889
2 changed files with 19 additions and 15 deletions

View File

@ -1,4 +1,4 @@
$NetBSD: TODO,v 1.5 2006/12/25 11:36:36 ad Exp $
$NetBSD: TODO,v 1.6 2007/02/15 15:39:33 yamt Exp $
Bugs to fix, mostly with SA:
@ -64,11 +64,11 @@ Future work for 1:1 threads:
- Verify that gdb still works well (basic functionality seems to be OK).
- There is a race between pthread_exit() and pthread_create() for
detached LWPs, where the stack (and pthread structure) could be reclaimed
before the thread has a chance to call _lwp_exit(). Checking the return
of _lwp_kill(target, 0) could be used to fix this but that seems a bit
heavyweight. (See shared page item.)
- A race between pthread_exit() and pthread_create() for detached LWPs,
where the stack (and pthread structure) could be reclaimed before the
thread has a chance to call _lwp_exit(), is currently prevented by
checking the return of _lwp_kill(target, 0). It could be done more
efficiently. (See shared page item.)
- Adaptive mutexes and spinlocks (see shared page item). These need
to implement exponential backoff to reduce bus contention. On x86 we

View File

@ -1,4 +1,4 @@
/* $NetBSD: pthread.c,v 1.59 2007/02/09 23:53:24 ad Exp $ */
/* $NetBSD: pthread.c,v 1.60 2007/02/15 15:39:38 yamt Exp $ */
/*-
* Copyright (c) 2001, 2002, 2003, 2006 The NetBSD Foundation, Inc.
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: pthread.c,v 1.59 2007/02/09 23:53:24 ad Exp $");
__RCSID("$NetBSD: pthread.c,v 1.60 2007/02/15 15:39:38 yamt Exp $");
#include <err.h>
#include <errno.h>
@ -418,12 +418,17 @@ pthread_create(pthread_t *thread, const pthread_attr_t *attr,
self = pthread__self();
pthread_spinlock(self, &pthread__deadqueue_lock);
if (!PTQ_EMPTY(&pthread__deadqueue)) {
newthread = PTQ_FIRST(&pthread__deadqueue);
PTQ_REMOVE(&pthread__deadqueue, newthread, pt_allq);
pthread_spinunlock(self, &pthread__deadqueue_lock);
} else {
pthread_spinunlock(self, &pthread__deadqueue_lock);
newthread = PTQ_FIRST(&pthread__deadqueue);
if (newthread != NULL) {
#ifndef PTHREAD_SA
if (_lwp_kill(newthread->pt_lid, 0) == 0 || errno != ESRCH)
newthread = NULL;
else
#endif
PTQ_REMOVE(&pthread__deadqueue, newthread, pt_allq);
}
pthread_spinunlock(self, &pthread__deadqueue_lock);
if (newthread == NULL) {
/* Set up a stack and allocate space for a pthread_st. */
ret = pthread__stackalloc(&newthread);
if (ret != 0) {
@ -720,7 +725,6 @@ pthread_exit(void *retval)
pthread_spinunlock(self, &pthread__allqueue_lock);
#else
pthread_spinunlock(self, &pthread__deadqueue_lock);
/* XXXLWP race against stack being reclaimed. */
_lwp_exit();
#endif
} else {