diff options
| author | ad <ad@NetBSD.org> | 2006-12-23 05:14:46 +0000 |
|---|---|---|
| committer | ad <ad@NetBSD.org> | 2006-12-23 05:14:46 +0000 |
| commit | 1ac6a89b79760f25efddd665a4dca817272bbfaf (patch) | |
| tree | 16b3f488e238ae2691b2080b7336c138b83ee1b7 /lib/libpthread | |
| parent | 642cea631210394ce02896c04a12450c9ca8825e (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/Makefile | 12 | ||||
| -rw-r--r-- | lib/libpthread/pthread.c | 296 | ||||
| -rw-r--r-- | lib/libpthread/pthread_alarms.c | 8 | ||||
| -rw-r--r-- | lib/libpthread/pthread_barrier.c | 21 | ||||
| -rw-r--r-- | lib/libpthread/pthread_cond.c | 47 | ||||
| -rw-r--r-- | lib/libpthread/pthread_debug.c | 19 | ||||
| -rw-r--r-- | lib/libpthread/pthread_int.h | 37 | ||||
| -rw-r--r-- | lib/libpthread/pthread_lock.c | 15 | ||||
| -rw-r--r-- | lib/libpthread/pthread_mutex.c | 33 | ||||
| -rw-r--r-- | lib/libpthread/pthread_run.c | 20 | ||||
| -rw-r--r-- | lib/libpthread/pthread_rwlock.c | 42 | ||||
| -rw-r--r-- | lib/libpthread/pthread_sa.c | 25 | ||||
| -rw-r--r-- | lib/libpthread/pthread_sig.c | 42 | ||||
| -rw-r--r-- | lib/libpthread/pthread_sleep.c | 22 | ||||
| -rw-r--r-- | lib/libpthread/pthread_stack.c | 6 | ||||
| -rw-r--r-- | lib/libpthread/sem.c | 29 |
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); } |
