diff options
| author | ad <ad@NetBSD.org> | 2007-08-16 13:54:16 +0000 |
|---|---|---|
| committer | ad <ad@NetBSD.org> | 2007-08-16 13:54:16 +0000 |
| commit | d9adedd76400ff3a3069a7e9f55a78ff6aeb43e8 (patch) | |
| tree | 4e3cfb7305417e09804e79b93bf94ca7313bc87b /lib/libpthread | |
| parent | 8423867fa7ce95339fc3981d44d13c064fd8614e (diff) | |
Trim fat off libpthread internal spinlock operations. Makes a mesurable
improvement across the board.
Diffstat (limited to 'lib/libpthread')
| -rw-r--r-- | lib/libpthread/Makefile | 10 | ||||
| -rw-r--r-- | lib/libpthread/pthread.c | 137 | ||||
| -rw-r--r-- | lib/libpthread/pthread_barrier.c | 34 | ||||
| -rw-r--r-- | lib/libpthread/pthread_cond.c | 38 | ||||
| -rw-r--r-- | lib/libpthread/pthread_int.h | 15 | ||||
| -rw-r--r-- | lib/libpthread/pthread_lock.c | 219 | ||||
| -rw-r--r-- | lib/libpthread/pthread_misc.c | 9 | ||||
| -rw-r--r-- | lib/libpthread/pthread_mutex.c | 16 | ||||
| -rw-r--r-- | lib/libpthread/pthread_rwlock.c | 69 | ||||
| -rw-r--r-- | lib/libpthread/pthread_spin.c | 139 | ||||
| -rw-r--r-- | lib/libpthread/sem.c | 42 |
11 files changed, 405 insertions, 323 deletions
diff --git a/lib/libpthread/Makefile b/lib/libpthread/Makefile index 0ee0ca6909a..b99f53dd7c8 100644 --- a/lib/libpthread/Makefile +++ b/lib/libpthread/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.41 2007/08/16 01:09:34 ad Exp $ +# $NetBSD: Makefile,v 1.42 2007/08/16 13:54:16 ad Exp $ # WARNS= 4 @@ -56,6 +56,7 @@ SRCS+= pthread_misc.c SRCS+= pthread_mutex.c SRCS+= pthread_rwlock.c SRCS+= pthread_specific.c +SRCS+= pthread_spin.c SRCS+= pthread_tsd.c SRCS+= pthread_debug.c SRCS+= res_state.c @@ -73,6 +74,13 @@ pthread_specific.po: pthread_specific.o ${_MKTARGET_CREATE} cp pthread_specific.o pthread_specific.po +# Internal spinlock routines are performance critical. Don't profile them, +# it's incompatibile with -fomit-frame-pointer. +COPTS.pthread_lock.c+= -fomit-frame-pointer -falign-functions=32 +pthread_lock.po: pthread_lock.o + ${_MKTARGET_CREATE} + cp pthread_lock.o pthread_lock.po + _context_u.po: _context_u.o ${_MKTARGET_CREATE} cp _context_u.o _context_u.po diff --git a/lib/libpthread/pthread.c b/lib/libpthread/pthread.c index 66dcc187c6f..837799b3e4e 100644 --- a/lib/libpthread/pthread.c +++ b/lib/libpthread/pthread.c @@ -1,4 +1,4 @@ -/* $NetBSD: pthread.c,v 1.77 2007/08/16 12:01:49 ad Exp $ */ +/* $NetBSD: pthread.c,v 1.78 2007/08/16 13:54:16 ad Exp $ */ /*- * Copyright (c) 2001, 2002, 2003, 2006, 2007 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: pthread.c,v 1.77 2007/08/16 12:01:49 ad Exp $"); +__RCSID("$NetBSD: pthread.c,v 1.78 2007/08/16 13:54:16 ad Exp $"); #define __EXPOSE_STACK 1 @@ -288,7 +288,7 @@ int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*startfunc)(void *), void *arg) { - pthread_t self, newthread; + pthread_t newthread; pthread_attr_t nattr; struct pthread_attr_private *p; char * volatile name; @@ -320,33 +320,32 @@ pthread_create(pthread_t *thread, const pthread_attr_t *attr, if ((name = strdup(p->ptap_name)) == NULL) return ENOMEM; - self = pthread__self(); newthread = NULL; /* * Try to reclaim a dead thread. */ if (!PTQ_EMPTY(&pthread__deadqueue)) { - pthread_spinlock(self, &pthread__deadqueue_lock); + pthread_spinlock(&pthread__deadqueue_lock); newthread = PTQ_FIRST(&pthread__deadqueue); if (newthread != NULL) { PTQ_REMOVE(&pthread__deadqueue, newthread, pt_deadq); - pthread_spinunlock(self, &pthread__deadqueue_lock); + pthread_spinunlock(&pthread__deadqueue_lock); if ((newthread->pt_flags & PT_FLAG_DETACHED) != 0) { /* Still running? */ if (_lwp_kill(newthread->pt_lid, 0) == 0 || errno != ESRCH) { - pthread_spinlock(self, + pthread_spinlock( &pthread__deadqueue_lock); PTQ_INSERT_TAIL(&pthread__deadqueue, newthread, pt_deadq); - pthread_spinunlock(self, + pthread_spinunlock( &pthread__deadqueue_lock); newthread = NULL; } } } else - pthread_spinunlock(self, &pthread__deadqueue_lock); + pthread_spinunlock(&pthread__deadqueue_lock); } /* @@ -370,9 +369,9 @@ pthread_create(pthread_t *thread, const pthread_attr_t *attr, newthread->pt_uc.uc_link = NULL; /* Add to list of all threads. */ - pthread_spinlock(self, &pthread__allqueue_lock); + pthread_spinlock(&pthread__allqueue_lock); PTQ_INSERT_HEAD(&pthread__allqueue, newthread, pt_allq); - pthread_spinunlock(self, &pthread__allqueue_lock); + pthread_spinunlock(&pthread__allqueue_lock); /* Will be reset by the thread upon exit. */ pthread__initthread(newthread); @@ -396,9 +395,9 @@ pthread_create(pthread_t *thread, const pthread_attr_t *attr, strerror(errno))); free(name); newthread->pt_state = PT_STATE_DEAD; - pthread_spinlock(self, &pthread__deadqueue_lock); + pthread_spinlock(&pthread__deadqueue_lock); PTQ_INSERT_HEAD(&pthread__deadqueue, newthread, pt_deadq); - pthread_spinunlock(self, &pthread__deadqueue_lock); + pthread_spinunlock(&pthread__deadqueue_lock); return ret; } @@ -406,7 +405,7 @@ pthread_create(pthread_t *thread, const pthread_attr_t *attr, newthread->pt_num = newthread->pt_lid; SDPRINTF(("(pthread_create %p) new thread %p (name %p, lid %d).\n", - self, newthread, newthread->pt_name, + pthread__self(), newthread, newthread->pt_name, (int)newthread->pt_lid)); *thread = newthread; @@ -446,26 +445,24 @@ pthread_suspend_np(pthread_t thread) return EDEADLK; } #ifdef ERRORCHECK - if (pthread__find(self, thread) != 0) + if (pthread__find(thread) != 0) return ESRCH; #endif SDPRINTF(("(pthread_suspend_np %p) Suspend thread %p.\n", - self, thread)); + pthread__self(), thread)); return _lwp_suspend(thread->pt_lid); } int pthread_resume_np(pthread_t thread) { - pthread_t self; - - self = pthread__self(); + #ifdef ERRORCHECK - if (pthread__find(self, thread) != 0) + if (pthread__find(thread) != 0) return ESRCH; #endif SDPRINTF(("(pthread_resume_np %p) Resume thread %p.\n", - self, thread)); + pthread__self(), thread)); return _lwp_continue(thread->pt_lid); } @@ -481,10 +478,10 @@ pthread_exit(void *retval) self, retval, self->pt_flags, self->pt_cancel)); /* Disable cancellability. */ - pthread_spinlock(self, &self->pt_lock); + pthread_spinlock(&self->pt_lock); self->pt_flags |= PT_FLAG_CS_DISABLED; self->pt_cancel = 0; - pthread_spinunlock(self, &self->pt_lock); + pthread_spinunlock(&self->pt_lock); /* Call any cancellation cleanup handlers */ while (!PTQ_EMPTY(&self->pt_cleanup_stack)) { @@ -498,21 +495,21 @@ pthread_exit(void *retval) self->pt_exitval = retval; - pthread_spinlock(self, &self->pt_lock); + pthread_spinlock(&self->pt_lock); if (self->pt_flags & PT_FLAG_DETACHED) { self->pt_state = PT_STATE_DEAD; name = self->pt_name; self->pt_name = NULL; - pthread_spinlock(self, &pthread__deadqueue_lock); + pthread_spinlock(&pthread__deadqueue_lock); PTQ_INSERT_TAIL(&pthread__deadqueue, self, pt_deadq); - pthread_spinunlock(self, &pthread__deadqueue_lock); - pthread_spinunlock(self, &self->pt_lock); + pthread_spinunlock(&pthread__deadqueue_lock); + pthread_spinunlock(&self->pt_lock); if (name != NULL) free(name); _lwp_exit(); } else { self->pt_state = PT_STATE_ZOMBIE; - pthread_spinunlock(self, &self->pt_lock); + pthread_spinunlock(&self->pt_lock); /* Note: name will be freed by the joiner. */ _lwp_exit(); } @@ -532,7 +529,7 @@ pthread_join(pthread_t thread, void **valptr) self = pthread__self(); SDPRINTF(("(pthread_join %p) Joining %p.\n", self, thread)); - if (pthread__find(self, thread) != 0) + if (pthread__find(thread) != 0) return ESRCH; if (thread->pt_magic != PT_MAGIC) @@ -568,9 +565,9 @@ pthread_join(pthread_t thread, void **valptr) name = thread->pt_name; thread->pt_name = NULL; thread->pt_state = PT_STATE_DEAD; - pthread_spinlock(self, &pthread__deadqueue_lock); + pthread_spinlock(&pthread__deadqueue_lock); PTQ_INSERT_HEAD(&pthread__deadqueue, thread, pt_deadq); - pthread_spinunlock(self, &pthread__deadqueue_lock); + pthread_spinunlock(&pthread__deadqueue_lock); SDPRINTF(("(pthread_join %p) Joined %p.\n", self, thread)); if (name != NULL) free(name); @@ -594,15 +591,15 @@ pthread_detach(pthread_t thread) self = pthread__self(); - if (pthread__find(self, thread) != 0) + if (pthread__find(thread) != 0) return ESRCH; if (thread->pt_magic != PT_MAGIC) return EINVAL; - pthread_spinlock(self, &self->pt_lock); + pthread_spinlock(&self->pt_lock); thread->pt_flags |= PT_FLAG_DETACHED; - pthread_spinunlock(self, &self->pt_lock); + pthread_spinunlock(&self->pt_lock); return _lwp_detach(thread->pt_lid); } @@ -611,22 +608,19 @@ pthread_detach(pthread_t thread) int pthread_getname_np(pthread_t thread, char *name, size_t len) { - pthread_t self; - - self = pthread__self(); - if (pthread__find(self, thread) != 0) + if (pthread__find(thread) != 0) return ESRCH; if (thread->pt_magic != PT_MAGIC) return EINVAL; - pthread_spinlock(self, &thread->pt_lock); + pthread_spinlock(&thread->pt_lock); if (thread->pt_name == NULL) name[0] = '\0'; else strlcpy(name, thread->pt_name, len); - pthread_spinunlock(self, &thread->pt_lock); + pthread_spinunlock(&thread->pt_lock); return 0; } @@ -635,12 +629,10 @@ pthread_getname_np(pthread_t thread, char *name, size_t len) int pthread_setname_np(pthread_t thread, const char *name, void *arg) { - pthread_t self; char *oldname, *cp, newname[PTHREAD_MAX_NAMELEN_NP]; int namelen; - self = pthread__self(); - if (pthread__find(self, thread) != 0) + if (pthread__find(thread) != 0) return ESRCH; if (thread->pt_magic != PT_MAGIC) @@ -654,10 +646,10 @@ pthread_setname_np(pthread_t thread, const char *name, void *arg) if (cp == NULL) return ENOMEM; - pthread_spinlock(self, &thread->pt_lock); + pthread_spinlock(&thread->pt_lock); oldname = thread->pt_name; thread->pt_name = cp; - pthread_spinunlock(self, &thread->pt_lock); + pthread_spinunlock(&thread->pt_lock); if (oldname != NULL) free(oldname); @@ -682,19 +674,17 @@ pthread_self(void) int pthread_cancel(pthread_t thread) { - pthread_t self; - self = pthread__self(); - if (pthread__find(self, thread) != 0) + if (pthread__find(thread) != 0) return ESRCH; - pthread_spinlock(self, &thread->pt_lock); + pthread_spinlock(&thread->pt_lock); thread->pt_flags |= PT_FLAG_CS_PENDING; if ((thread->pt_flags & PT_FLAG_CS_DISABLED) == 0) { thread->pt_cancel = 1; - pthread_spinunlock(self, &thread->pt_lock); + pthread_spinunlock(&thread->pt_lock); _lwp_wakeup(thread->pt_lid); } else - pthread_spinunlock(self, &thread->pt_lock); + pthread_spinunlock(&thread->pt_lock); return 0; } @@ -709,7 +699,7 @@ pthread_setcancelstate(int state, int *oldstate) self = pthread__self(); retval = 0; - pthread_spinlock(self, &self->pt_lock); + pthread_spinlock(&self->pt_lock); if (oldstate != NULL) { if (self->pt_flags & PT_FLAG_CS_DISABLED) @@ -735,14 +725,14 @@ pthread_setcancelstate(int state, int *oldstate) self->pt_cancel = 1; /* This is not a deferred cancellation point. */ if (self->pt_flags & PT_FLAG_CS_ASYNC) { - pthread_spinunlock(self, &self->pt_lock); + pthread_spinunlock(&self->pt_lock); pthread_exit(PTHREAD_CANCELED); } } } else retval = EINVAL; - pthread_spinunlock(self, &self->pt_lock); + pthread_spinunlock(&self->pt_lock); return retval; } @@ -757,7 +747,7 @@ pthread_setcanceltype(int type, int *oldtype) self = pthread__self(); retval = 0; - pthread_spinlock(self, &self->pt_lock); + pthread_spinlock(&self->pt_lock); if (oldtype != NULL) { if (self->pt_flags & PT_FLAG_CS_ASYNC) @@ -769,7 +759,7 @@ pthread_setcanceltype(int type, int *oldtype) if (type == PTHREAD_CANCEL_ASYNCHRONOUS) { self->pt_flags |= PT_FLAG_CS_ASYNC; if (self->pt_cancel) { - pthread_spinunlock(self, &self->pt_lock); + pthread_spinunlock(&self->pt_lock); pthread_exit(PTHREAD_CANCELED); } } else if (type == PTHREAD_CANCEL_DEFERRED) @@ -777,7 +767,7 @@ pthread_setcanceltype(int type, int *oldtype) else retval = EINVAL; - pthread_spinunlock(self, &self->pt_lock); + pthread_spinunlock(&self->pt_lock); return retval; } @@ -802,15 +792,15 @@ pthread_testcancel() * value without dereferencing it. */ int -pthread__find(pthread_t self, pthread_t id) +pthread__find(pthread_t id) { pthread_t target; - pthread_spinlock(self, &pthread__allqueue_lock); + pthread_spinlock(&pthread__allqueue_lock); PTQ_FOREACH(target, &pthread__allqueue, pt_allq) if (target == id) break; - pthread_spinunlock(self, &pthread__allqueue_lock); + pthread_spinunlock(&pthread__allqueue_lock); if (target == NULL || target->pt_state == PT_STATE_DEAD) return ESRCH; @@ -1021,17 +1011,8 @@ pthread__park(pthread_t self, pthread_spin_t *lock, } } /* Check for cancellation. */ - if (cancelpt && self->pt_cancel) { - /* - * Ensure visibility of the correct value. - * _lwp_park/_lwp_wakeup also provide a - * barrier. - */ - pthread_spinlock(self, &self->pt_lock); - if (self->pt_cancel) - rv = EINTR; - pthread_spinunlock(self, &self->pt_lock); - } + if (cancelpt && self->pt_cancel) + rv = EINTR; } /* @@ -1040,13 +1021,13 @@ pthread__park(pthread_t self, pthread_spin_t *lock, * without holding any locks. */ if (self->pt_sleeponq) { - pthread_spinlock(self, lock); + pthread_spinlock(lock); if (self->pt_sleeponq) { PTQ_REMOVE(queue, self, pt_sleep); self->pt_sleepobj = NULL; self->pt_sleeponq = 0; } - pthread_spinunlock(self, lock); + pthread_spinunlock(lock); } SDPRINTF(("(pthread__park %p) queue %p exit\n", self, queue)); @@ -1061,7 +1042,7 @@ pthread__unpark(pthread_t self, pthread_spin_t *lock, int rv; if (target == NULL) { - pthread_spinunlock(self, lock); + pthread_spinunlock(lock); return; } @@ -1081,7 +1062,7 @@ pthread__unpark(pthread_t self, pthread_spin_t *lock, * to the thread in pthread__park() before the unpark * operation is set in motion. */ - pthread_spinunlock(self, lock); + pthread_spinunlock(lock); /* * If the calling thread is about to block, defer @@ -1109,7 +1090,7 @@ pthread__unpark_all(pthread_t self, pthread_spin_t *lock, pthread_t thread, next; if (PTQ_EMPTY(queue)) { - pthread_spinunlock(self, lock); + pthread_spinunlock(lock); return; } @@ -1159,7 +1140,7 @@ pthread__unpark_all(pthread_t self, pthread_spin_t *lock, * to the thread in pthread__park() before the unpark * operation is set in motion. */ - pthread_spinunlock(self, lock); + pthread_spinunlock(lock); switch (n) { case 0: return; @@ -1190,7 +1171,7 @@ pthread__unpark_all(pthread_t self, pthread_spin_t *lock, } break; } - pthread_spinlock(self, lock); + pthread_spinlock(lock); } } diff --git a/lib/libpthread/pthread_barrier.c b/lib/libpthread/pthread_barrier.c index 6897f63c3c5..3f7956f9dda 100644 --- a/lib/libpthread/pthread_barrier.c +++ b/lib/libpthread/pthread_barrier.c @@ -1,4 +1,4 @@ -/* $NetBSD: pthread_barrier.c,v 1.13 2007/08/04 13:37:49 ad Exp $ */ +/* $NetBSD: pthread_barrier.c,v 1.14 2007/08/16 13:54:16 ad Exp $ */ /*- * Copyright (c) 2001, 2003, 2006, 2007 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: pthread_barrier.c,v 1.13 2007/08/04 13:37:49 ad Exp $"); +__RCSID("$NetBSD: pthread_barrier.c,v 1.14 2007/08/16 13:54:16 ad Exp $"); #include <errno.h> @@ -56,7 +56,6 @@ int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count) { - pthread_t self; #ifdef ERRORCHECK if ((barrier == NULL) || @@ -67,22 +66,20 @@ pthread_barrier_init(pthread_barrier_t *barrier, if (count == 0) return EINVAL; - self = pthread__self(); - if (barrier->ptb_magic == _PT_BARRIER_MAGIC) { /* * We're simply reinitializing the barrier to a * new count. */ - pthread_spinlock(self, &barrier->ptb_lock); + pthread_spinlock(&barrier->ptb_lock); if (barrier->ptb_magic != _PT_BARRIER_MAGIC) { - pthread_spinunlock(self, &barrier->ptb_lock); + pthread_spinunlock(&barrier->ptb_lock); return EINVAL; } if (!PTQ_EMPTY(&barrier->ptb_waiters)) { - pthread_spinunlock(self, &barrier->ptb_lock); + pthread_spinunlock(&barrier->ptb_lock); return EBUSY; } @@ -90,7 +87,7 @@ pthread_barrier_init(pthread_barrier_t *barrier, barrier->ptb_curcount = 0; barrier->ptb_generation = 0; - pthread_spinunlock(self, &barrier->ptb_lock); + pthread_spinunlock(&barrier->ptb_lock); return 0; } @@ -109,30 +106,27 @@ pthread_barrier_init(pthread_barrier_t *barrier, int pthread_barrier_destroy(pthread_barrier_t *barrier) { - pthread_t self; #ifdef ERRORCHECK if ((barrier == NULL) || (barrier->ptb_magic != _PT_BARRIER_MAGIC)) return EINVAL; #endif - self = pthread__self(); - - pthread_spinlock(self, &barrier->ptb_lock); + pthread_spinlock(&barrier->ptb_lock); if (barrier->ptb_magic != _PT_BARRIER_MAGIC) { - pthread_spinunlock(self, &barrier->ptb_lock); + pthread_spinunlock(&barrier->ptb_lock); return EINVAL; } if (!PTQ_EMPTY(&barrier->ptb_waiters)) { - pthread_spinunlock(self, &barrier->ptb_lock); + pthread_spinunlock(&barrier->ptb_lock); return EBUSY; } barrier->ptb_magic = _PT_BARRIER_DEAD; - pthread_spinunlock(self, &barrier->ptb_lock); + pthread_spinunlock(&barrier->ptb_lock); return 0; } @@ -150,7 +144,7 @@ pthread_barrier_wait(pthread_barrier_t *barrier) #endif self = pthread__self(); - pthread_spinlock(self, &barrier->ptb_lock); + pthread_spinlock(&barrier->ptb_lock); /* * A single arbitrary thread is supposed to return @@ -180,15 +174,15 @@ pthread_barrier_wait(pthread_barrier_t *barrier) PTQ_INSERT_TAIL(&barrier->ptb_waiters, self, pt_sleep); self->pt_sleeponq = 1; self->pt_sleepobj = &barrier->ptb_waiters; - pthread_spinunlock(self, &barrier->ptb_lock); + pthread_spinunlock(&barrier->ptb_lock); (void)pthread__park(self, &barrier->ptb_lock, &barrier->ptb_waiters, NULL, 0, &barrier->ptb_waiters); SDPRINTF(("(barrier wait %p) Woke up on %p\n", self, barrier)); - pthread_spinlock(self, &barrier->ptb_lock); + pthread_spinlock(&barrier->ptb_lock); } - pthread_spinunlock(self, &barrier->ptb_lock); + pthread_spinunlock(&barrier->ptb_lock); return 0; } diff --git a/lib/libpthread/pthread_cond.c b/lib/libpthread/pthread_cond.c index 02d28a7e2c4..983c1413891 100644 --- a/lib/libpthread/pthread_cond.c +++ b/lib/libpthread/pthread_cond.c @@ -1,4 +1,4 @@ -/* $NetBSD: pthread_cond.c,v 1.33 2007/08/07 19:04:21 ad Exp $ */ +/* $NetBSD: pthread_cond.c,v 1.34 2007/08/16 13:54:16 ad Exp $ */ /*- * Copyright (c) 2001, 2006, 2007 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: pthread_cond.c,v 1.33 2007/08/07 19:04:21 ad Exp $"); +__RCSID("$NetBSD: pthread_cond.c,v 1.34 2007/08/16 13:54:16 ad Exp $"); #include <errno.h> #include <sys/time.h> @@ -118,7 +118,7 @@ pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) * performance it's critical that the spinlock is held for * as short a time as possible - that means no system calls. */ - pthread_spinlock(self, &cond->ptc_lock); + pthread_spinlock(&cond->ptc_lock); if (cond->ptc_mutex == NULL) cond->ptc_mutex = mutex; else { @@ -132,7 +132,7 @@ pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) self->pt_signalled = 0; self->pt_sleeponq = 1; self->pt_sleepobj = &cond->ptc_waiters; - pthread_spinunlock(self, &cond->ptc_lock); + pthread_spinunlock(&cond->ptc_lock); /* * Before releasing the mutex, note that this thread is @@ -155,10 +155,10 @@ pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) * last issued a wakeup. */ if (PTQ_EMPTY(&cond->ptc_waiters) && cond->ptc_mutex != NULL) { - pthread_spinlock(self, &cond->ptc_lock); + pthread_spinlock(&cond->ptc_lock); if (PTQ_EMPTY(&cond->ptc_waiters)) cond->ptc_mutex = NULL; - pthread_spinunlock(self, &cond->ptc_lock); + pthread_spinunlock(&cond->ptc_lock); } /* @@ -208,7 +208,7 @@ pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, * performance it's critical that the spinlock is held for * as short a time as possible - that means no system calls. */ - pthread_spinlock(self, &cond->ptc_lock); + pthread_spinlock(&cond->ptc_lock); if (cond->ptc_mutex == NULL) cond->ptc_mutex = mutex; else { @@ -222,7 +222,7 @@ pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, self->pt_signalled = 0; self->pt_sleeponq = 1; self->pt_sleepobj = &cond->ptc_waiters; - pthread_spinunlock(self, &cond->ptc_lock); + pthread_spinunlock(&cond->ptc_lock); /* * Before releasing the mutex, note that this thread is @@ -245,10 +245,10 @@ pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, * last issued a wakeup. */ if (PTQ_EMPTY(&cond->ptc_waiters) && cond->ptc_mutex != NULL) { - pthread_spinlock(self, &cond->ptc_lock); + pthread_spinlock(&cond->ptc_lock); if (PTQ_EMPTY(&cond->ptc_waiters)) cond->ptc_mutex = NULL; - pthread_spinunlock(self, &cond->ptc_lock); + pthread_spinunlock(&cond->ptc_lock); } /* @@ -281,7 +281,7 @@ pthread_cond_signal(pthread_cond_t *cond) return 0; self = pthread__self(); - pthread_spinlock(self, &cond->ptc_lock); + pthread_spinlock(&cond->ptc_lock); /* * Find a thread that is still blocked (no pending wakeup). @@ -294,7 +294,7 @@ pthread_cond_signal(pthread_cond_t *cond) } if (__predict_false(signaled == NULL)) { cond->ptc_mutex = NULL; - pthread_spinunlock(self, &cond->ptc_lock); + pthread_spinunlock(&cond->ptc_lock); return 0; } @@ -323,10 +323,10 @@ pthread_cond_signal(pthread_cond_t *cond) * thread) releases the mutex. */ if (self->pt_mutexhint != NULL && self->pt_mutexhint == mutex) { - pthread_spinunlock(self, &cond->ptc_lock); - pthread_spinlock(self, &mutex->ptm_interlock); + pthread_spinunlock(&cond->ptc_lock); + pthread_spinlock(&mutex->ptm_interlock); PTQ_INSERT_HEAD(&mutex->ptm_blocked, signaled, pt_sleep); - pthread_spinunlock(self, &mutex->ptm_interlock); + pthread_spinunlock(&mutex->ptm_interlock); } else { pthread__unpark(self, &cond->ptc_lock, &cond->ptc_waiters, signaled); @@ -352,7 +352,7 @@ pthread_cond_broadcast(pthread_cond_t *cond) return 0; self = pthread__self(); - pthread_spinlock(self, &cond->ptc_lock); + pthread_spinlock(&cond->ptc_lock); mutex = cond->ptc_mutex; cond->ptc_mutex = NULL; @@ -362,7 +362,7 @@ pthread_cond_broadcast(pthread_cond_t *cond) * there is no pending wakeup. */ if (self->pt_mutexhint != NULL && self->pt_mutexhint == mutex) { - pthread_spinlock(self, &mutex->ptm_interlock); + pthread_spinlock(&mutex->ptm_interlock); for (signaled = PTQ_FIRST(&cond->ptc_waiters); signaled != NULL; signaled = next) { @@ -373,8 +373,8 @@ pthread_cond_broadcast(pthread_cond_t *cond) PTQ_INSERT_HEAD(&mutex->ptm_blocked, signaled, pt_sleep); } - pthread_spinunlock(self, &mutex->ptm_interlock); - pthread_spinunlock(self, &cond->ptc_lock); + pthread_spinunlock(&mutex->ptm_interlock); + pthread_spinunlock(&cond->ptc_lock); } else pthread__unpark_all(self, &cond->ptc_lock, &cond->ptc_waiters); diff --git a/lib/libpthread/pthread_int.h b/lib/libpthread/pthread_int.h index 307969c9edc..6e2b82ba97d 100644 --- a/lib/libpthread/pthread_int.h +++ b/lib/libpthread/pthread_int.h @@ -1,4 +1,4 @@ -/* $NetBSD: pthread_int.h,v 1.48 2007/08/16 12:01:49 ad Exp $ */ +/* $NetBSD: pthread_int.h,v 1.49 2007/08/16 13:54:16 ad Exp $ */ /*- * Copyright (c) 2001, 2002, 2003, 2006, 2007 The NetBSD Foundation, Inc. @@ -170,10 +170,10 @@ int pthread__park(pthread_t self, pthread_spin_t *lock, /* Internal locking primitives */ void pthread__lockprim_init(void); -void pthread_lockinit(pthread_spin_t *lock); -void pthread_spinlock(pthread_t thread, pthread_spin_t *lock); -int pthread_spintrylock(pthread_t thread, pthread_spin_t *lock); -void pthread_spinunlock(pthread_t thread, pthread_spin_t *lock); +void pthread_lockinit(pthread_spin_t *); +void pthread_spinlock(pthread_spin_t *); +int pthread_spintrylock(pthread_spin_t *); +void pthread_spinunlock(pthread_spin_t *); extern const struct pthread_lock_ops *pthread__lock_ops; @@ -191,8 +191,8 @@ int _setcontext_u(const ucontext_t *); int _swapcontext_u(ucontext_t *, const ucontext_t *); #endif -void pthread__testcancel(pthread_t self); -int pthread__find(pthread_t self, pthread_t target); +void pthread__testcancel(pthread_t); +int pthread__find(pthread_t); #ifndef PTHREAD_MD_INIT #define PTHREAD_MD_INIT @@ -242,6 +242,7 @@ void pthread__errorfunc(const char *file, int line, const char *function, #if defined(i386) || defined(__x86_64__) #define pthread__smt_pause() __asm __volatile("rep; nop" ::: "memory") +#define PTHREAD__CHEAP_UNLOCK #else #define pthread__smt_pause() /* nothing */ #endif diff --git a/lib/libpthread/pthread_lock.c b/lib/libpthread/pthread_lock.c index f39c68f4a0c..c5f8d027881 100644 --- a/lib/libpthread/pthread_lock.c +++ b/lib/libpthread/pthread_lock.c @@ -1,4 +1,4 @@ -/* $NetBSD: pthread_lock.c,v 1.22 2007/08/16 12:01:49 ad Exp $ */ +/* $NetBSD: pthread_lock.c,v 1.23 2007/08/16 13:54:17 ad Exp $ */ /*- * Copyright (c) 2001, 2006, 2007 The NetBSD Foundation, Inc. @@ -36,8 +36,12 @@ * POSSIBILITY OF SUCH DAMAGE. */ +/* + * libpthread internal spinlock routines. + */ + #include <sys/cdefs.h> -__RCSID("$NetBSD: pthread_lock.c,v 1.22 2007/08/16 12:01:49 ad Exp $"); +__RCSID("$NetBSD: pthread_lock.c,v 1.23 2007/08/16 13:54:17 ad Exp $"); #include <sys/types.h> #include <sys/lock.h> @@ -60,9 +64,12 @@ __RCSID("$NetBSD: pthread_lock.c,v 1.22 2007/08/16 12:01:49 ad Exp $"); #define SDPRINTF(x) #endif +static void pthread_spinlock_slow(pthread_spin_t *); + static int pthread__atomic; RAS_DECL(pthread__lock); +RAS_DECL(pthread__lock2); void pthread__simple_lock_init(__cpu_simple_lock_t *alp) @@ -96,67 +103,66 @@ inline void pthread__simple_unlock(__cpu_simple_lock_t *alp) { +#ifdef PTHREAD__CHEAP_UNLOCK + __cpu_simple_unlock(alp); +#else if (pthread__atomic) { __cpu_simple_unlock(alp); return; } - *alp = __SIMPLELOCK_UNLOCKED; +#endif } -/* - * Initialize the locking primitives. On uniprocessors, we always - * use Restartable Atomic Sequences if they are available. Otherwise, - * we fall back onto machine-dependent atomic lock primitives. - */ void -pthread__lockprim_init(void) +pthread_spinlock(pthread_spin_t *lock) { - char *p; - - if ((p = getenv("PTHREAD_NSPINS")) != NULL) - pthread__nspins = atoi(p); - else if (pthread__concurrency != 1) - pthread__nspins = PTHREAD__NSPINS; - else - pthread__nspins = 1; +#ifdef PTHREAD_SPIN_DEBUG + pthread_t thread = pthread__self(); - if (pthread__concurrency != 1) { - pthread__atomic = 1; - return; - } + SDPRINTF(("(pthread_spinlock %p) spinlock %p (count %d)\n", + thread, lock, thread->pt_spinlocks)); + pthread__assert(thread->pt_spinlocks >= 0); + thread->pt_spinlocks++; +#endif - if (rasctl(RAS_ADDR(pthread__lock), RAS_SIZE(pthread__lock), - RAS_INSTALL) != 0) { - pthread__atomic = 1; - return; - } -} + if (pthread__atomic) { + if (__predict_false(!__cpu_simple_lock_try(lock))) { + pthread_spinlock_slow(lock); + return; + } + } else { + __cpu_simple_lock_t old; -void -pthread_lockinit(pthread_spin_t *lock) -{ + RAS_START(pthread__lock2); + old = *lock; + *lock = __SIMPLELOCK_LOCKED; + RAS_END(pthread__lock2); - pthread__simple_lock_init(lock); + if (__predict_false(old != __SIMPLELOCK_UNLOCKED)) { + pthread_spinlock_slow(lock); + return; + } + } + + PTHREADD_ADD(PTHREADD_SPINLOCKS); } -void -pthread_spinlock(pthread_t thread, pthread_spin_t *lock) +/* + * Prevent this routine from being inlined. The common case is no + * contention and it's better to not burden the instruction decoder. + */ +#if __GNUC_PREREQ__(3, 0) +__attribute ((noinline)) +#endif +static void +pthread_spinlock_slow(pthread_spin_t *lock) { int count; - - SDPRINTF(("(pthread_spinlock %p) spinlock %p (count %d)\n", - thread, lock, thread->pt_spinlocks)); #ifdef PTHREAD_SPIN_DEBUG - pthread__assert(thread->pt_spinlocks >= 0); + pthread_t thread = pthread__self(); #endif - thread->pt_spinlocks++; - if (__predict_true(pthread__simple_lock_try(lock))) { - PTHREADD_ADD(PTHREADD_SPINLOCKS); - return; - } - do { count = pthread__nspins; while (*lock == __SIMPLELOCK_LOCKED && --count > 0) @@ -167,133 +173,98 @@ pthread_spinlock(pthread_t thread, pthread_spin_t *lock) continue; } +#ifdef PTHREAD_SPIN_DEBUG SDPRINTF(("(pthread_spinlock %p) retrying spinlock %p " "(count %d)\n", thread, lock, thread->pt_spinlocks)); thread->pt_spinlocks--; - /* XXXLWP far from ideal */ sched_yield(); thread->pt_spinlocks++; +#else + /* XXXLWP far from ideal */ + sched_yield(); +#endif } while (/*CONSTCOND*/ 1); PTHREADD_ADD(PTHREADD_SPINLOCKS); } int -pthread_spintrylock(pthread_t thread, pthread_spin_t *lock) +pthread_spintrylock(pthread_spin_t *lock) { +#ifdef PTHREAD_SPIN_DEBUG + pthread_t thread = pthread__self(); int ret; SDPRINTF(("(pthread_spintrylock %p) spinlock %p (count %d)\n", thread, lock, thread->pt_spinlocks)); - thread->pt_spinlocks++; ret = pthread__simple_lock_try(lock); if (!ret) thread->pt_spinlocks--; - return ret; +#else + return pthread__simple_lock_try(lock); +#endif } void -pthread_spinunlock(pthread_t thread, pthread_spin_t *lock) +pthread_spinunlock(pthread_spin_t *lock) { +#ifdef PTHREAD_SPIN_DEBUG + pthread_t thread = pthread__self(); SDPRINTF(("(pthread_spinunlock %p) spinlock %p (count %d)\n", thread, lock, thread->pt_spinlocks)); pthread__simple_unlock(lock); thread->pt_spinlocks--; -#ifdef PTHREAD_SPIN_DEBUG pthread__assert(thread->pt_spinlocks >= 0); -#endif PTHREADD_ADD(PTHREADD_SPINUNLOCKS); -} - - -/* - * Public (POSIX-specified) spinlocks. - */ -int -pthread_spin_init(pthread_spinlock_t *lock, int pshared) -{ - -#ifdef ERRORCHECK - if (lock == NULL || (pshared != PTHREAD_PROCESS_PRIVATE && - pshared != PTHREAD_PROCESS_SHARED)) - return EINVAL; -#endif - lock->pts_magic = _PT_SPINLOCK_MAGIC; - - /* - * We don't actually use the pshared flag for anything; - * CPU simple locks have all the process-shared properties - * that we want anyway. - */ - lock->pts_flags = pshared; - pthread_lockinit(&lock->pts_spin); - - return 0; -} - -int -pthread_spin_destroy(pthread_spinlock_t *lock) -{ - -#ifdef ERRORCHECK - if (lock == NULL || lock->pts_magic != _PT_SPINLOCK_MAGIC) - return EINVAL; - if (lock->pts_spin != __SIMPLELOCK_UNLOCKED) - return EBUSY; +#else + pthread__simple_unlock(lock); #endif - - lock->pts_magic = _PT_SPINLOCK_DEAD; - - return 0; } -int -pthread_spin_lock(pthread_spinlock_t *lock) +/* + * Initialize the locking primitives. On uniprocessors, we always + * use Restartable Atomic Sequences if they are available. Otherwise, + * we fall back onto machine-dependent atomic lock primitives. + */ +void +pthread__lockprim_init(void) { + char *p; -#ifdef ERRORCHECK - if (lock == NULL || lock->pts_magic != _PT_SPINLOCK_MAGIC) - return EINVAL; -#endif + if ((p = getenv("PTHREAD_NSPINS")) != NULL) + pthread__nspins = atoi(p); + else if (pthread__concurrency != 1) + pthread__nspins = PTHREAD__NSPINS; + else + pthread__nspins = 1; - while (pthread__simple_lock_try(&lock->pts_spin) == 0) { - pthread__smt_pause(); + if (pthread__concurrency != 1) { + pthread__atomic = 1; + return; } - return 0; -} - -int -pthread_spin_trylock(pthread_spinlock_t *lock) -{ - -#ifdef ERRORCHECK - if (lock == NULL || lock->pts_magic != _PT_SPINLOCK_MAGIC) - return EINVAL; -#endif - - if (pthread__simple_lock_try(&lock->pts_spin) == 0) - return EBUSY; + if (rasctl(RAS_ADDR(pthread__lock), RAS_SIZE(pthread__lock), + RAS_INSTALL) != 0) { + pthread__atomic = 1; + return; + } - return 0; + if (rasctl(RAS_ADDR(pthread__lock2), RAS_SIZE(pthread__lock2), + RAS_INSTALL) != 0) { + pthread__atomic = 1; + return; + } } -int -pthread_spin_unlock(pthread_spinlock_t *lock) +void +pthread_lockinit(pthread_spin_t *lock) { -#ifdef ERRORCHECK - if (lock == NULL || lock->pts_magic != _PT_SPINLOCK_MAGIC) - return EINVAL; -#endif - - pthread__simple_unlock(&lock->pts_spin); - - return 0; + pthread__simple_lock_init(lock); } diff --git a/lib/libpthread/pthread_misc.c b/lib/libpthread/pthread_misc.c index 5e3ef1313e7..62089aa7664 100644 --- a/lib/libpthread/pthread_misc.c +++ b/lib/libpthread/pthread_misc.c @@ -1,4 +1,4 @@ -/* $NetBSD: pthread_misc.c,v 1.1 2007/03/02 18:53:52 ad Exp $ */ +/* $NetBSD: pthread_misc.c,v 1.2 2007/08/16 13:54:17 ad Exp $ */ /*- * Copyright (c) 2001, 2006, 2007 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: pthread_misc.c,v 1.1 2007/03/02 18:53:52 ad Exp $"); +__RCSID("$NetBSD: pthread_misc.c,v 1.2 2007/08/16 13:54:17 ad Exp $"); #include <sys/types.h> #include <sys/signal.h> @@ -83,13 +83,10 @@ pthread_setschedparam(pthread_t thread, int policy, int pthread_kill(pthread_t thread, int sig) { - pthread_t self; - - self = pthread__self(); if ((sig < 0) || (sig >= _NSIG)) return EINVAL; - if (pthread__find(self, thread) != 0) + if (pthread__find(thread) != 0) return ESRCH; return _lwp_kill(thread->pt_lid, sig); diff --git a/lib/libpthread/pthread_mutex.c b/lib/libpthread/pthread_mutex.c index bb9024faf00..b0371fe22b8 100644 --- a/lib/libpthread/pthread_mutex.c +++ b/lib/libpthread/pthread_mutex.c @@ -1,4 +1,4 @@ -/* $NetBSD: pthread_mutex.c,v 1.29 2007/08/04 13:37:49 ad Exp $ */ +/* $NetBSD: pthread_mutex.c,v 1.30 2007/08/16 13:54:17 ad Exp $ */ /*- * Copyright (c) 2001, 2003, 2006, 2007 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: pthread_mutex.c,v 1.29 2007/08/04 13:37:49 ad Exp $"); +__RCSID("$NetBSD: pthread_mutex.c,v 1.30 2007/08/16 13:54:17 ad Exp $"); #include <errno.h> #include <limits.h> @@ -210,7 +210,7 @@ pthread_mutex_lock_slow(pthread_t self, pthread_mutex_t *mutex) } /* Okay, didn't look free. Get the interlock... */ - pthread_spinlock(self, &mutex->ptm_interlock); + pthread_spinlock(&mutex->ptm_interlock); /* * The mutex_unlock routine will get the interlock @@ -222,7 +222,7 @@ pthread_mutex_lock_slow(pthread_t self, pthread_mutex_t *mutex) PTQ_INSERT_HEAD(&mutex->ptm_blocked, self, pt_sleep); if (mutex->ptm_lock != __SIMPLELOCK_LOCKED) { PTQ_REMOVE(&mutex->ptm_blocked, self, pt_sleep); - pthread_spinunlock(self, &mutex->ptm_interlock); + pthread_spinunlock(&mutex->ptm_interlock); continue; } @@ -232,7 +232,7 @@ pthread_mutex_lock_slow(pthread_t self, pthread_mutex_t *mutex) switch (mp->type) { case PTHREAD_MUTEX_ERRORCHECK: PTQ_REMOVE(&mutex->ptm_blocked, self, pt_sleep); - pthread_spinunlock(self, &mutex->ptm_interlock); + pthread_spinunlock(&mutex->ptm_interlock); return EDEADLK; case PTHREAD_MUTEX_RECURSIVE: @@ -243,7 +243,7 @@ pthread_mutex_lock_slow(pthread_t self, pthread_mutex_t *mutex) * own the mutex. */ PTQ_REMOVE(&mutex->ptm_blocked, self, pt_sleep); - pthread_spinunlock(self, &mutex->ptm_interlock); + pthread_spinunlock(&mutex->ptm_interlock); if (mp->recursecount == INT_MAX) return EAGAIN; mp->recursecount++; @@ -271,7 +271,7 @@ pthread_mutex_lock_slow(pthread_t self, pthread_mutex_t *mutex) */ self->pt_sleeponq = 1; self->pt_sleepobj = &mutex->ptm_blocked; - pthread_spinunlock(self, &mutex->ptm_interlock); + pthread_spinunlock(&mutex->ptm_interlock); (void)pthread__park(self, &mutex->ptm_interlock, &mutex->ptm_blocked, NULL, 0, &mutex->ptm_blocked); } @@ -380,7 +380,7 @@ pthread_mutex_unlock(pthread_mutex_t *mutex) if (self->pt_mutexhint == mutex) self->pt_mutexhint = NULL; - pthread_spinlock(self, &mutex->ptm_interlock); + pthread_spinlock(&mutex->ptm_interlock); pthread__unpark_all(self, &mutex->ptm_interlock, &mutex->ptm_blocked); return 0; diff --git a/lib/libpthread/pthread_rwlock.c b/lib/libpthread/pthread_rwlock.c index f7f5c6c879c..5f5044d1484 100644 --- a/lib/libpthread/pthread_rwlock.c +++ b/lib/libpthread/pthread_rwlock.c @@ -1,4 +1,4 @@ -/* $NetBSD: pthread_rwlock.c,v 1.19 2007/08/04 13:37:50 ad Exp $ */ +/* $NetBSD: pthread_rwlock.c,v 1.20 2007/08/16 13:54:17 ad Exp $ */ /*- * Copyright (c) 2002, 2006, 2007 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: pthread_rwlock.c,v 1.19 2007/08/04 13:37:50 ad Exp $"); +__RCSID("$NetBSD: pthread_rwlock.c,v 1.20 2007/08/16 13:54:17 ad Exp $"); #include <errno.h> @@ -100,10 +100,10 @@ pthread_rwlock_rdlock(pthread_rwlock_t *rwlock) #endif self = pthread__self(); - pthread_spinlock(self, &rwlock->ptr_interlock); + pthread_spinlock(&rwlock->ptr_interlock); #ifdef ERRORCHECK if (rwlock->ptr_writer == self) { - pthread_spinunlock(self, &rwlock->ptr_interlock); + pthread_spinunlock(&rwlock->ptr_interlock); return EDEADLK; } #endif @@ -117,14 +117,14 @@ pthread_rwlock_rdlock(pthread_rwlock_t *rwlock) PTQ_INSERT_TAIL(&rwlock->ptr_rblocked, self, pt_sleep); self->pt_sleeponq = 1; self->pt_sleepobj = &rwlock->ptr_rblocked; - pthread_spinunlock(self, &rwlock->ptr_interlock); + pthread_spinunlock(&rwlock->ptr_interlock); (void)pthread__park(self, &rwlock->ptr_interlock, &rwlock->ptr_rblocked, NULL, 0, &rwlock->ptr_rblocked); - pthread_spinlock(self, &rwlock->ptr_interlock); + pthread_spinlock(&rwlock->ptr_interlock); } rwlock->ptr_nreaders++; - pthread_spinunlock(self, &rwlock->ptr_interlock); + pthread_spinunlock(&rwlock->ptr_interlock); return 0; } @@ -133,14 +133,13 @@ pthread_rwlock_rdlock(pthread_rwlock_t *rwlock) int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock) { - pthread_t self; + #ifdef ERRORCHECK if ((rwlock == NULL) || (rwlock->ptr_magic != _PT_RWLOCK_MAGIC)) return EINVAL; #endif - self = pthread__self(); - pthread_spinlock(self, &rwlock->ptr_interlock); + pthread_spinlock(&rwlock->ptr_interlock); /* * Don't get a readlock if there is a writer or if there are waiting * writers; i.e. prefer writers to readers. This strategy is dictated @@ -148,12 +147,12 @@ pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock) */ if ((rwlock->ptr_writer != NULL) || (!PTQ_EMPTY(&rwlock->ptr_wblocked))) { - pthread_spinunlock(self, &rwlock->ptr_interlock); + pthread_spinunlock(&rwlock->ptr_interlock); return EBUSY; } rwlock->ptr_nreaders++; - pthread_spinunlock(self, &rwlock->ptr_interlock); + pthread_spinunlock(&rwlock->ptr_interlock); return 0; } @@ -171,10 +170,10 @@ pthread_rwlock_wrlock(pthread_rwlock_t *rwlock) #endif self = pthread__self(); - pthread_spinlock(self, &rwlock->ptr_interlock); + pthread_spinlock(&rwlock->ptr_interlock); #ifdef ERRORCHECK if (rwlock->ptr_writer == self) { - pthread_spinunlock(self, &rwlock->ptr_interlock); + pthread_spinunlock(&rwlock->ptr_interlock); return EDEADLK; } #endif @@ -185,21 +184,21 @@ pthread_rwlock_wrlock(pthread_rwlock_t *rwlock) while ((rwlock->ptr_nreaders > 0) || (rwlock->ptr_writer != NULL)) { #ifdef ERRORCHECK if (pthread__started == 0) { - pthread_spinunlock(self, &rwlock->ptr_interlock); + pthread_spinunlock(&rwlock->ptr_interlock); return EDEADLK; } #endif PTQ_INSERT_TAIL(&rwlock->ptr_wblocked, self, pt_sleep); self->pt_sleeponq = 1; self->pt_sleepobj = &rwlock->ptr_wblocked; - pthread_spinunlock(self, &rwlock->ptr_interlock); + pthread_spinunlock(&rwlock->ptr_interlock); (void)pthread__park(self, &rwlock->ptr_interlock, &rwlock->ptr_wblocked, NULL, 0, &rwlock->ptr_wblocked); - pthread_spinlock(self, &rwlock->ptr_interlock); + pthread_spinlock(&rwlock->ptr_interlock); } rwlock->ptr_writer = self; - pthread_spinunlock(self, &rwlock->ptr_interlock); + pthread_spinunlock(&rwlock->ptr_interlock); return 0; } @@ -215,18 +214,18 @@ pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock) #endif self = pthread__self(); - pthread_spinlock(self, &rwlock->ptr_interlock); + pthread_spinlock(&rwlock->ptr_interlock); /* * Prefer writers to readers here; permit writers even if there are * waiting readers. */ if ((rwlock->ptr_nreaders > 0) || (rwlock->ptr_writer != NULL)) { - pthread_spinunlock(self, &rwlock->ptr_interlock); + pthread_spinunlock(&rwlock->ptr_interlock); return EBUSY; } rwlock->ptr_writer = self; - pthread_spinunlock(self, &rwlock->ptr_interlock); + pthread_spinunlock(&rwlock->ptr_interlock); return 0; } @@ -251,10 +250,10 @@ pthread_rwlock_timedrdlock(pthread_rwlock_t *rwlock, return EINVAL; self = pthread__self(); - pthread_spinlock(self, &rwlock->ptr_interlock); + pthread_spinlock(&rwlock->ptr_interlock); #ifdef ERRORCHECK if (rwlock->ptr_writer == self) { - pthread_spinunlock(self, &rwlock->ptr_interlock); + pthread_spinunlock(&rwlock->ptr_interlock); return EDEADLK; } #endif @@ -269,11 +268,11 @@ pthread_rwlock_timedrdlock(pthread_rwlock_t *rwlock, PTQ_INSERT_TAIL(&rwlock->ptr_rblocked, self, pt_sleep); self->pt_sleeponq = 1; self->pt_sleepobj = &rwlock->ptr_rblocked; - pthread_spinunlock(self, &rwlock->ptr_interlock); + pthread_spinunlock(&rwlock->ptr_interlock); retval = pthread__park(self, &rwlock->ptr_interlock, &rwlock->ptr_rblocked, abs_timeout, 0, &rwlock->ptr_rblocked); - pthread_spinlock(self, &rwlock->ptr_interlock); + pthread_spinlock(&rwlock->ptr_interlock); } /* One last chance to get the lock, in case it was released between @@ -284,7 +283,7 @@ pthread_rwlock_timedrdlock(pthread_rwlock_t *rwlock, rwlock->ptr_nreaders++; retval = 0; } - pthread_spinunlock(self, &rwlock->ptr_interlock); + pthread_spinunlock(&rwlock->ptr_interlock); return retval; } @@ -310,10 +309,10 @@ pthread_rwlock_timedwrlock(pthread_rwlock_t *rwlock, return EINVAL; self = pthread__self(); - pthread_spinlock(self, &rwlock->ptr_interlock); + pthread_spinlock(&rwlock->ptr_interlock); #ifdef ERRORCHECK if (rwlock->ptr_writer == self) { - pthread_spinunlock(self, &rwlock->ptr_interlock); + pthread_spinunlock(&rwlock->ptr_interlock); return EDEADLK; } #endif @@ -326,25 +325,25 @@ pthread_rwlock_timedwrlock(pthread_rwlock_t *rwlock, ((rwlock->ptr_nreaders > 0) || (rwlock->ptr_writer != NULL))) { #ifdef ERRORCHECK if (pthread__started == 0) { - pthread_spinunlock(self, &rwlock->ptr_interlock); + pthread_spinunlock(&rwlock->ptr_interlock); return EDEADLK; } #endif PTQ_INSERT_TAIL(&rwlock->ptr_wblocked, self, pt_sleep); self->pt_sleeponq = 1; self->pt_sleepobj = &rwlock->ptr_wblocked; - pthread_spinunlock(self, &rwlock->ptr_interlock); + pthread_spinunlock(&rwlock->ptr_interlock); retval = pthread__park(self, &rwlock->ptr_interlock, &rwlock->ptr_wblocked, abs_timeout, 0, &rwlock->ptr_wblocked); - pthread_spinlock(self, &rwlock->ptr_interlock); + pthread_spinlock(&rwlock->ptr_interlock); } if ((rwlock->ptr_nreaders == 0) && (rwlock->ptr_writer == NULL)) { rwlock->ptr_writer = self; retval = 0; } - pthread_spinunlock(self, &rwlock->ptr_interlock); + pthread_spinunlock(&rwlock->ptr_interlock); return retval; } @@ -361,12 +360,12 @@ pthread_rwlock_unlock(pthread_rwlock_t *rwlock) writer = NULL; self = pthread__self(); - pthread_spinlock(self, &rwlock->ptr_interlock); + pthread_spinlock(&rwlock->ptr_interlock); if (rwlock->ptr_writer != NULL) { /* Releasing a write lock. */ #ifdef ERRORCHECK if (rwlock->ptr_writer != self) { - pthread_spinunlock(self, &rwlock->ptr_interlock); + pthread_spinunlock(&rwlock->ptr_interlock); return EPERM; } #endif @@ -390,7 +389,7 @@ pthread_rwlock_unlock(pthread_rwlock_t *rwlock) } #ifdef ERRORCHECK } else { - pthread_spinunlock(self, &rwlock->ptr_interlock); + pthread_spinunlock(&rwlock->ptr_interlock); return EPERM; #endif } diff --git a/lib/libpthread/pthread_spin.c b/lib/libpthread/pthread_spin.c new file mode 100644 index 00000000000..1e7af0ee544 --- /dev/null +++ b/lib/libpthread/pthread_spin.c @@ -0,0 +1,139 @@ +/* $NetBSD: pthread_spin.c,v 1.1 2007/08/16 13:54:17 ad Exp $ */ + +/*- + * Copyright (c) 2001, 2006, 2007 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Nathan J. Williams and Andrew Doran. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Public (POSIX-specified) spinlocks. + */ + +#include <sys/cdefs.h> +__RCSID("$NetBSD: pthread_spin.c,v 1.1 2007/08/16 13:54:17 ad Exp $"); + +#include <sys/types.h> +#include <sys/lock.h> +#include <sys/ras.h> + +#include <errno.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> + +#include "pthread.h" +#include "pthread_int.h" + +int +pthread_spin_init(pthread_spinlock_t *lock, int pshared) +{ + +#ifdef ERRORCHECK + if (lock == NULL || (pshared != PTHREAD_PROCESS_PRIVATE && + pshared != PTHREAD_PROCESS_SHARED)) + return EINVAL; +#endif + lock->pts_magic = _PT_SPINLOCK_MAGIC; + + /* + * We don't actually use the pshared flag for anything; + * CPU simple locks have all the process-shared properties + * that we want anyway. + */ + lock->pts_flags = pshared; + pthread_lockinit(&lock->pts_spin); + + return 0; +} + +int +pthread_spin_destroy(pthread_spinlock_t *lock) +{ + +#ifdef ERRORCHECK + if (lock == NULL || lock->pts_magic != _PT_SPINLOCK_MAGIC) + return EINVAL; + if (lock->pts_spin != __SIMPLELOCK_UNLOCKED) + return EBUSY; +#endif + + lock->pts_magic = _PT_SPINLOCK_DEAD; + + return 0; +} + +int +pthread_spin_lock(pthread_spinlock_t *lock) +{ + +#ifdef ERRORCHECK + if (lock == NULL || lock->pts_magic != _PT_SPINLOCK_MAGIC) + return EINVAL; +#endif + + while (pthread__simple_lock_try(&lock->pts_spin) == 0) { + pthread__smt_pause(); + } + + return 0; +} + +int +pthread_spin_trylock(pthread_spinlock_t *lock) +{ + +#ifdef ERRORCHECK + if (lock == NULL || lock->pts_magic != _PT_SPINLOCK_MAGIC) + return EINVAL; +#endif + + if (pthread__simple_lock_try(&lock->pts_spin) == 0) + return EBUSY; + + return 0; +} + +int +pthread_spin_unlock(pthread_spinlock_t *lock) +{ + +#ifdef ERRORCHECK + if (lock == NULL || lock->pts_magic != _PT_SPINLOCK_MAGIC) + return EINVAL; +#endif + + pthread__simple_unlock(&lock->pts_spin); + + return 0; +} diff --git a/lib/libpthread/sem.c b/lib/libpthread/sem.c index b659cf33719..640cea91a61 100644 --- a/lib/libpthread/sem.c +++ b/lib/libpthread/sem.c @@ -1,4 +1,4 @@ -/* $NetBSD: sem.c,v 1.15 2007/08/04 13:37:50 ad Exp $ */ +/* $NetBSD: sem.c,v 1.16 2007/08/16 13:54:17 ad Exp $ */ /*- * Copyright (c) 2003, 2006, 2007 The NetBSD Foundation, Inc. @@ -66,7 +66,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: sem.c,v 1.15 2007/08/04 13:37:50 ad Exp $"); +__RCSID("$NetBSD: sem.c,v 1.16 2007/08/16 13:54:17 ad Exp $"); #include <sys/types.h> #include <sys/ksem.h> @@ -155,7 +155,6 @@ sem_init(sem_t *sem, int pshared, unsigned int value) int sem_destroy(sem_t *sem) { - pthread_t self; #ifdef ERRORCHECK if (sem == NULL || *sem == NULL || (*sem)->usem_magic != USEM_MAGIC) { @@ -168,14 +167,13 @@ sem_destroy(sem_t *sem) if (_ksem_destroy((*sem)->usem_semid)) return (-1); } else { - self = pthread__self(); - pthread_spinlock(self, &(*sem)->usem_interlock); + pthread_spinlock(&(*sem)->usem_interlock); if (!PTQ_EMPTY(&(*sem)->usem_waiters)) { - pthread_spinunlock(self, &(*sem)->usem_interlock); + pthread_spinunlock(&(*sem)->usem_interlock); errno = EBUSY; return (-1); } - pthread_spinunlock(self, &(*sem)->usem_interlock); + pthread_spinunlock(&(*sem)->usem_interlock); } sem_free(*sem); @@ -320,10 +318,10 @@ sem_wait(sem_t *sem) } queue = &(*sem)->usem_waiters; - pthread_spinlock(self, &(*sem)->usem_interlock); + pthread_spinlock(&(*sem)->usem_interlock); for (;;) { if (self->pt_cancel) { - pthread_spinunlock(self, &(*sem)->usem_interlock); + pthread_spinunlock(&(*sem)->usem_interlock); pthread_exit(PTHREAD_CANCELED); } @@ -333,13 +331,13 @@ sem_wait(sem_t *sem) PTQ_INSERT_TAIL(queue, self, pt_sleep); self->pt_sleeponq = 1; self->pt_sleepobj = queue, - pthread_spinunlock(self, &(*sem)->usem_interlock); + pthread_spinunlock(&(*sem)->usem_interlock); (void)pthread__park(self, &(*sem)->usem_interlock, queue, NULL, 1, queue); - pthread_spinlock(self, &(*sem)->usem_interlock); + pthread_spinlock(&(*sem)->usem_interlock); } (*sem)->usem_count--; - pthread_spinunlock(self, &(*sem)->usem_interlock); + pthread_spinunlock(&(*sem)->usem_interlock); return (0); } @@ -347,7 +345,6 @@ sem_wait(sem_t *sem) int sem_trywait(sem_t *sem) { - pthread_t self; extern int pthread__started; #ifdef ERRORCHECK @@ -376,19 +373,17 @@ sem_trywait(sem_t *sem) return rv; } - self = pthread__self(); - - pthread_spinlock(self, &(*sem)->usem_interlock); + pthread_spinlock(&(*sem)->usem_interlock); if ((*sem)->usem_count == 0) { - pthread_spinunlock(self, &(*sem)->usem_interlock); + pthread_spinunlock(&(*sem)->usem_interlock); errno = EAGAIN; return (-1); } (*sem)->usem_count--; - pthread_spinunlock(self, &(*sem)->usem_interlock); + pthread_spinunlock(&(*sem)->usem_interlock); return (0); } @@ -410,7 +405,7 @@ sem_post(sem_t *sem) self = pthread__self(); - pthread_spinlock(self, &(*sem)->usem_interlock); + pthread_spinlock(&(*sem)->usem_interlock); (*sem)->usem_count++; blocked = PTQ_FIRST(&(*sem)->usem_waiters); if (blocked) { @@ -419,7 +414,7 @@ sem_post(sem_t *sem) pthread__unpark(self, &(*sem)->usem_interlock, &(*sem)->usem_waiters, blocked); } else - pthread_spinunlock(self, &(*sem)->usem_interlock); + pthread_spinunlock(&(*sem)->usem_interlock); return (0); } @@ -427,7 +422,6 @@ sem_post(sem_t *sem) int sem_getvalue(sem_t * __restrict sem, int * __restrict sval) { - pthread_t self; #ifdef ERRORCHECK if (sem == NULL || *sem == NULL || (*sem)->usem_magic != USEM_MAGIC) { @@ -438,11 +432,9 @@ sem_getvalue(sem_t * __restrict sem, int * __restrict sval) if ((*sem)->usem_semid != USEM_USER) return (_ksem_getvalue((*sem)->usem_semid, sval)); - self = pthread__self(); - - pthread_spinlock(self, &(*sem)->usem_interlock); + pthread_spinlock(&(*sem)->usem_interlock); *sval = (int) (*sem)->usem_count; - pthread_spinunlock(self, &(*sem)->usem_interlock); + pthread_spinunlock(&(*sem)->usem_interlock); return (0); } |
