summaryrefslogtreecommitdiff
path: root/lib/libpthread
diff options
context:
space:
mode:
authorad <ad@NetBSD.org>2006-12-23 05:14:46 +0000
committerad <ad@NetBSD.org>2006-12-23 05:14:46 +0000
commit1ac6a89b79760f25efddd665a4dca817272bbfaf (patch)
tree16b3f488e238ae2691b2080b7336c138b83ee1b7 /lib/libpthread
parent642cea631210394ce02896c04a12450c9ca8825e (diff)
Conditionalised support for 1:1 threads. Needs associated kernel changes
and more work to be useful.
Diffstat (limited to 'lib/libpthread')
-rw-r--r--lib/libpthread/Makefile12
-rw-r--r--lib/libpthread/pthread.c296
-rw-r--r--lib/libpthread/pthread_alarms.c8
-rw-r--r--lib/libpthread/pthread_barrier.c21
-rw-r--r--lib/libpthread/pthread_cond.c47
-rw-r--r--lib/libpthread/pthread_debug.c19
-rw-r--r--lib/libpthread/pthread_int.h37
-rw-r--r--lib/libpthread/pthread_lock.c15
-rw-r--r--lib/libpthread/pthread_mutex.c33
-rw-r--r--lib/libpthread/pthread_run.c20
-rw-r--r--lib/libpthread/pthread_rwlock.c42
-rw-r--r--lib/libpthread/pthread_sa.c25
-rw-r--r--lib/libpthread/pthread_sig.c42
-rw-r--r--lib/libpthread/pthread_sleep.c22
-rw-r--r--lib/libpthread/pthread_stack.c6
-rw-r--r--lib/libpthread/sem.c29
16 files changed, 600 insertions, 74 deletions
diff --git a/lib/libpthread/Makefile b/lib/libpthread/Makefile
index 1081a354b8d..3a5293d2478 100644
--- a/lib/libpthread/Makefile
+++ b/lib/libpthread/Makefile
@@ -1,6 +1,7 @@
-# $NetBSD: Makefile,v 1.35 2005/12/13 22:07:20 christos Exp $
+# $NetBSD: Makefile,v 1.36 2006/12/23 05:14:46 ad Exp $
#
+PTHREAD_SA=1
WARNS= 2
# Define PT_FIXEDSTACKSIZE_LG to set a fixed stacksize
@@ -28,6 +29,10 @@ ARCHDIR= ${.CURDIR}/arch/${ARCHSUBDIR}
CPPFLAGS+= -I${ARCHDIR} -I${.CURDIR} -I${.OBJDIR} -D_LIBC
CPPFLAGS+= -D__LIBPTHREAD_SOURCE__ -DPTHREAD_MLOCK_KLUDGE
+.if defined(PTHREAD_SA)
+CPPFLAGS+= -DPTHREAD_SA
+.endif
+
# XXX: This crappy poke at libc's internals needs to be fixed.
# We need to put this *after our own includes, so that our "assym.h"
# gets picked, instead of the libc one
@@ -70,7 +75,10 @@ SRCS+= res_state.c
SRCS+= sched.c
SRCS+= sem.c
# Architecture-dependent files
-SRCS+= pthread_switch.S _context_u.S
+.if defined(PTHREAD_SA)
+SRCS+= pthread_switch.S
+.endif
+SRCS+= _context_u.S
.if exists(${ARCHDIR}/pthread_md.c)
SRCS+= pthread_md.c
.endif
diff --git a/lib/libpthread/pthread.c b/lib/libpthread/pthread.c
index b4ad11aed7c..6f758c62d0c 100644
--- a/lib/libpthread/pthread.c
+++ b/lib/libpthread/pthread.c
@@ -1,11 +1,11 @@
-/* $NetBSD: pthread.c,v 1.48 2006/04/24 18:39:36 drochner Exp $ */
+/* $NetBSD: pthread.c,v 1.49 2006/12/23 05:14:46 ad Exp $ */
/*-
- * Copyright (c) 2001,2002,2003 The NetBSD Foundation, Inc.
+ * Copyright (c) 2001, 2002, 2003, 2006 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
- * by Nathan J. Williams.
+ * 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
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: pthread.c,v 1.48 2006/04/24 18:39:36 drochner Exp $");
+__RCSID("$NetBSD: pthread.c,v 1.49 2006/12/23 05:14:46 ad Exp $");
#include <err.h>
#include <errno.h>
@@ -90,6 +90,7 @@ enum {
static int pthread__diagassert = DIAGASSERT_ABORT | DIAGASSERT_STDERR;
+#ifdef PTHREAD_SA
pthread_spin_t pthread__runqueue_lock = __SIMPLELOCK_UNLOCKED;
struct pthread_queue_t pthread__runqueue;
struct pthread_queue_t pthread__idlequeue;
@@ -98,6 +99,7 @@ struct pthread_queue_t pthread__suspqueue;
int pthread__concurrency, pthread__maxconcurrency;
int _sys___sigprocmask14(int, const sigset_t *, sigset_t *);
+#endif
__strong_alias(__libc_thr_self,pthread_self)
__strong_alias(__libc_thr_create,pthread_create)
@@ -110,8 +112,10 @@ __strong_alias(__libc_thr_setcancelstate,pthread_setcancelstate)
* file which does not already have a reference here.
*/
extern int pthread__cancel_stub_binder;
+#ifdef PTHREAD_SA
extern int pthread__sched_binder;
extern struct pthread_queue_t pthread__nanosleeping;
+#endif
void *pthread__static_lib_binder[] = {
&pthread__cancel_stub_binder,
@@ -121,8 +125,10 @@ void *pthread__static_lib_binder[] = {
pthread_barrier_init,
pthread_key_create,
pthread_setspecific,
+#ifdef PTHREAD_SA
&pthread__sched_binder,
&pthread__nanosleeping
+#endif
};
/*
@@ -136,12 +142,15 @@ pthread_init(void)
{
pthread_t first;
char *p;
- int i, mib[2], ncpu;
+ int mib[2], ncpu;
size_t len;
extern int __isthreaded;
#ifdef PTHREAD_MLOCK_KLUDGE
int ret;
#endif
+#ifdef PTHREAD_SA
+ int i;
+#endif
mib[0] = CTL_HW;
mib[1] = HW_NCPU;
@@ -152,6 +161,7 @@ pthread_init(void)
/* Initialize locks first; they're needed elsewhere. */
pthread__lockprim_init(ncpu);
+#ifdef PTHREAD_SA
/* Find out requested/possible concurrency */
p = getenv("PTHREAD_CONCURRENCY");
pthread__maxconcurrency = p ? atoi(p) : 1;
@@ -166,6 +176,7 @@ pthread_init(void)
(pthread__maxconcurrency * sizeof(struct pthread_queue_t));
if (pthread__reidlequeue == NULL)
err(1, "Couldn't allocate memory for pthread__reidlequeue");
+#endif
/* Basic data structure setup */
pthread_attr_init(&pthread_default_attr);
@@ -175,21 +186,29 @@ pthread_init(void)
ret = mlock(&pthread__deadqueue, sizeof(pthread__deadqueue));
pthread__assert(ret == 0);
#endif
+#ifdef PTHREAD_SA
PTQ_INIT(&pthread__runqueue);
PTQ_INIT(&pthread__idlequeue);
for (i = 0; i < pthread__maxconcurrency; i++)
PTQ_INIT(&pthread__reidlequeue[i]);
nthreads = 1;
-
+#endif
/* Create the thread structure corresponding to main() */
pthread__initmain(&first);
pthread__initthread(first, first);
+
first->pt_state = PT_STATE_RUNNING;
+#ifdef PTHREAD_SA
_sys___sigprocmask14(0, NULL, &first->pt_sigmask);
+#else
+ first->pt_lid = _lwp_self();
+#endif
PTQ_INSERT_HEAD(&pthread__allqueue, first, pt_allq);
/* Start subsystems */
+#ifdef PTHREAD_SA
pthread__signal_init();
+#endif
PTHREAD_MD_INIT
#ifdef PTHREAD__DEBUG
pthread__debug_init(ncpu);
@@ -242,8 +261,11 @@ pthread__child_callback(void)
static void
pthread__start(void)
{
- pthread_t self, idle;
+ pthread_t self;
+#ifdef PTHREAD_SA
+ pthread_t idle;
int i, ret;
+#endif
self = pthread__self(); /* should be the "main()" thread */
@@ -252,12 +274,15 @@ pthread__start(void)
* various restrictions on fork() and threads, it's legal to
* fork() before creating any threads.
*/
+#ifdef PTHREAD_SA
pthread__alarm_init();
pthread__signal_start();
+#endif
pthread_atfork(NULL, NULL, pthread__child_callback);
+#ifdef PTHREAD_SA
/*
* Create idle threads
* XXX need to create more idle threads if concurrency > 3
@@ -275,6 +300,8 @@ pthread__start(void)
/* Start up the SA subsystem */
pthread__sa_start();
+#endif
+
SDPRINTF(("(pthread__start %p) Started.\n", self));
}
@@ -292,29 +319,37 @@ pthread__initthread(pthread_t self, pthread_t t)
t->pt_num = id;
t->pt_magic = PT_MAGIC;
- t->pt_type = PT_THREAD_NORMAL;
- t->pt_state = PT_STATE_RUNNABLE;
- pthread_lockinit(&t->pt_statelock);
pthread_lockinit(&t->pt_flaglock);
t->pt_spinlocks = 0;
- t->pt_next = NULL;
t->pt_exitval = NULL;
t->pt_flags = 0;
t->pt_cancel = 0;
t->pt_errno = 0;
- t->pt_parent = NULL;
+
+#ifdef PTHREAD_SA
+ t->pt_type = PT_THREAD_NORMAL;
+ t->pt_state = PT_STATE_RUNNABLE;
t->pt_heldlock = NULL;
+ t->pt_next = NULL;
+ t->pt_parent = NULL;
t->pt_switchto = NULL;
t->pt_trapuc = NULL;
sigemptyset(&t->pt_siglist);
sigemptyset(&t->pt_sigmask);
pthread_lockinit(&t->pt_siglock);
+#else
+ t->pt_state = PT_STATE_RUNNING;
+#endif
+
+ pthread_lockinit(&t->pt_statelock);
+
PTQ_INIT(&t->pt_joiners);
pthread_lockinit(&t->pt_join_lock);
PTQ_INIT(&t->pt_cleanup_stack);
memset(&t->pt_specific, 0, sizeof(int) * PTHREAD_KEYS_MAX);
t->pt_name = NULL;
-#ifdef PTHREAD__DEBUG
+
+#if defined(PTHREAD__DEBUG) && defined(PTHREAD_SA)
t->blocks = 0;
t->preempts = 0;
t->rescheds = 0;
@@ -331,6 +366,9 @@ pthread_create(pthread_t *thread, const pthread_attr_t *attr,
struct pthread_attr_private *p;
char *name;
int ret;
+#ifndef PTHREAD_SA
+ int flag;
+#endif
PTHREADD_ADD(PTHREADD_CREATE);
@@ -378,7 +416,9 @@ pthread_create(pthread_t *thread, const pthread_attr_t *attr,
/* 2. Set up state. */
pthread__initthread(self, newthread);
newthread->pt_flags = nattr.pta_flags;
+#ifdef PTHREAD_SA
newthread->pt_sigmask = self->pt_sigmask;
+#endif
/* 3. Set up misc. attributes. */
newthread->pt_name = name;
@@ -398,12 +438,26 @@ pthread_create(pthread_t *thread, const pthread_attr_t *attr,
makecontext(newthread->pt_uc, pthread__create_tramp, 2,
startfunc, arg);
+#ifndef PTHREAD_SA
+ /* 4a. Create the new LWP. */
+ flag = (newthread->pt_flags & PT_FLAG_SUSPENDED) ? LWP_SUSPENDED : 0;
+ ret = _lwp_create(newthread->pt_uc, (u_long)flag, &newthread->pt_lid);
+ if (ret != 0) {
+ SDPRINTF(("(pthread_create %p) _lwp_create: %s\n",
+ strerror(errno)));
+ /* XXXLWP what else? */
+ free(name);
+ return ret;
+ }
+#endif
+
/* 5. Add to list of all threads. */
pthread_spinlock(self, &pthread__allqueue_lock);
PTQ_INSERT_HEAD(&pthread__allqueue, newthread, pt_allq);
nthreads++;
pthread_spinunlock(self, &pthread__allqueue_lock);
+#ifdef PTHREAD_SA
SDPRINTF(("(pthread_create %p) new thread %p (name pointer %p).\n",
self, newthread, newthread->pt_name));
/* 6. Put on appropriate queue. */
@@ -413,7 +467,12 @@ pthread_create(pthread_t *thread, const pthread_attr_t *attr,
pthread_spinunlock(self, &newthread->pt_statelock);
} else
pthread__sched(self, newthread);
-
+#else
+ SDPRINTF(("(pthread_create %p) new thread %p (name %p, lid %d).\n",
+ self, newthread, newthread->pt_name,
+ (int)newthread->pt_lid));
+#endif
+
*thread = newthread;
return 0;
@@ -446,6 +505,7 @@ pthread_suspend_np(pthread_t thread)
if (pthread__find(self, thread) != 0)
return ESRCH;
#endif
+#ifdef PTHREAD_SA
SDPRINTF(("(pthread_suspend_np %p) Suspend thread %p (state %d).\n",
self, thread, thread->pt_state));
pthread_spinlock(self, &thread->pt_statelock);
@@ -482,6 +542,11 @@ pthread_suspend_np(pthread_t thread)
out:
pthread_spinunlock(self, &thread->pt_statelock);
return 0;
+#else
+ SDPRINTF(("(pthread_suspend_np %p) Suspend thread %p.\n",
+ self, thread));
+ return _lwp_suspend(thread->pt_lid);
+#endif
}
int
@@ -494,6 +559,7 @@ pthread_resume_np(pthread_t thread)
if (pthread__find(self, thread) != 0)
return ESRCH;
#endif
+#ifdef PTHREAD_SA
SDPRINTF(("(pthread_resume_np %p) Resume thread %p (state %d).\n",
self, thread, thread->pt_state));
pthread_spinlock(self, &thread->pt_statelock);
@@ -507,9 +573,14 @@ pthread_resume_np(pthread_t thread)
}
pthread_spinunlock(self, &thread->pt_statelock);
return 0;
+#else
+ SDPRINTF(("(pthread_resume_np %p) Resume thread %p.\n",
+ self, thread));
+ return _lwp_continue(thread->pt_lid);
+#endif
}
-
+#ifdef PTHREAD_SA
/*
* Other threads will switch to the idle thread so that they
* can dispose of any awkward locks or recycle upcall state.
@@ -550,6 +621,7 @@ pthread__idle(void)
SDPRINTF(("(pthread__idle %p) Returned! Error.\n", self));
pthread__abort();
}
+#endif
void
@@ -558,7 +630,9 @@ pthread_exit(void *retval)
pthread_t self;
struct pt_clean_t *cleanup;
char *name;
+#ifdef PTHREAD_SA
int nt;
+#endif
self = pthread__self();
SDPRINTF(("(pthread_exit %p) status %p, flags %x, cancel %d\n",
@@ -598,6 +672,7 @@ pthread_exit(void *retval)
pthread_spinlock(self, &pthread__allqueue_lock);
PTQ_REMOVE(&pthread__allqueue, self, pt_allq);
+#ifdef PTHREAD_SA
nthreads--;
nt = nthreads;
pthread_spinunlock(self, &pthread__allqueue_lock);
@@ -612,8 +687,14 @@ pthread_exit(void *retval)
PTQ_INSERT_HEAD(&pthread__deadqueue, self, pt_allq);
pthread__block(self, &pthread__deadqueue_lock);
SDPRINTF(("(pthread_exit %p) walking dead\n", self));
+#else
+ pthread_spinunlock(self, &pthread__allqueue_lock);
+ _lwp_exit();
+#endif
} else {
self->pt_state = PT_STATE_ZOMBIE;
+
+#ifdef PTHREAD_SA
/* Note: name will be freed by the joiner. */
pthread_spinlock(self, &pthread__allqueue_lock);
nthreads--;
@@ -630,6 +711,10 @@ pthread_exit(void *retval)
pthread__sched_sleepers(self, &self->pt_joiners);
pthread__block(self, &self->pt_join_lock);
SDPRINTF(("(pthread_exit %p) walking zombie\n", self));
+#else
+ pthread_spinunlock(self, &self->pt_join_lock);
+ _lwp_exit();
+#endif
}
/*NOTREACHED*/
@@ -643,7 +728,7 @@ pthread_join(pthread_t thread, void **valptr)
{
pthread_t self;
char *name;
- int num;
+ int num, retval;
self = pthread__self();
SDPRINTF(("(pthread_join %p) Joining %p.\n", self, thread));
@@ -657,6 +742,7 @@ pthread_join(pthread_t thread, void **valptr)
if (thread == self)
return EDEADLK;
+#ifdef PTHREAD_SA
pthread_spinlock(self, &thread->pt_flaglock);
if (thread->pt_flags & PT_FLAG_DETACHED) {
@@ -713,6 +799,35 @@ pthread_join(pthread_t thread, void **valptr)
if (valptr != NULL)
*valptr = thread->pt_exitval;
+ retval = 0;
+#else /* PTHREAD_SA */
+ retval = 0;
+ name = NULL;
+ again:
+ pthread_spinlock(self, &thread->pt_join_lock);
+ switch (thread->pt_state) {
+ case PT_STATE_RUNNING:
+ pthread_spinunlock(self, &thread->pt_join_lock);
+ retval = _lwp_wait(thread->pt_lid, &num);
+ if (retval != 0)
+ return retval;
+ goto again;
+ case PT_STATE_ZOMBIE:
+ if (valptr != NULL)
+ *valptr = thread->pt_exitval; /* XXXLWP search for LWP */
+ if (retval == 0) {
+ name = thread->pt_name;
+ thread->pt_name = NULL;
+ }
+ thread->pt_state = PT_STATE_DEAD;
+ pthread_spinunlock(self, &thread->pt_join_lock);
+ break;
+ default:
+ pthread_spinunlock(self, &thread->pt_join_lock);
+ return EINVAL;
+ }
+#endif /* PTHREAD_SA */
+
SDPRINTF(("(pthread_join %p) Joined %p.\n", self, thread));
pthread__dead(self, thread);
@@ -720,7 +835,7 @@ pthread_join(pthread_t thread, void **valptr)
if (name != NULL)
free(name);
- return 0;
+ return retval;
}
@@ -737,8 +852,10 @@ int
pthread_detach(pthread_t thread)
{
pthread_t self;
+#ifdef PTHREAD_SA
int doreclaim = 0;
char *name = NULL;
+#endif
self = pthread__self();
@@ -748,6 +865,7 @@ pthread_detach(pthread_t thread)
if (thread->pt_magic != PT_MAGIC)
return EINVAL;
+#ifdef PTHREAD_SA
pthread_spinlock(self, &thread->pt_flaglock);
pthread_spinlock(self, &thread->pt_join_lock);
@@ -779,6 +897,9 @@ pthread_detach(pthread_t thread)
}
return 0;
+#else
+ return _lwp_detach(thread->pt_lid);
+#endif
}
@@ -850,11 +971,13 @@ pthread_setname_np(pthread_t thread, const char *name, void *arg)
pthread_spinlock(self, &thread->pt_join_lock);
+#ifdef PTHREAD_SA
if (thread->pt_state == PT_STATE_DEAD) {
pthread_spinunlock(self, &thread->pt_join_lock);
free(cp);
return EINVAL;
}
+#endif
oldname = thread->pt_name;
thread->pt_name = cp;
@@ -891,6 +1014,7 @@ pthread_cancel(pthread_t thread)
if (pthread__find(self, thread) != 0)
return ESRCH;
#endif
+#ifdef PTHREAD_SA
if (!(thread->pt_state == PT_STATE_RUNNING ||
thread->pt_state == PT_STATE_RUNNABLE ||
thread->pt_state == PT_STATE_BLOCKED_QUEUE))
@@ -934,6 +1058,16 @@ pthread_cancel(pthread_t thread)
pthread_spinunlock(self, &thread->pt_statelock);
} else
pthread_spinunlock(self, &thread->pt_flaglock);
+#else
+ pthread_spinlock(self, &thread->pt_flaglock);
+ 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_flaglock);
+ _lwp_wakeup(thread->pt_lid);
+ } else
+ pthread_spinunlock(self, &thread->pt_flaglock);
+#endif
return 0;
}
@@ -1166,3 +1300,131 @@ pthread__errorfunc(const char *file, int line, const char *function,
_exit(1);
}
}
+
+#ifndef PTHREAD_SA
+
+#define OOPS(msg) \
+ pthread__errorfunc(__FILE__, __LINE__, __FUNCTION__, msg)
+
+int
+pthread__park(pthread_t self, pthread_spin_t *lock,
+ void *obj, struct pthread_queue_t *queue,
+ const struct timespec *abstime, int tail)
+{
+ int rv;
+
+ SDPRINTF(("(pthread__park %p) obj %p enter\n", self, obj));
+
+ if (queue != NULL) {
+ if (tail)
+ PTQ_INSERT_TAIL(queue, self, pt_sleep);
+ else
+ PTQ_INSERT_HEAD(queue, self, pt_sleep);
+ }
+ self->pt_sleepobj = obj;
+
+ do {
+ pthread_spinunlock(self, lock);
+
+ if ((rv = _lwp_park((const void *)abstime, NULL)) != 0)
+ rv = errno;
+ else
+ rv = 0;
+
+ switch (rv) {
+ case 0:
+ case EINTR:
+ case ETIMEDOUT:
+ case EALREADY:
+ break;
+ default:
+ OOPS("_lwp_park failed");
+ SDPRINTF(("(pthread__park %p) syscall rv=%d\n",
+ self, rv));
+ break;
+ }
+
+ pthread_spinlock(self, lock);
+ } while (self->pt_sleepobj != NULL && rv != ETIMEDOUT);
+
+ if (rv == ETIMEDOUT && queue != NULL && self->pt_sleepobj != NULL) {
+ PTQ_REMOVE(queue, self, pt_sleep);
+ self->pt_sleepobj = NULL;
+ }
+
+ SDPRINTF(("(pthread__park %p) obj %p exit\n", self, obj));
+
+ return rv;
+}
+
+void
+pthread__unpark(pthread_t self, pthread_spin_t *lock, void *obj,
+ pthread_t target)
+{
+ int rv;
+
+ if (target != NULL) {
+ SDPRINTF(("(pthread__unpark %p) obj %p target %p\n", self, obj,
+ target));
+
+ target->pt_sleepobj = NULL;
+ pthread_spinunlock(self, lock);
+ rv = _lwp_unpark(target->pt_lid);
+
+ if (rv != 0 && errno != EALREADY && errno != EINTR) {
+ SDPRINTF(("(pthread__unpark %p) syscall rv=%d\n",
+ self, rv));
+ OOPS("_lwp_unpark failed");
+ }
+ } else
+ pthread_spinunlock(self, lock);
+}
+
+void
+pthread__unpark_all(pthread_t self, pthread_spin_t *lock, void *obj,
+ struct pthread_queue_t *queue)
+{
+ pthread_t thread;
+ lwpid_t waiters[32]; /* XXXLWP get value from kernel */
+ int nwaiters, rv;
+
+ for (;;) {
+ nwaiters = 0;
+ while (nwaiters < sizeof(waiters) / sizeof(waiters[0]) &&
+ (thread = PTQ_FIRST(queue)) != NULL) {
+ PTQ_REMOVE(queue, thread, pt_sleep);
+ thread->pt_sleepobj = NULL;
+ waiters[nwaiters++] = thread->pt_lid;
+ SDPRINTF(("(pthread__unpark_all %p) obj %p "
+ "unpark %p\n", self, obj, thread));
+ }
+ pthread_spinunlock(self, lock);
+ switch (nwaiters) {
+ case 0:
+ return;
+ case 1:
+ rv = _lwp_unpark(waiters[0]);
+ if (rv != 0 && errno != EALREADY && errno != EINTR) {
+ OOPS("_lwp_unpark failed");
+ SDPRINTF(("(pthread__unpark_all %p) "
+ "syscall rv=%d\n", self, rv));
+ }
+ return;
+ default:
+ rv = _lwp_unpark_all(waiters, nwaiters);
+ if (rv != 0 && errno != EINTR) {
+ OOPS("_lwp_unpark_all failed");
+ SDPRINTF(("(pthread__unpark_all %p) "
+ "syscall rv=%d\n", self, rv));
+ }
+ break;
+ }
+ if (PTQ_EMPTY(queue))
+ return;
+ pthread_spinlock(self, lock);
+ }
+}
+
+#undef OOPS
+
+#endif /* !PTHREAD_SA */
diff --git a/lib/libpthread/pthread_alarms.c b/lib/libpthread/pthread_alarms.c
index 3f9fda222ae..bdff7861211 100644
--- a/lib/libpthread/pthread_alarms.c
+++ b/lib/libpthread/pthread_alarms.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pthread_alarms.c,v 1.13 2006/03/19 23:01:03 christos Exp $ */
+/* $NetBSD: pthread_alarms.c,v 1.14 2006/12/23 05:14:46 ad Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -36,8 +36,10 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
+#ifdef PTHREAD_SA
+
#include <sys/cdefs.h>
-__RCSID("$NetBSD: pthread_alarms.c,v 1.13 2006/03/19 23:01:03 christos Exp $");
+__RCSID("$NetBSD: pthread_alarms.c,v 1.14 2006/12/23 05:14:46 ad Exp $");
#include <err.h>
#include <sys/time.h>
@@ -227,3 +229,5 @@ pthread__alarm_process(pthread_t self, void *arg)
}
SDPRINTF(("(pro %p) done\n", self, iterator));
}
+
+#endif
diff --git a/lib/libpthread/pthread_barrier.c b/lib/libpthread/pthread_barrier.c
index ac1aa4baeb9..8f9fbe80434 100644
--- a/lib/libpthread/pthread_barrier.c
+++ b/lib/libpthread/pthread_barrier.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pthread_barrier.c,v 1.6 2003/03/08 08:03:35 lukem Exp $ */
+/* $NetBSD: pthread_barrier.c,v 1.7 2006/12/23 05:14:46 ad Exp $ */
/*-
* Copyright (c) 2001, 2003 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: pthread_barrier.c,v 1.6 2003/03/08 08:03:35 lukem Exp $");
+__RCSID("$NetBSD: pthread_barrier.c,v 1.7 2006/12/23 05:14:46 ad Exp $");
#include <errno.h>
#include <sys/cdefs.h>
@@ -174,10 +174,14 @@ pthread_barrier_wait(pthread_barrier_t *barrier)
barrier->ptb_curcount = 0;
barrier->ptb_generation++;
+#ifdef PTHREAD_SA
pthread__sched_sleepers(self, &blockedq);
pthread_spinunlock(self, &barrier->ptb_lock);
-
+#else
+ pthread__unpark_all(self, &barrier->ptb_lock, barrier,
+ &blockedq);
+#endif
return PTHREAD_BARRIER_SERIAL_THREAD;
}
@@ -187,22 +191,27 @@ pthread_barrier_wait(pthread_barrier_t *barrier)
SDPRINTF(("(barrier wait %p) Waiting on %p\n",
self, barrier));
+#ifdef PTHREAD_SA
pthread_spinlock(self, &self->pt_statelock);
self->pt_state = PT_STATE_BLOCKED_QUEUE;
self->pt_sleepobj = barrier;
self->pt_sleepq = &barrier->ptb_waiters;
self->pt_sleeplock = &barrier->ptb_lock;
-
+
pthread_spinunlock(self, &self->pt_statelock);
PTQ_INSERT_TAIL(&barrier->ptb_waiters, self, pt_sleep);
pthread__block(self, &barrier->ptb_lock);
- SDPRINTF(("(barrier wait %p) Woke up on %p\n",
- self, barrier));
/* Spinlock is unlocked on return */
pthread_spinlock(self, &barrier->ptb_lock);
+#else /* PTHREAD_SA */
+ (void)pthread__park(self, &barrier->ptb_lock, barrier,
+ &barrier->ptb_waiters, NULL, 1);
+#endif /* PTHREAD_SA */
+ SDPRINTF(("(barrier wait %p) Woke up on %p\n",
+ self, barrier));
}
pthread_spinunlock(self, &barrier->ptb_lock);
diff --git a/lib/libpthread/pthread_cond.c b/lib/libpthread/pthread_cond.c
index 2686bdf9f85..89216c8317a 100644
--- a/lib/libpthread/pthread_cond.c
+++ b/lib/libpthread/pthread_cond.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pthread_cond.c,v 1.18 2005/01/06 17:33:36 mycroft Exp $ */
+/* $NetBSD: pthread_cond.c,v 1.19 2006/12/23 05:14:46 ad Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: pthread_cond.c,v 1.18 2005/01/06 17:33:36 mycroft Exp $");
+__RCSID("$NetBSD: pthread_cond.c,v 1.19 2006/12/23 05:14:46 ad Exp $");
#include <errno.h>
#include <sys/time.h>
@@ -56,7 +56,9 @@ int _sys_nanosleep(const struct timespec *, struct timespec *);
extern int pthread__started;
+#ifdef PTHREAD_SA
static void pthread_cond_wait__callback(void *);
+#endif
static int pthread_cond_wait_nothread(pthread_t, pthread_mutex_t *,
const struct timespec *);
@@ -134,8 +136,10 @@ pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
"Multiple mutexes used for condition wait",
cond->ptc_mutex == mutex);
#endif
- self->pt_state = PT_STATE_BLOCKED_QUEUE;
+
+#ifdef PTHREAD_SA
self->pt_sleepobj = cond;
+ self->pt_state = PT_STATE_BLOCKED_QUEUE;
self->pt_sleepq = &cond->ptc_waiters;
self->pt_sleeplock = &cond->ptc_lock;
pthread_spinunlock(self, &self->pt_statelock);
@@ -144,6 +148,14 @@ pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
pthread__block(self, &cond->ptc_lock);
/* Spinlock is unlocked on return */
+#else /* PTHREAD_SA */
+ pthread_mutex_unlock(mutex);
+ pthread_spinunlock(self, &self->pt_statelock);
+ (void)pthread__park(self, &cond->ptc_lock, cond,
+ &cond->ptc_waiters, NULL, 0);
+ pthread_spinunlock(self, &cond->ptc_lock);
+#endif /* PTHREAD_SA */
+
pthread_mutex_lock(mutex);
#ifdef ERRORCHECK
pthread_spinlock(self, &cond->ptc_lock);
@@ -172,7 +184,9 @@ pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
{
pthread_t self;
struct pthread_cond__waitarg wait;
+#ifdef PTHREAD_SA
struct pt_alarm_t alarm;
+#endif
int retval;
pthread__error(EINVAL, "Invalid condition variable",
@@ -213,7 +227,8 @@ pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
"Multiple mutexes used for condition wait",
cond->ptc_mutex == mutex);
#endif
-
+
+#ifdef PTHREAD_SA
pthread__alarm_add(self, &alarm, abstime, pthread_cond_wait__callback,
&wait);
self->pt_state = PT_STATE_BLOCKED_QUEUE;
@@ -227,11 +242,18 @@ pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
pthread__block(self, &cond->ptc_lock);
/* Spinlock is unlocked on return */
- SDPRINTF(("(cond timed wait %p) Woke up on %p, mutex %p\n",
- self, cond));
pthread__alarm_del(self, &alarm);
if (pthread__alarm_fired(&alarm))
retval = ETIMEDOUT;
+#else /* PTHREAD_SA */
+ pthread_spinunlock(self, &self->pt_statelock);
+ retval = pthread__park(self, &cond->ptc_lock, cond,
+ &cond->ptc_waiters, abstime, 0);
+ pthread_spinunlock(self, &cond->ptc_lock);
+#endif /* PTHREAD_SA */
+
+ SDPRINTF(("(cond timed wait %p) Woke up on %p, mutex %p\n",
+ self, cond));
SDPRINTF(("(cond timed wait %p) %s\n",
self, (retval == ETIMEDOUT) ? "(timed out)" : ""));
pthread_mutex_lock(mutex);
@@ -247,6 +269,7 @@ pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
return retval;
}
+#ifdef PTHREAD_SA
static void
pthread_cond_wait__callback(void *arg)
{
@@ -273,6 +296,7 @@ pthread_cond_wait__callback(void *arg)
}
pthread_spinunlock(self, &a->ptw_cond->ptc_lock);
}
+#endif /* PTHREAD_SA */
int
pthread_cond_signal(pthread_cond_t *cond)
@@ -292,14 +316,20 @@ pthread_cond_signal(pthread_cond_t *cond)
signaled = PTQ_FIRST(&cond->ptc_waiters);
if (signaled != NULL) {
PTQ_REMOVE(&cond->ptc_waiters, signaled, pt_sleep);
+#ifdef PTHREAD_SA
pthread__sched(self, signaled);
+#endif /* PTHREAD_SA */
PTHREADD_ADD(PTHREADD_COND_WOKEUP);
}
#ifdef ERRORCHECK
if (PTQ_EMPTY(&cond->ptc_waiters))
cond->ptc_mutex = NULL;
#endif
+#ifdef PTHREAD_SA
pthread_spinunlock(self, &cond->ptc_lock);
+#else /* PTHREAD_SA */
+ pthread__unpark(self, &cond->ptc_lock, cond, signaled);
+#endif /* !PTHREAD_SA */
}
return 0;
@@ -326,9 +356,14 @@ pthread_cond_broadcast(pthread_cond_t *cond)
#ifdef ERRORCHECK
cond->ptc_mutex = NULL;
#endif
+#ifdef PTHREAD_SA
pthread__sched_sleepers(self, &blockedq);
PTHREADD_ADD(PTHREADD_COND_WOKEUP);
pthread_spinunlock(self, &cond->ptc_lock);
+#else /* PTHREAD_SA */
+ pthread__unpark_all(self, &cond->ptc_lock, cond, &blockedq);
+ PTHREADD_ADD(PTHREADD_COND_WOKEUP);
+#endif /* PTHREAD_SA */
}
return 0;
diff --git a/lib/libpthread/pthread_debug.c b/lib/libpthread/pthread_debug.c
index 31bfe5df8b5..7e4961281d9 100644
--- a/lib/libpthread/pthread_debug.c
+++ b/lib/libpthread/pthread_debug.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pthread_debug.c,v 1.9 2006/12/14 20:40:57 ad Exp $ */
+/* $NetBSD: pthread_debug.c,v 1.10 2006/12/23 05:14:47 ad Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: pthread_debug.c,v 1.9 2006/12/14 20:40:57 ad Exp $");
+__RCSID("$NetBSD: pthread_debug.c,v 1.10 2006/12/23 05:14:47 ad Exp $");
#include <err.h>
#include <errno.h>
@@ -75,7 +75,7 @@ extern int pthread__maxconcurrency, pthread__started;
void pthread__debug_init(int ncpu)
{
time_t t;
- int i;
+ int i, nbuf;
if (getenv("PTHREAD_DEBUGCOUNTERS") != NULL)
atexit(pthread__debug_printcounters);
@@ -83,6 +83,11 @@ void pthread__debug_init(int ncpu)
if (getenv("PTHREAD_DEBUGLOG") != NULL) {
t = time(NULL);
debugbuf = pthread__debuglog_init(0);
+#ifdef PTHREAD_SA
+ nbuf = ncpu;
+#else
+ nbuf = 1000; /* XXXLWP */
+#endif
linebuf = (struct linebuf *)
malloc(ncpu * sizeof(struct linebuf));
if (linebuf == NULL)
@@ -161,10 +166,14 @@ pthread__debuglog_printf(const char *fmt, ...)
if (debugbuf == NULL || linebuf == NULL)
return;
+#ifdef PTHREAD_SA
if (pthread__maxconcurrency > 1) {
vpid = pthread_self()->pt_vpid;
} else
vpid = 0;
+#else
+ vpid = (int)_lwp_self();
+#endif
tmpbuf = linebuf[vpid].buf;
len = linebuf[vpid].len;
@@ -233,10 +242,14 @@ pthread__debuglog_newline(void)
if (debugbuf == NULL)
return 1;
+#ifdef PTHREAD_SA
if (pthread__maxconcurrency > 1)
vpid = pthread_self()->pt_vpid;
else
vpid = 0;
+#else
+ vpid = (int)_lwp_self();
+#endif
return (linebuf[vpid].len == 0);
}
diff --git a/lib/libpthread/pthread_int.h b/lib/libpthread/pthread_int.h
index a990cb948c1..d0a6e276055 100644
--- a/lib/libpthread/pthread_int.h
+++ b/lib/libpthread/pthread_int.h
@@ -1,4 +1,4 @@
-/* $NetBSD: pthread_int.h,v 1.34 2006/10/03 09:37:07 yamt Exp $ */
+/* $NetBSD: pthread_int.h,v 1.35 2006/12/23 05:14:47 ad Exp $ */
/*-
* Copyright (c) 2001,2002,2003 The NetBSD Foundation, Inc.
@@ -47,6 +47,10 @@
#include "pthread_debug.h"
#include "pthread_md.h"
+#ifndef PTHREAD_SA
+#include <lwp.h>
+#endif
+
#include <sa.h>
#include <signal.h>
@@ -84,7 +88,11 @@ struct __pthread_st {
/* Identifier, for debugging and for preventing recycling. */
int pt_num;
+#ifdef PTHREAD_SA
int pt_type; /* normal, upcall, or idle */
+#else
+ lwpid_t pt_lid; /* LWP ID */
+#endif
int pt_state; /* running, blocked, etc. */
pthread_spin_t pt_statelock; /* lock on pt_state */
int pt_flags; /* see PT_FLAG_* below */
@@ -104,7 +112,11 @@ struct __pthread_st {
PTQ_ENTRY(__pthread_st) pt_allq;
/* Entry on the sleep queue (xxx should be same as run queue?) */
PTQ_ENTRY(__pthread_st) pt_sleep;
- /* Object we're sleeping on */
+ /*
+ * Object we're sleeping on. For 1:1 threads (!SA), this is
+ * protected by the interlock on the object that the thread is
+ * sleeping on.
+ */
void *pt_sleepobj;
/* Queue we're sleeping on */
struct pthread_queue_t *pt_sleepq;
@@ -180,6 +192,8 @@ struct pthread_lock_ops {
void (*plo_unlock)(__cpu_simple_lock_t *);
};
+#ifdef PTHREAD_SA
+
/* Thread types */
#define PT_THREAD_NORMAL 1
#define PT_THREAD_UPCALL 2
@@ -194,6 +208,15 @@ struct pthread_lock_ops {
#define PT_STATE_DEAD 6
#define PT_STATE_SUSPENDED 7
+#else /* PTHREAD_SA */
+
+/* Thread states */
+#define PT_STATE_RUNNING 1
+#define PT_STATE_ZOMBIE 5
+#define PT_STATE_DEAD 6
+
+#endif /* PTHREAD_SA */
+
/* Flag values */
#define PT_FLAG_DETACHED 0x0001
@@ -271,6 +294,16 @@ void pthread__idle(void);
/* Get the next thread */
pthread_t pthread__next(pthread_t self);
+#ifndef PTHREAD_SA
+void pthread__unpark_all(pthread_t self, pthread_spin_t *lock,
+ void *obj, struct pthread_queue_t *threadq);
+void pthread__unpark(pthread_t self, pthread_spin_t *lock,
+ void *obj, pthread_t target);
+int pthread__park(pthread_t self, pthread_spin_t *lock,
+ void *obj, struct pthread_queue_t *threadq,
+ const struct timespec *abs_timeout, int tail);
+#endif
+
int pthread__stackalloc(pthread_t *t);
void pthread__initmain(pthread_t *t);
diff --git a/lib/libpthread/pthread_lock.c b/lib/libpthread/pthread_lock.c
index c532c10cf65..0705c717855 100644
--- a/lib/libpthread/pthread_lock.c
+++ b/lib/libpthread/pthread_lock.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pthread_lock.c,v 1.14 2005/03/17 17:23:21 jwise Exp $ */
+/* $NetBSD: pthread_lock.c,v 1.15 2006/12/23 05:14:47 ad Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: pthread_lock.c,v 1.14 2005/03/17 17:23:21 jwise Exp $");
+__RCSID("$NetBSD: pthread_lock.c,v 1.15 2006/12/23 05:14:47 ad Exp $");
#include <sys/types.h>
#include <sys/lock.h>
@@ -190,11 +190,16 @@ pthread_spinlock(pthread_t thread, pthread_spin_t *lock)
* (in case (a), we should let the code finish and
* we will bail out in pthread_spinunlock()).
*/
+#ifdef PTHREAD_SA
if (thread->pt_next != NULL) {
PTHREADD_ADD(PTHREADD_SPINPREEMPT);
pthread__assert(thread->pt_blockgen == thread->pt_unblockgen);
pthread__switch(thread, thread->pt_next);
}
+#else
+ /* XXXLWP */
+ sched_yield();
+#endif
/* try again */
count = nspins;
SDPRINTF(("(pthread_spinlock %p) incrementing spinlock from %d\n",
@@ -217,7 +222,8 @@ pthread_spintrylock(pthread_t thread, pthread_spin_t *lock)
++thread->pt_spinlocks;
ret = pthread__simple_lock_try(lock);
-
+
+#ifdef PTHREAD_SA
if (ret == 0) {
SDPRINTF(("(pthread_spintrylock %p) decrementing spinlock from %d\n",
thread, thread->pt_spinlocks));
@@ -229,6 +235,7 @@ pthread_spintrylock(pthread_t thread, pthread_spin_t *lock)
pthread__switch(thread, thread->pt_next);
}
}
+#endif
return ret;
}
@@ -247,6 +254,7 @@ pthread_spinunlock(pthread_t thread, pthread_spin_t *lock)
#endif
PTHREADD_ADD(PTHREADD_SPINUNLOCKS);
+#ifdef PTHREAD_SA
/*
* If we were preempted while holding a spinlock, the
* scheduler will notice this and continue us. To be good
@@ -260,6 +268,7 @@ pthread_spinunlock(pthread_t thread, pthread_spin_t *lock)
/* pthread__assert(thread->pt_blockgen == thread->pt_unblockgen); */
pthread__switch(thread, thread->pt_next);
}
+#endif
}
diff --git a/lib/libpthread/pthread_mutex.c b/lib/libpthread/pthread_mutex.c
index c4436cab604..8c013369108 100644
--- a/lib/libpthread/pthread_mutex.c
+++ b/lib/libpthread/pthread_mutex.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pthread_mutex.c,v 1.22 2006/08/22 21:46:09 wrstuden Exp $ */
+/* $NetBSD: pthread_mutex.c,v 1.23 2006/12/23 05:14:47 ad Exp $ */
/*-
* Copyright (c) 2001, 2003 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: pthread_mutex.c,v 1.22 2006/08/22 21:46:09 wrstuden Exp $");
+__RCSID("$NetBSD: pthread_mutex.c,v 1.23 2006/12/23 05:14:47 ad Exp $");
#include <errno.h>
#include <limits.h>
@@ -267,6 +267,7 @@ pthread_mutex_lock_slow(pthread_mutex_t *mutex)
* but it's okay since we're just going to
* retry.
*/
+#ifdef PTHREAD_SA
pthread_spinlock(self, &self->pt_statelock);
self->pt_state = PT_STATE_BLOCKED_QUEUE;
self->pt_sleepobj = mutex;
@@ -276,6 +277,11 @@ pthread_mutex_lock_slow(pthread_mutex_t *mutex)
pthread__block(self, &mutex->ptm_interlock);
/* interlock is not held when we return */
+#else /* PTHREAD_SA */
+ (void)pthread__park(self, &mutex->ptm_interlock,
+ mutex, NULL, NULL, 0);
+ pthread_spinunlock(self, &mutex->ptm_interlock);
+#endif /* PTHREAD_SA */
} else {
PTQ_REMOVE(&mutex->ptm_blocked, self, pt_sleep);
pthread_spinunlock(self, &mutex->ptm_interlock);
@@ -380,16 +386,19 @@ pthread_mutex_unlock(pthread_mutex_t *mutex)
* waiter will loop and see that the mutex is still locked.
*/
pthread_spinlock(self, &mutex->ptm_interlock);
- if (!PTQ_EMPTY(&mutex->ptm_blocked)) {
- blocked = PTQ_FIRST(&mutex->ptm_blocked);
- if (blocked) {
- PTQ_REMOVE(&mutex->ptm_blocked, blocked, pt_sleep);
- PTHREADD_ADD(PTHREADD_MUTEX_UNLOCK_UNBLOCK);
- /* Give the head of the blocked queue another try. */
- pthread__sched(self, blocked);
- }
- }
- pthread_spinunlock(self, &mutex->ptm_interlock);
+ if ((blocked = PTQ_FIRST(&mutex->ptm_blocked)) != NULL) {
+ PTQ_REMOVE(&mutex->ptm_blocked, blocked, pt_sleep);
+ PTHREADD_ADD(PTHREADD_MUTEX_UNLOCK_UNBLOCK);
+#ifdef PTHREAD_SA
+ /* Give the head of the blocked queue another try. */
+ pthread__sched(self, blocked);
+ pthread_spinunlock(self, &mutex->ptm_interlock);
+#else /* PTHREAD_SA */
+ pthread__unpark(self, &mutex->ptm_interlock, mutex, blocked);
+#endif /* PTHREAD_SA */
+ } else
+ pthread_spinunlock(self, &mutex->ptm_interlock);
+
return 0;
}
diff --git a/lib/libpthread/pthread_run.c b/lib/libpthread/pthread_run.c
index 8c43fdcb106..6eca746b94d 100644
--- a/lib/libpthread/pthread_run.c
+++ b/lib/libpthread/pthread_run.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pthread_run.c,v 1.18 2005/01/06 17:40:22 mycroft Exp $ */
+/* $NetBSD: pthread_run.c,v 1.19 2006/12/23 05:14:47 ad Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: pthread_run.c,v 1.18 2005/01/06 17:40:22 mycroft Exp $");
+__RCSID("$NetBSD: pthread_run.c,v 1.19 2006/12/23 05:14:47 ad Exp $");
#include <ucontext.h>
#include <errno.h>
@@ -51,6 +51,8 @@ __RCSID("$NetBSD: pthread_run.c,v 1.18 2005/01/06 17:40:22 mycroft Exp $");
#define SDPRINTF(x)
#endif
+#ifdef PTHREAD_SA
+
extern pthread_spin_t pthread__runqueue_lock;
extern struct pthread_queue_t pthread__runqueue;
extern struct pthread_queue_t pthread__idlequeue;
@@ -299,6 +301,20 @@ pthread__sched_bulk(pthread_t self, pthread_t qhead)
pthread_spinunlock(self, &pthread__runqueue_lock);
}
+#else /* PTHREAD_SA */
+
+#include <unistd.h> /* XXXLWP */
+
+int
+sched_yield(void)
+{
+
+ /* XXXLWP */
+ (void)usleep(1);
+ return 0;
+}
+
+#endif /* PTHREAD_SA */
/*ARGSUSED*/
int
diff --git a/lib/libpthread/pthread_rwlock.c b/lib/libpthread/pthread_rwlock.c
index d0d5904d90c..0bb156c5005 100644
--- a/lib/libpthread/pthread_rwlock.c
+++ b/lib/libpthread/pthread_rwlock.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pthread_rwlock.c,v 1.13 2005/10/19 02:15:03 chs Exp $ */
+/* $NetBSD: pthread_rwlock.c,v 1.14 2006/12/23 05:14:47 ad Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
@@ -37,14 +37,16 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: pthread_rwlock.c,v 1.13 2005/10/19 02:15:03 chs Exp $");
+__RCSID("$NetBSD: pthread_rwlock.c,v 1.14 2006/12/23 05:14:47 ad Exp $");
#include <errno.h>
#include "pthread.h"
#include "pthread_int.h"
+#ifdef PTHREAD_SA
static void pthread_rwlock__callback(void *);
+#endif
__strong_alias(__libc_rwlock_init,pthread_rwlock_init)
__strong_alias(__libc_rwlock_rdlock,pthread_rwlock_rdlock)
@@ -116,6 +118,7 @@ pthread_rwlock_rdlock(pthread_rwlock_t *rwlock)
*/
while ((rwlock->ptr_writer != NULL) ||
(!PTQ_EMPTY(&rwlock->ptr_wblocked))) {
+#ifdef PTHREAD_SA
PTQ_INSERT_TAIL(&rwlock->ptr_rblocked, self, pt_sleep);
/* Locking a rwlock is not a cancellation point; don't check */
pthread_spinlock(self, &self->pt_statelock);
@@ -127,6 +130,10 @@ pthread_rwlock_rdlock(pthread_rwlock_t *rwlock)
pthread__block(self, &rwlock->ptr_interlock);
/* interlock is not held when we return */
pthread_spinlock(self, &rwlock->ptr_interlock);
+#else /* PTHREAD_SA */
+ (void)pthread__park(self, &rwlock->ptr_interlock, rwlock,
+ &rwlock->ptr_rblocked, NULL, 1);
+#endif /* PTHREAD_SA */
}
rwlock->ptr_nreaders++;
@@ -195,6 +202,7 @@ pthread_rwlock_wrlock(pthread_rwlock_t *rwlock)
return EDEADLK;
}
#endif
+#ifdef PTHREAD_SA
PTQ_INSERT_TAIL(&rwlock->ptr_wblocked, self, pt_sleep);
/* Locking a rwlock is not a cancellation point; don't check */
pthread_spinlock(self, &self->pt_statelock);
@@ -206,6 +214,10 @@ pthread_rwlock_wrlock(pthread_rwlock_t *rwlock)
pthread__block(self, &rwlock->ptr_interlock);
/* interlock is not held when we return */
pthread_spinlock(self, &rwlock->ptr_interlock);
+#else
+ (void)pthread__park(self, &rwlock->ptr_interlock, rwlock,
+ &rwlock->ptr_wblocked, NULL, 1);
+#endif
}
rwlock->ptr_writer = self;
@@ -253,8 +265,10 @@ pthread_rwlock_timedrdlock(pthread_rwlock_t *rwlock,
const struct timespec *abs_timeout)
{
pthread_t self;
+#ifdef PTHREAD_SA
struct pthread_rwlock__waitarg wait;
struct pt_alarm_t alarm;
+#endif
int retval;
#ifdef ERRORCHECK
@@ -284,6 +298,7 @@ pthread_rwlock_timedrdlock(pthread_rwlock_t *rwlock,
retval = 0;
while ((retval == 0) && ((rwlock->ptr_writer != NULL) ||
(!PTQ_EMPTY(&rwlock->ptr_wblocked)))) {
+#ifdef PTHREAD_SA
wait.ptw_thread = self;
wait.ptw_rwlock = rwlock;
wait.ptw_queue = &rwlock->ptr_rblocked;
@@ -303,6 +318,10 @@ pthread_rwlock_timedrdlock(pthread_rwlock_t *rwlock,
if (pthread__alarm_fired(&alarm))
retval = ETIMEDOUT;
pthread_spinlock(self, &rwlock->ptr_interlock);
+#else
+ retval = pthread__park(self, &rwlock->ptr_interlock, rwlock,
+ &rwlock->ptr_rblocked, abs_timeout, 1);
+#endif
}
/* One last chance to get the lock, in case it was released between
@@ -323,8 +342,10 @@ int
pthread_rwlock_timedwrlock(pthread_rwlock_t *rwlock,
const struct timespec *abs_timeout)
{
+#ifdef PTHREAD_SA
struct pthread_rwlock__waitarg wait;
struct pt_alarm_t alarm;
+#endif
pthread_t self;
int retval;
extern int pthread__started;
@@ -361,6 +382,7 @@ pthread_rwlock_timedwrlock(pthread_rwlock_t *rwlock,
return EDEADLK;
}
#endif
+#ifdef PTHREAD_SA
wait.ptw_thread = self;
wait.ptw_rwlock = rwlock;
wait.ptw_queue = &rwlock->ptr_wblocked;
@@ -380,6 +402,10 @@ pthread_rwlock_timedwrlock(pthread_rwlock_t *rwlock,
if (pthread__alarm_fired(&alarm))
retval = ETIMEDOUT;
pthread_spinlock(self, &rwlock->ptr_interlock);
+#else
+ retval = pthread__park(self, &rwlock->ptr_interlock, rwlock,
+ &rwlock->ptr_wblocked, abs_timeout, 1);
+#endif
}
if ((rwlock->ptr_nreaders == 0) && (rwlock->ptr_writer == NULL)) {
@@ -392,6 +418,7 @@ pthread_rwlock_timedwrlock(pthread_rwlock_t *rwlock,
}
+#ifdef PTHREAD_SA
static void
pthread_rwlock__callback(void *arg)
{
@@ -415,6 +442,7 @@ pthread_rwlock__callback(void *arg)
pthread_spinunlock(self, &a->ptw_rwlock->ptr_interlock);
}
+#endif
int
@@ -467,12 +495,20 @@ pthread_rwlock_unlock(pthread_rwlock_t *rwlock)
#endif
}
+#ifdef PTHREAD_SA
if (writer != NULL)
pthread__sched(self, writer);
else
pthread__sched_sleepers(self, &blockedq);
-
+
pthread_spinunlock(self, &rwlock->ptr_interlock);
+#else /* PTHREAD_SA */
+ if (writer != NULL)
+ pthread__unpark(self, &rwlock->ptr_interlock, rwlock, writer);
+ else
+ pthread__unpark_all(self, &rwlock->ptr_interlock, rwlock,
+ &blockedq);
+#endif /* PTHREAD_SA */
return 0;
}
diff --git a/lib/libpthread/pthread_sa.c b/lib/libpthread/pthread_sa.c
index ff23e6e20b0..3aa75451b4d 100644
--- a/lib/libpthread/pthread_sa.c
+++ b/lib/libpthread/pthread_sa.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pthread_sa.c,v 1.37 2005/03/17 17:23:21 jwise Exp $ */
+/* $NetBSD: pthread_sa.c,v 1.38 2006/12/23 05:14:47 ad Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: pthread_sa.c,v 1.37 2005/03/17 17:23:21 jwise Exp $");
+__RCSID("$NetBSD: pthread_sa.c,v 1.38 2006/12/23 05:14:47 ad Exp $");
#include <err.h>
#include <errno.h>
@@ -60,6 +60,8 @@ __RCSID("$NetBSD: pthread_sa.c,v 1.37 2005/03/17 17:23:21 jwise Exp $");
#define SDPRINTF(x)
#endif
+#ifdef PTHREAD_SA
+
#define UC(t) ((t)->pt_trapuc ? (t)->pt_trapuc : (t)->pt_uc)
#define PUC(t) ((t)->pt_trapuc ? 'T':'U') , UC(t)
@@ -827,3 +829,22 @@ pthread__setconcurrency(int concurrency)
SDPRINTF(("(set %p concurrency) now %d\n",
self, pthread__concurrency));
}
+
+
+#else /* PTHREAD_SA */
+
+int
+pthread_getrrtimer_np(void)
+{
+
+ return (100);
+}
+
+int
+pthread_setrrtimer_np(int msec)
+{
+
+ return (EOPNOTSUPP);
+}
+
+#endif /* PTHREAD_SA */
diff --git a/lib/libpthread/pthread_sig.c b/lib/libpthread/pthread_sig.c
index ef8a4708609..825134fdee3 100644
--- a/lib/libpthread/pthread_sig.c
+++ b/lib/libpthread/pthread_sig.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pthread_sig.c,v 1.47 2006/11/24 19:46:58 christos Exp $ */
+/* $NetBSD: pthread_sig.c,v 1.48 2006/12/23 05:14:47 ad Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: pthread_sig.c,v 1.47 2006/11/24 19:46:58 christos Exp $");
+__RCSID("$NetBSD: pthread_sig.c,v 1.48 2006/12/23 05:14:47 ad Exp $");
/* We're interposing a specific version of the signal interface. */
#define __LIBC12_SOURCE__
@@ -67,6 +67,13 @@ __RCSID("$NetBSD: pthread_sig.c,v 1.47 2006/11/24 19:46:58 christos Exp $");
#define SDPRINTF(x)
#endif
+int _sys___sigprocmask14(int, const sigset_t *, sigset_t *);
+
+__strong_alias(__libc_thr_sigsetmask,pthread_sigmask)
+__strong_alias(__sigprocmask14,pthread_sigmask)
+
+#ifdef PTHREAD_SA
+
extern int pthread__started;
extern pthread_spin_t pthread__runqueue_lock;
@@ -112,10 +119,7 @@ pthread__signal_tramp(void (*)(int, siginfo_t *, void *),
static int firstsig(const sigset_t *);
int _sys_execve(const char *, char *const [], char *const []);
-int _sys___sigprocmask14(int, const sigset_t *, sigset_t *);
-__strong_alias(__libc_thr_sigsetmask,pthread_sigmask)
-__strong_alias(__sigprocmask14,pthread_sigmask)
__strong_alias(__exeve,execve)
void
@@ -1096,3 +1100,31 @@ execve(const char *path, char *const argv[], char *const envp[])
return ret;
}
+
+#else /* PTHREAD_SA */
+
+int
+pthread_kill(pthread_t thread, int sig)
+{
+ pthread_t self;
+
+ self = pthread__self();
+
+ SDPRINTF(("(pthread_kill %p) kill %p sig %d\n", self, thread, sig));
+
+ if ((sig < 0) || (sig >= _NSIG))
+ return EINVAL;
+ if (pthread__find(self, thread) != 0)
+ return ESRCH;
+
+ return _lwp_kill(thread->pt_lid, sig);
+}
+
+int
+pthread_sigmask(int how, const sigset_t *set, sigset_t *oset)
+{
+
+ return _sys___sigprocmask14(how, set, oset);
+}
+
+#endif /* PTHREAD_SA */
diff --git a/lib/libpthread/pthread_sleep.c b/lib/libpthread/pthread_sleep.c
index 340af61bb6a..676d8602ab1 100644
--- a/lib/libpthread/pthread_sleep.c
+++ b/lib/libpthread/pthread_sleep.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pthread_sleep.c,v 1.7 2005/04/19 16:38:57 nathanw Exp $ */
+/* $NetBSD: pthread_sleep.c,v 1.8 2006/12/23 05:14:47 ad Exp $ */
/*-
* Copyright (c) 2003 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: pthread_sleep.c,v 1.7 2005/04/19 16:38:57 nathanw Exp $");
+__RCSID("$NetBSD: pthread_sleep.c,v 1.8 2006/12/23 05:14:47 ad Exp $");
#include <errno.h>
#include <limits.h>
@@ -48,6 +48,8 @@ __RCSID("$NetBSD: pthread_sleep.c,v 1.7 2005/04/19 16:38:57 nathanw Exp $");
int _sys_nanosleep(const struct timespec *, struct timespec *);
+#ifdef PTHREAD_SA
+
extern int pthread__started;
/*
@@ -170,4 +172,20 @@ pthread__nanosleep_callback(void *arg)
pthread_spinunlock(self, &pt_nanosleep_lock);
}
+#else /* PTHREAD_SA */
+
+int
+nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
+{
+
+ /*
+ * XXXLWP For now, just nanosleep. In the future, maybe pass
+ * a ucontext_t to _lwp_nanosleep() and allow it to recycle our
+ * kernel stack.
+ */
+ return _sys_nanosleep(rqtp, rmtp);
+}
+
+#endif /* PTHREAD_SA */
+
__strong_alias(_nanosleep, nanosleep)
diff --git a/lib/libpthread/pthread_stack.c b/lib/libpthread/pthread_stack.c
index 6258deae6a9..435fffc1255 100644
--- a/lib/libpthread/pthread_stack.c
+++ b/lib/libpthread/pthread_stack.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pthread_stack.c,v 1.17 2006/02/12 11:41:53 yamt Exp $ */
+/* $NetBSD: pthread_stack.c,v 1.18 2006/12/23 05:14:47 ad Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: pthread_stack.c,v 1.17 2006/02/12 11:41:53 yamt Exp $");
+__RCSID("$NetBSD: pthread_stack.c,v 1.18 2006/12/23 05:14:47 ad Exp $");
#define __EXPOSE_STACK 1
#include <sys/param.h>
@@ -218,6 +218,7 @@ pthread__stackid_setup(void *base, size_t size, pthread_t *tp)
}
+#ifdef PTHREAD_SA
ssize_t
pthread__stackinfo_offset()
{
@@ -231,3 +232,4 @@ pthread__stackinfo_offset()
return (-(2 * pagesize) + offsetof(struct __pthread_st, pt_stackinfo));
#endif
}
+#endif
diff --git a/lib/libpthread/sem.c b/lib/libpthread/sem.c
index 03e2cc92c99..c3cc65823bc 100644
--- a/lib/libpthread/sem.c
+++ b/lib/libpthread/sem.c
@@ -1,4 +1,4 @@
-/* $NetBSD: sem.c,v 1.9 2005/10/19 02:15:03 chs Exp $ */
+/* $NetBSD: sem.c,v 1.10 2006/12/23 05:14:47 ad Exp $ */
/*-
* Copyright (c) 2003 The NetBSD Foundation, Inc.
@@ -66,7 +66,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: sem.c,v 1.9 2005/10/19 02:15:03 chs Exp $");
+__RCSID("$NetBSD: sem.c,v 1.10 2006/12/23 05:14:47 ad Exp $");
#include <sys/types.h>
#include <sys/ksem.h>
@@ -332,9 +332,10 @@ sem_wait(sem_t *sem)
break;
}
+#ifdef PTHREAD_SA
PTQ_INSERT_TAIL(&(*sem)->usem_waiters, self, pt_sleep);
- self->pt_state = PT_STATE_BLOCKED_QUEUE;
self->pt_sleepobj = *sem;
+ self->pt_state = PT_STATE_BLOCKED_QUEUE;
self->pt_sleepq = &(*sem)->usem_waiters;
self->pt_sleeplock = &(*sem)->usem_interlock;
pthread_spinunlock(self, &self->pt_statelock);
@@ -343,6 +344,18 @@ sem_wait(sem_t *sem)
pthread__block(self, &(*sem)->usem_interlock);
/* interlock is not held when we return */
+#else
+ /*
+ * Should be no race against self->pt_cancel here, as the
+ * kernel needs to preserve L_CANCELLED.
+ *
+ * XXXLWP lock soup
+ */
+ pthread_spinunlock(self, &self->pt_statelock);
+ (void)pthread__park(self, &(*sem)->usem_interlock, *sem,
+ &(*sem)->usem_waiters, NULL, 1);
+ pthread_spinunlock(self, &(*sem)->usem_interlock);
+#endif
}
(*sem)->usem_count--;
@@ -424,9 +437,15 @@ sem_post(sem_t *sem)
if (blocked) {
PTQ_REMOVE(&(*sem)->usem_waiters, blocked, pt_sleep);
/* Give the head of the blocked queue another try. */
+#ifdef PTHREAD_SA
pthread__sched(self, blocked);
- }
- pthread_spinunlock(self, &(*sem)->usem_interlock);
+ pthread_spinunlock(self, &(*sem)->usem_interlock);
+#else
+ pthread__unpark(self, &(*sem)->usem_interlock, *sem,
+ blocked);
+#endif
+ } else
+ pthread_spinunlock(self, &(*sem)->usem_interlock);
return (0);
}