diff options
| author | ad <ad@NetBSD.org> | 2007-11-13 17:20:08 +0000 |
|---|---|---|
| committer | ad <ad@NetBSD.org> | 2007-11-13 17:20:08 +0000 |
| commit | 66ac2ffaf293a1766211e270fcce0ba856f8f80e (patch) | |
| tree | 14c1c20985051c159c5d7b74ce133f33a8efdd64 /lib/libpthread/pthread.c | |
| parent | 3c776c8aa6570d9365bd4dc5468590e6c51103bb (diff) | |
Mutexes:
- Play scrooge again and chop more cycles off acquire/release.
- Spin while the lock holder is running on another CPU (adaptive mutexes).
- Do non-atomic release.
Threadreg:
- Add the necessary hooks to use a thread register.
- Add the code for i386, using %gs.
- Leave i386 code disabled until xen and COMPAT_NETBSD32 have the changes.
Diffstat (limited to 'lib/libpthread/pthread.c')
| -rw-r--r-- | lib/libpthread/pthread.c | 77 |
1 files changed, 64 insertions, 13 deletions
diff --git a/lib/libpthread/pthread.c b/lib/libpthread/pthread.c index 4d2a2fdb087..78de6571e5d 100644 --- a/lib/libpthread/pthread.c +++ b/lib/libpthread/pthread.c @@ -1,4 +1,4 @@ -/* $NetBSD: pthread.c,v 1.87 2007/11/13 15:57:10 ad Exp $ */ +/* $NetBSD: pthread.c,v 1.88 2007/11/13 17:20:09 ad Exp $ */ /*- * Copyright (c) 2001, 2002, 2003, 2006, 2007 The NetBSD Foundation, Inc. @@ -37,13 +37,14 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: pthread.c,v 1.87 2007/11/13 15:57:10 ad Exp $"); +__RCSID("$NetBSD: pthread.c,v 1.88 2007/11/13 17:20:09 ad Exp $"); #define __EXPOSE_STACK 1 #include <sys/param.h> #include <sys/mman.h> #include <sys/sysctl.h> +#include <sys/lwpctl.h> #include <err.h> #include <errno.h> @@ -68,22 +69,24 @@ static int pthread__cmp(struct __pthread_st *, struct __pthread_st *); RB_PROTOTYPE_STATIC(__pthread__alltree, __pthread_st, pt_alltree, pthread__cmp) #endif -static void pthread__create_tramp(void *(*)(void *), void *); +static void pthread__create_tramp(pthread_t, void *(*)(void *), void *); static void pthread__initthread(pthread_t); static void pthread__scrubthread(pthread_t, char *, int); static int pthread__stackid_setup(void *, size_t, pthread_t *); static int pthread__stackalloc(pthread_t *); static void pthread__initmain(pthread_t *); +static void pthread__fork_callback(void); void pthread__init(void); int pthread__started; - pthread_mutex_t pthread__deadqueue_lock = PTHREAD_MUTEX_INITIALIZER; pthread_queue_t pthread__deadqueue; pthread_queue_t pthread__allqueue; static pthread_attr_t pthread_default_attr; +static lwpctl_t pthread__dummy_lwpctl = { .lc_curcpu = LWPCTL_CPU_NONE }; +static pthread_t pthread__first; enum { DIAGASSERT_ABORT = 1<<0, @@ -191,6 +194,13 @@ pthread__init(void) PTQ_INSERT_HEAD(&pthread__allqueue, first, pt_allq); RB_INSERT(__pthread__alltree, &pthread__alltree, first); + /* + * Don't need lwpctl if running on a uniprocessor. + * Just use the dummy block. + */ + if (pthread__concurrency > 1) + (void)_lwp_ctl(LWPCTL_FEATURE_CURCPU, &first->pt_lwpctl); + /* Start subsystems */ PTHREAD_MD_INIT pthread__debug_init(); @@ -218,14 +228,27 @@ pthread__init(void) } } - /* Tell libc that we're here and it should role-play accordingly. */ + pthread__first = first; + pthread_atfork(NULL, NULL, pthread__fork_callback); __isthreaded = 1; } static void +pthread__fork_callback(void) +{ + + /* lwpctl state is not copied across fork. */ + if (pthread__concurrency > 1) { + (void)_lwp_ctl(LWPCTL_FEATURE_CURCPU, + &pthread__first->pt_lwpctl); + } +} + +static void pthread__child_callback(void) { + /* * Clean up data structures that a forked child process might * trip over. Note that if threads have been created (causing @@ -268,6 +291,8 @@ pthread__initthread(pthread_t t) t->pt_signalled = 0; t->pt_havespecific = 0; t->pt_early = NULL; + t->pt_lwpctl = &pthread__dummy_lwpctl; + t->pt_blocking = 0; memcpy(&t->pt_lockops, pthread__lock_ops, sizeof(t->pt_lockops)); pthread_mutex_init(&t->pt_lock, NULL); @@ -339,8 +364,10 @@ pthread_create(pthread_t *thread, const pthread_attr_t *attr, pthread_mutex_unlock(&pthread__deadqueue_lock); if ((newthread->pt_flags & PT_FLAG_DETACHED) != 0) { /* Still running? */ - if (_lwp_kill(newthread->pt_lid, 0) == 0 || - errno != ESRCH) { + if (newthread->pt_lwpctl->lc_curcpu != + LWPCTL_CPU_EXITED && + (_lwp_kill(newthread->pt_lid, 0) == 0 || + errno != ESRCH)) { pthread_mutex_lock( &pthread__deadqueue_lock); PTQ_INSERT_TAIL(&pthread__deadqueue, @@ -388,8 +415,8 @@ pthread_create(pthread_t *thread, const pthread_attr_t *attr, * Create the new LWP. */ pthread__scrubthread(newthread, name, nattr.pta_flags); - makecontext(&newthread->pt_uc, pthread__create_tramp, 2, - startfunc, arg); + makecontext(&newthread->pt_uc, pthread__create_tramp, 3, + newthread, startfunc, arg); flag = 0; if ((newthread->pt_flags & PT_FLAG_SUSPENDED) != 0) @@ -413,11 +440,15 @@ pthread_create(pthread_t *thread, const pthread_attr_t *attr, static void -pthread__create_tramp(void *(*start)(void *), void *arg) +pthread__create_tramp(pthread_t self, void *(*start)(void *), void *arg) { - pthread_t self; void *retval; +#ifdef PTHREAD__HAVE_THREADREG + /* Set up identity register. */ + pthread__threadreg_set(self); +#endif + /* * Throw away some stack in a feeble attempt to reduce cache * thrash. May help for SMT processors. XXX We should not @@ -426,16 +457,22 @@ pthread__create_tramp(void *(*start)(void *), void *arg) * that pt_lid may not be set by this point, but we don't * care. */ - self = pthread__self(); (void)alloca(((unsigned)self->pt_lid & 7) << 8); if (self->pt_name != NULL) { pthread_mutex_lock(&self->pt_lock); if (self->pt_name != NULL) - (void)_lwp_setname(_lwp_self(), self->pt_name); + (void)_lwp_setname(0, self->pt_name); pthread_mutex_unlock(&self->pt_lock); } + /* + * Don't need lwpctl if running on a uniprocessor. + * Just use the dummy block. + */ + if (pthread__concurrency > 1) + (void)_lwp_ctl(LWPCTL_FEATURE_CURCPU, &self->pt_lwpctl); + retval = (*start)(arg); pthread_exit(retval); @@ -947,6 +984,14 @@ pthread__park(pthread_t self, pthread_spin_t *lock, /* Clear the willpark flag, since we're about to block. */ self->pt_willpark = 0; + /* + * For non-interlocked release of mutexes we need a store + * barrier before incrementing pt_blocking away from zero. + * This is provided by the caller (it will release an + * interlock, or do an explicit barrier). + */ + self->pt_blocking++; + /* * Kernels before 4.99.27 can't park and unpark in one step, * so take care of it now if on an old kernel. @@ -1034,6 +1079,7 @@ pthread__park(pthread_t self, pthread_spin_t *lock, pthread__spinunlock(self, lock); } self->pt_early = NULL; + self->pt_blocking--; return rv; } @@ -1260,6 +1306,11 @@ pthread__initmain(pthread_t *newt) } *newt = t; + +#ifdef PTHREAD__HAVE_THREADREG + /* Set up identity register. */ + pthread__threadreg_set(t); +#endif } static int |
