Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/lib/libpthread - delay processing unblocked threads until af...
details: https://anonhg.NetBSD.org/src/rev/adde0007dfcd
branches: trunk
changeset: 555449:adde0007dfcd
user: cl <cl%NetBSD.org@localhost>
date: Mon Nov 17 22:59:00 2003 +0000
description:
- delay processing unblocked threads until after locks are resolved:
without the blocked/unblocked upcall ordering, an interrupted blocked
upcall might put the blocked thread on the intqueue because it needs
to be continued. With the delayed processing, we avoid putting such a
thread twice on the runqueue.
- fix putting a thread on the intqueue when it needs to be continued
after it blocked.
Also check return value when returning a single stack.
diffstat:
lib/libpthread/pthread_sa.c | 116 +++++++++++++++++++++++++++++++------------
1 files changed, 84 insertions(+), 32 deletions(-)
diffs (248 lines):
diff -r 996998087127 -r adde0007dfcd lib/libpthread/pthread_sa.c
--- a/lib/libpthread/pthread_sa.c Mon Nov 17 22:57:52 2003 +0000
+++ b/lib/libpthread/pthread_sa.c Mon Nov 17 22:59:00 2003 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pthread_sa.c,v 1.20 2003/11/12 22:21:21 cl Exp $ */
+/* $NetBSD: pthread_sa.c,v 1.21 2003/11/17 22:59:00 cl Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__RCSID("$NetBSD: pthread_sa.c,v 1.20 2003/11/12 22:21:21 cl Exp $");
+__RCSID("$NetBSD: pthread_sa.c,v 1.21 2003/11/17 22:59:00 cl Exp $");
#include <err.h>
#include <errno.h>
@@ -78,8 +78,8 @@
void pthread__upcall(int type, struct sa_t *sas[], int ev, int intr,
void *arg);
-void pthread__find_interrupted(struct sa_t *sas[], int nsas, pthread_t *qhead,
- pthread_t *schedqhead, pthread_t self);
+void pthread__find_interrupted(int type, struct sa_t *sas[], int ev, int intr,
+ pthread_t *qhead, pthread_t *schedqhead, pthread_t self);
void pthread__resolve_locks(pthread_t self, pthread_t *interrupted);
void pthread__recycle_bulk(pthread_t self, pthread_t qhead);
@@ -108,23 +108,32 @@
/* Don't handle this SA in the usual processing. */
t = pthread__sa_id(sas[1]);
pthread__assert(self->pt_spinlocks == 0);
- if ((t->pt_spinlocks > 0) || (t->pt_next)) {
- SDPRINTF(("(up %p) unblocking %p "
- "(uc: T %p pc: %lx sp: %lx) "
+ if (t->pt_spinlocks > 0 || t->pt_next ||
+ t->pt_type == PT_THREAD_UPCALL ||
+ t->pt_blockedlwp == -1) {
+ if (t->pt_blockedlwp != -1) {
+ SDPRINTF(("(up %p) unblocking %p "
+ "(uc: T %p pc: %lx sp: %lx) "
+ "spinlocks: %d, pt_next: %p\n",
+ self, t, sas[1]->sa_context,
+ pthread__uc_pc(sas[1]->sa_context),
+ pthread__uc_sp(sas[1]->sa_context),
+ t->pt_spinlocks, t->pt_next));
+ if (sa_unblockyield(sas[1]->sa_id, &self->pt_next,
+ &self->pt_stack) != 0)
+ pthread__abort();
+ /* maybe NOTREACHED */
+ }
+ pthread__assert(t->pt_blockedlwp == -1);
+ t->pt_blockedlwp = 0;
+ SDPRINTF(("(up %p) unblocking switchto to %p(%d) "
+ "(uc: T %p pc: %lx) chain %p "
"spinlocks: %d, pt_next: %p\n",
- self, t, sas[1]->sa_context,
+ self, t, t->pt_type, sas[1]->sa_context,
pthread__uc_pc(sas[1]->sa_context),
- pthread__uc_sp(sas[1]->sa_context),
- t->pt_spinlocks, t->pt_next));
- if (sa_unblockyield(sas[1]->sa_id, &self->pt_next,
- &self->pt_stack) != 0)
- pthread__abort();
- SDPRINTF(("(up %p) unblocking switchto to %p "
- "(uc: T %p pc: %lx) chain %p\n",
- self, t, sas[1]->sa_context,
- pthread__uc_pc(sas[1]->sa_context),
- self->pt_next));
- self->pt_switchtouc = sas[1]->sa_context;
+ self->pt_next, t->pt_spinlocks,
+ t->pt_next));
+ self->pt_switchtouc = t->pt_trapuc;
self->pt_switchto = t;
pthread__switch(self, self->pt_next);
/*NOTREACHED*/
@@ -137,6 +146,7 @@
if (sa_unblockyield(sas[1]->sa_id, NULL,
&self->pt_stack) != 0)
pthread__abort();
+ t->pt_blockedlwp = 0;
/* XXX need flaglock? */
if ((t->pt_flags & PT_FLAG_IDLED) == 0)
pthread__sched_bulk(self, t);
@@ -148,7 +158,7 @@
* This includes any upcalls that have been interupted, so
* they can do their own version of this dance.
*/
- pthread__find_interrupted(sas + 1, ev + intr,
+ pthread__find_interrupted(type, sas, ev, intr,
&intqueue, &schedqueue, self);
if (intqueue != self)
pthread__resolve_locks(self, &intqueue);
@@ -177,7 +187,13 @@
#ifdef PTHREAD__DEBUG
t->blocks++;
#endif
- t->pt_trapuc = sas[1]->sa_context;
+ /*
+ * Because we might be preempted between the check and
+ * the set, we set the unblocked thread trapuc again
+ * below in the SA_UPCALL_UNBLOCKED case.
+ */
+ if (t->pt_trapuc == NULL)
+ t->pt_trapuc = sas[1]->sa_context;
SDPRINTF(("(up %p) blocker %d %p(%d)\n", self, 1, t,
t->pt_type));
break;
@@ -189,8 +205,16 @@
break;
case SA_UPCALL_UNBLOCKED:
PTHREADD_ADD(PTHREADD_UP_UNBLOCK);
+ schedqueue = NULL;
for (i = 0; i < ev; i++) {
t = pthread__sa_id(sas[1 + i]);
+ if (t->pt_blockedlwp != 0) {
+ /* Set unblocked thread trapuc again. */
+ t->pt_trapuc = sas[1 + i]->sa_context;
+ t->pt_next = schedqueue;
+ schedqueue = t;
+ t->pt_blockedlwp = 0;
+ }
/*
* A signal may have been presented to this
* thread while it was in the kernel.
@@ -201,6 +225,8 @@
if (flags & PT_FLAG_SIGDEFERRED)
pthread__signal_deferred(self, t);
}
+ if (schedqueue != NULL)
+ pthread__sched_bulk(self, schedqueue);
break;
case SA_UPCALL_SIGNAL:
PTHREADD_ADD(PTHREADD_UP_SIGNAL);
@@ -264,24 +290,32 @@
* need to be continued early.
*/
void
-pthread__find_interrupted(struct sa_t *sas[], int nsas, pthread_t *intqhead,
- pthread_t *schedqhead, pthread_t self)
+pthread__find_interrupted(int type, struct sa_t *sas[], int ev, int intr,
+ pthread_t *intqhead, pthread_t *schedqhead, pthread_t self)
{
int i, resume;
pthread_t victim, nextint, nextsched;
nextint = nextsched = self;
- for (i = 0; i < nsas; i++) {
+ for (i = 0; i < ev + intr; i++) {
resume = 0;
- victim = pthread__sa_id(sas[i]);
+ victim = pthread__sa_id(sas[1 + i]);
#ifdef PTHREAD__DEBUG
victim->preempts++;
#endif
- victim->pt_trapuc = sas[i]->sa_context;
+ victim->pt_trapuc = sas[1 + i]->sa_context;
victim->pt_trapuc->uc_flags &= ~_UC_SIGMASK;
SDPRINTF(("(fi %p) victim %d %p(%d)", self, i, victim,
victim->pt_type));
+ if (type == SA_UPCALL_UNBLOCKED && i < ev) {
+ if (victim->pt_blockedlwp == 0) {
+ SDPRINTF((" unblock before block\n"));
+ victim->pt_blockedlwp = -1;
+ } else
+ SDPRINTF((" event\n"));
+ continue;
+ }
if (victim->pt_type == PT_THREAD_UPCALL) {
/* Case 1: Upcall. Must be resumed. */
SDPRINTF((" upcall"));
@@ -347,7 +381,7 @@
* queue mangled by
* pthread__sched_idle2()
*/
- SDPRINTF(("\n"));
+ SDPRINTF((" idled\n"));
continue;
}
@@ -518,8 +552,9 @@
switchto->pt_trapuc = NULL;
victim->pt_switchto = NULL;
victim->pt_switchtouc = NULL;
- SDPRINTF((" switchto: %p (uc %p)", switchto,
- switchto->pt_uc));
+ SDPRINTF((" switchto: %p (uc %p pc %lx)",
+ switchto, switchto->pt_uc,
+ pthread__uc_pc(switchto->pt_uc)));
/*
* Threads can have switchto set to themselves
@@ -528,7 +563,8 @@
*/
if (switchto != victim) {
if ((switchto->pt_next) ||
- (switchto->pt_spinlocks != 0)) {
+ (switchto->pt_spinlocks != 0) ||
+ (switchto->pt_type == PT_THREAD_UPCALL)) {
/*
* The thread being switched
* to was preempted and
@@ -540,12 +576,26 @@
for ( tmp = switchto;
tmp->pt_parent != NULL;
tmp = tmp->pt_parent)
- SDPRINTF((" parent: %p", tmp));
+ SDPRINTF((" parent: %p", tmp->pt_parent));
pthread__assert(tmp->pt_parent == NULL);
tmp->pt_parent = self;
pthread__assert(tmp->pt_next == NULL);
tmp->pt_next = intqueue;
intqueue = tmp;
+ if (switchto->pt_type == PT_THREAD_NORMAL &&
+ switchto->pt_spinlocks == 0) {
+ /*
+ * We set switchto to
+ * ourselves so that we
+ * get off the intqueue
+ */
+ switchto->pt_switchto = switchto;
+ switchto->pt_switchtouc = switchto->pt_uc;
+ }
+ } else if (switchto->pt_type ==
+ PT_THREAD_IDLE &&
+ switchto->pt_flags & PT_FLAG_IDLED) {
+ SDPRINTF((" idle done"));
} else {
switchto->pt_next = runq;
runq = switchto;
@@ -628,12 +678,14 @@
void
pthread__sa_recycle(pthread_t old, pthread_t new)
{
+ int ret;
old->pt_next = NULL;
old->pt_parent = NULL;
old->pt_state = PT_STATE_RUNNABLE;
- sa_stacks(1, &old->pt_stack);
+ ret = sa_stacks(1, &old->pt_stack);
+ pthread__assert(ret == 1);
SDPRINTF(("(recycle %p) recycled %p\n", new, old));
}
Home |
Main Index |
Thread Index |
Old Index