summaryrefslogtreecommitdiff
path: root/lib/libpthread
diff options
context:
space:
mode:
authorad <ad@NetBSD.org>2007-08-16 13:54:16 +0000
committerad <ad@NetBSD.org>2007-08-16 13:54:16 +0000
commitd9adedd76400ff3a3069a7e9f55a78ff6aeb43e8 (patch)
tree4e3cfb7305417e09804e79b93bf94ca7313bc87b /lib/libpthread
parent8423867fa7ce95339fc3981d44d13c064fd8614e (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/Makefile10
-rw-r--r--lib/libpthread/pthread.c137
-rw-r--r--lib/libpthread/pthread_barrier.c34
-rw-r--r--lib/libpthread/pthread_cond.c38
-rw-r--r--lib/libpthread/pthread_int.h15
-rw-r--r--lib/libpthread/pthread_lock.c219
-rw-r--r--lib/libpthread/pthread_misc.c9
-rw-r--r--lib/libpthread/pthread_mutex.c16
-rw-r--r--lib/libpthread/pthread_rwlock.c69
-rw-r--r--lib/libpthread/pthread_spin.c139
-rw-r--r--lib/libpthread/sem.c42
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);
}