diff options
| author | nathanw <nathanw@NetBSD.org> | 2003-01-30 01:04:50 +0000 |
|---|---|---|
| committer | nathanw <nathanw@NetBSD.org> | 2003-01-30 01:04:50 +0000 |
| commit | a8773f45f88d5bf9095c85a8f358fb6d34d6410d (patch) | |
| tree | c6abcc16433f722b89d40bc855c9b380c3c1d243 /lib/libpthread | |
| parent | 7d8ac1f6c284b25e109b7d81bc501b03c31e1378 (diff) | |
Simplify pthread__upcall() a bit by moving lock resolution before the big
switch statement, and moving upcall-type-specific code into that switch.
Beneficial side effect: don't manipulate a statelock before lock resolution
occurs.
Diffstat (limited to 'lib/libpthread')
| -rw-r--r-- | lib/libpthread/pthread_sa.c | 119 |
1 files changed, 57 insertions, 62 deletions
diff --git a/lib/libpthread/pthread_sa.c b/lib/libpthread/pthread_sa.c index 4f906e3a92b..b6010896ef8 100644 --- a/lib/libpthread/pthread_sa.c +++ b/lib/libpthread/pthread_sa.c @@ -1,4 +1,4 @@ -/* $NetBSD: pthread_sa.c,v 1.4 2003/01/25 00:43:38 nathanw Exp $ */ +/* $NetBSD: pthread_sa.c,v 1.5 2003/01/30 01:04:50 nathanw Exp $ */ /*- * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -90,7 +90,6 @@ pthread__upcall(int type, struct sa_t *sas[], int ev, int intr, void *arg) { pthread_t t, self, next, intqueue; int first = 1; - int runalarms = 0; siginfo_t *si; PTHREADD_ADD(PTHREADD_UPCALLS); @@ -100,23 +99,45 @@ pthread__upcall(int type, struct sa_t *sas[], int ev, int intr, void *arg) if (sas[0]->sa_id > pthread__maxlwps) pthread__maxlwps = sas[0]->sa_id; + SDPRINTF(("(up %p) type %d LWP %d ev %d intr %d\n", self, type, sas[0]->sa_id, ev ? sas[1]->sa_id : 0, intr ? sas[ev+intr]->sa_id : 0)); + + if (type == SA_UPCALL_BLOCKED) + first++; /* Don't handle this SA in the usual processing. */ + + /* + * Do per-thread work, including saving the context. + * Briefly run any threads that were in a critical section. + * This includes any upcalls that have been interupted, so + * they can do their own version of this dance. + */ + intqueue = NULL; + if ((ev + intr) >= first) { + if (pthread__find_interrupted(sas + first, ev + intr, + &intqueue, self) > 0) + pthread__resolve_locks(self, &intqueue); + } + + /* We can take spinlocks now */ + pthread__sched_idle2(self); + if (intqueue) + pthread__sched_bulk(self, intqueue); + switch (type) { case SA_UPCALL_BLOCKED: t = pthread__sa_id(sas[1]); pthread_spinlock(self, &t->pt_statelock); t->pt_state = PT_STATE_BLOCKED_SYS; + t->pt_blockedlwp = sas[1]->sa_id; + if (t->pt_cancel) + _lwp_wakeup(t->pt_blockedlwp); pthread_spinunlock(self, &t->pt_statelock); #ifdef PTHREAD__DEBUG t->blocks++; #endif - t->pt_blockedlwp = sas[1]->sa_id; - if (t->pt_cancel) - _lwp_wakeup(t->pt_blockedlwp); t->pt_uc = sas[1]->sa_context; - first++; /* Don't handle this SA in the usual processing. */ PTHREADD_ADD(PTHREADD_UP_BLOCK); break; case SA_UPCALL_NEWPROC: @@ -127,15 +148,44 @@ pthread__upcall(int type, struct sa_t *sas[], int ev, int intr, void *arg) break; case SA_UPCALL_UNBLOCKED: PTHREADD_ADD(PTHREADD_UP_UNBLOCK); + /* + * A signal may have been presented to this thread while + * it was in the kernel. + */ + t = pthread__sa_id(sas[1]); + if (t->pt_flags & PT_FLAG_SIGDEFERRED) + pthread__signal_deferred(self, t); break; case SA_UPCALL_SIGNAL: PTHREADD_ADD(PTHREADD_UP_SIGNAL); + /* + * Note that we handle signals after handling + * spinlock preemption. This is because spinlocks are only + * used internally to the thread library and we don't want to + * expose the middle of them to a signal. While this means + * that synchronous instruction traps that occur inside + * critical sections in this library (SIGFPE, SIGILL, SIGBUS, + * SIGSEGV) won't be handled at the precise location where + * they occured, that's okay, because (1) we don't use any FP + * and (2) SIGILL/SIGBUS/SIGSEGV should really just core dump. + * + * This also means that a thread that was interrupted to take + * a signal will be on a run queue, and not in upcall limbo. + */ + si = arg; + if (ev) + pthread__signal(self, pthread__sa_id(sas[1]), + si->si_signo, si->si_code); + else + pthread__signal(self, NULL, si->si_signo, si->si_code); break; case SA_UPCALL_SIGEV: PTHREADD_ADD(PTHREADD_UP_SIGEV); si = arg; + SDPRINTF(("(up %p) sigev val %x\n", self, + si->si_sigval.sival_int)); if (si->si_sigval.sival_int == PT_ALARMTIMER_MAGIC) - runalarms = 1; + pthread__alarm_process(self, arg); /* * PT_RRTIMER_MAGIC doesn't need explicit handling; * the per-thread work below will put the interrupted @@ -151,61 +201,6 @@ pthread__upcall(int type, struct sa_t *sas[], int ev, int intr, void *arg) } /* - * Do per-thread work, including saving the context. - * Briefly run any threads that were in a critical section. - * This includes any upcalls that have been interupted, so - * they can do their own version of this dance. - */ - intqueue = NULL; - if ((ev + intr) >= first) { - if (pthread__find_interrupted(sas + first, ev + intr, - &intqueue, self) > 0) - pthread__resolve_locks(self, &intqueue); - } - pthread__sched_idle2(self); - if (intqueue) - pthread__sched_bulk(self, intqueue); - - - /* - * Run the alarm queue (handled after lock resolution since - * alarm handling requires locks). - */ - if (runalarms) - pthread__alarm_process(self, arg); - - /* - * Note that we handle signals after handling - * spinlock preemption. This is because spinlocks are only - * used internally to the thread library and we don't want to - * expose the middle of them to a signal. While this means - * that synchronous instruction traps that occur inside - * critical sections in this library (SIGFPE, SIGILL, SIGBUS, - * SIGSEGV) won't be handled at the precise location where - * they occured, that's okay, because (1) we don't use any FP - * and (2) SIGILL/SIGBUS/SIGSEGV should really just core dump. - * - * This also means that a thread that was interrupted to take - * a signal will be on a run queue, and not in upcall limbo. - */ - if (type == SA_UPCALL_SIGNAL) { - si = arg; - if (ev) - pthread__signal(self, pthread__sa_id(sas[1]), - si->si_signo, si->si_code); - else - pthread__signal(self, NULL, si->si_signo, si->si_code); - } else if (type == SA_UPCALL_UNBLOCKED) { - /* - * A signal may have been presented to this thread while - * it was in the kernel. - */ - t = pthread__sa_id(sas[1]); - if (t->pt_flags & PT_FLAG_SIGDEFERRED) - pthread__signal_deferred(self, t); - } - - /* * At this point everything on our list should be scheduled * (or was an upcall). */ |
