summaryrefslogtreecommitdiff
path: root/lib/libpthread
diff options
context:
space:
mode:
authornathanw <nathanw@NetBSD.org>2003-01-30 01:04:50 +0000
committernathanw <nathanw@NetBSD.org>2003-01-30 01:04:50 +0000
commita8773f45f88d5bf9095c85a8f358fb6d34d6410d (patch)
treec6abcc16433f722b89d40bc855c9b380c3c1d243 /lib/libpthread
parent7d8ac1f6c284b25e109b7d81bc501b03c31e1378 (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.c119
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).
*/