Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/nathanw_sa]: src/sys/kern If sa_switch() fails, have the next LWP go int...
details: https://anonhg.NetBSD.org/src/rev/ec5406a8317c
branches: nathanw_sa
changeset: 506330:ec5406a8317c
user: nathanw <nathanw%NetBSD.org@localhost>
date: Wed Oct 09 16:57:27 2002 +0000
description:
If sa_switch() fails, have the next LWP go into sa_yield() rather than
blithely calling mi_switch(), so that the invariants about running
vs. idle LWPs are maintained. Also, be sure not to set L_SA_UPCALL
when waking up if we didn't successfully make the BLOCKED upcall.
Add some stack count debugging.
diffstat:
sys/kern/kern_sa.c | 123 ++++++++++++++++++++++++++++++----------------------
1 files changed, 70 insertions(+), 53 deletions(-)
diffs (241 lines):
diff -r 4753dd758795 -r ec5406a8317c sys/kern/kern_sa.c
--- a/sys/kern/kern_sa.c Tue Oct 08 19:53:54 2002 +0000
+++ b/sys/kern/kern_sa.c Wed Oct 09 16:57:27 2002 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_sa.c,v 1.1.2.33 2002/09/26 19:45:55 nathanw Exp $ */
+/* $NetBSD: kern_sa.c,v 1.1.2.34 2002/10/09 16:57:27 nathanw Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -51,6 +51,7 @@
#include <uvm/uvm_extern.h>
static int sa_newcachelwp(struct lwp *);
+static struct lwp *sa_vp_repossess(struct lwp *l);
void sa_upcall_getstate(struct sadata_upcall *, struct lwp *, struct lwp *);
@@ -184,7 +185,9 @@
if (error)
return (error);
sa->sa_nstacks += count;
-
+ DPRINTFN(9, ("sa_stacks(%d.%d) nstacks + %d = %2d, nrstacks = %d\n",
+ l->l_proc->p_pid, l->l_lid, count, sa->sa_nstacks, sa->sa_nrstacks));
+
*retval = count;
return (0);
}
@@ -373,6 +376,8 @@
return (ENOMEM);
}
st = sa->sa_stacks[--sa->sa_nstacks];
+ DPRINTFN(9,("sa_upcall(%d.%d) nstacks-- = %2d, nrstacks = %d\n",
+ l->l_proc->p_pid, l->l_lid, sa->sa_nstacks, sa->sa_nrstacks));
return sa_upcall0(l, type, event, interrupted, argsize, arg, sau, &st);
}
@@ -504,18 +509,15 @@
*/
if (sa->sa_nstacks < 2) {
#ifdef DIAGNOSTIC
- printf("sa_switch(%d.%d): Not enough stacks.\n",
- p->p_pid, l->l_lid, error);
+ printf("sa_switch(%d.%d flag %x): Not enough stacks.\n",
+ p->p_pid, l->l_lid, l->l_flag);
#endif
goto sa_upcall_failed;
}
st = sa->sa_stacks[--sa->sa_nstacks];
- DPRINTFN(9, ("sa_switch(%d.%d) nrstacks++ from %d\n",
- p->p_pid, l->l_lid, sa->sa_nrstacks));
sa->sa_rstacks[sa->sa_nrstacks++] =
sa->sa_stacks[--sa->sa_nstacks];
-
sau = sadata_upcall_alloc(0);
if (sau == NULL) {
#ifdef DIAGNOSTIC
@@ -534,11 +536,7 @@
printf("sa_switch(%d.%d): Error %d from sa_upcall()\n",
p->p_pid, l->l_lid, error);
#endif
- sa_upcall_failed:
- /* Put the lwp back */
- sa_putcachelwp(p, l2);
- mi_switch(l, NULL);
- return;
+ goto sa_upcall_failed;
}
l->l_flag |= L_SA_BLOCKING;
@@ -581,6 +579,7 @@
mi_switch(l, NULL);
return;
}
+ sa_upcall_failed:
cpu_setfunc(l2, sa_yieldcall, l2);
l2->l_priority = l2->l_usrpri;
@@ -593,27 +592,31 @@
p->p_pid, l->l_lid, l2 ? l2->l_lid : 0));
mi_switch(l, l2);
- DPRINTFN(4,("sa_switch(%d.%d) returned.\n", p->p_pid, l->l_lid));
+ DPRINTFN(4,("sa_switch(%d.%d flag %x) returned.\n", p->p_pid, l->l_lid, l->l_flag));
KDASSERT(l->l_wchan == 0);
SCHED_ASSERT_UNLOCKED();
if (sa->sa_woken == l)
sa->sa_woken = NULL;
- /*
- * Okay, now we've been woken up. This means that it's time
- * for a SA_UNBLOCKED upcall when we get back to userlevel. */
/*
- * ... unless we're trying to exit. In this case, the last thing
+ * The process is trying to exit. In this case, the last thing
* we want to do is put something back on the cache list.
* It's also not useful to make the upcall at all, so just punt.
*/
-
if (p->p_flag & P_WEXIT)
return;
- l->l_flag |= L_SA_UPCALL;
+ /*
+ * Okay, now we've been woken up. This means that it's time
+ * for a SA_UNBLOCKED upcall when we get back to userlevel, provided
+ * that the SA_BLOCKED upcall happened.
+ */
+ if (l->l_flag & L_SA_BLOCKING)
+ l->l_flag |= L_SA_UPCALL;
+ else
+ sa_vp_repossess(l);
}
void
@@ -752,52 +755,22 @@
p = l->l_proc;
sa = p->p_sa;
- DPRINTFN(7,("sa_upcall_userret(%d.%d)\n", p->p_pid, l->l_lid));
+ DPRINTFN(7,("sa_upcall_userret(%d.%d %x) \n", p->p_pid, l->l_lid,
+ l->l_flag));
if (l->l_flag & L_SA_BLOCKING) {
/* Invoke an "unblocked" upcall */
struct lwp *l2;
- int s;
DPRINTFN(8,("sa_upcall_userret(%d.%d) unblocking ",
p->p_pid, l->l_lid));
- /*
- * Put ourselves on the virtual processor and note that the
- * previous occupant of that position was interrupted.
- */
- l2 = sa->sa_vp;
- sa->sa_vp = l;
- if (sa->sa_idle == l2)
- sa->sa_idle = NULL;
- KDASSERT(l2 != l);
- if (l2) {
- SCHED_LOCK(s);
- switch (l2->l_stat) {
- case LSRUN:
- remrunqueue(l2);
- p->p_nrlwps--;
- break;
- case LSSLEEP:
- unsleep(l2);
- break;
-#ifdef DIAGNOSTIC
- default:
- panic("SA VP %d.%d is in state %d, not running"
- " or sleeping\n", p->p_pid, l2->l_lid,
- l2->l_stat);
-#endif
- }
- sa_putcachelwp(p, l2);
- SCHED_UNLOCK(s);
- }
+ l2 = sa_vp_repossess(l);
l->l_flag &= ~L_SA;
sau = sadata_upcall_alloc(1);
l->l_flag |= L_SA;
KDASSERT(sa->sa_nrstacks > 0);
- DPRINTFN(9, ("sa_userret(%d.%d) decrementing nrstacks from %d\n",
- p->p_pid, l->l_lid, sa->sa_nrstacks));
st = sa->sa_rstacks[--sa->sa_nrstacks];
if (sa_upcall0(l, SA_UPCALL_UNBLOCKED, l, l2, 0, NULL, sau,
&st) != 0) {
@@ -809,7 +782,7 @@
printf("sa_upcall_userret: out of upcall resources"
" for %d.%d\n", p->p_pid, l->l_lid);
#endif
- sigexit(l, SIGILL);
+ sigexit(l, SIGABRT);
/* NOTREACHED */
}
l->l_flag &= ~L_SA_BLOCKING;
@@ -935,6 +908,48 @@
cpu_upcall(l, type, nevents, nint, sapp, ap, stack, sa->sa_upcall);
}
+static struct lwp *
+sa_vp_repossess(struct lwp *l)
+{
+ struct lwp *l2;
+ struct proc *p = l->l_proc;
+ struct sadata *sa = p->p_sa;
+ int s;
+
+ /*
+ * Put ourselves on the virtual processor and note that the
+ * previous occupant of that position was interrupted.
+ */
+ l2 = sa->sa_vp;
+ sa->sa_vp = l;
+ if (sa->sa_idle == l2)
+ sa->sa_idle = NULL;
+
+ KDASSERT(l2 != l);
+ if (l2) {
+ SCHED_LOCK(s);
+ switch (l2->l_stat) {
+ case LSRUN:
+ remrunqueue(l2);
+ p->p_nrlwps--;
+ break;
+ case LSSLEEP:
+ unsleep(l2);
+ break;
+#ifdef DIAGNOSTIC
+ default:
+ panic("SA VP %d.%d is in state %d, not running"
+ " or sleeping\n", p->p_pid, l2->l_lid,
+ l2->l_stat);
+#endif
+ }
+ sa_putcachelwp(p, l2);
+ SCHED_UNLOCK(s);
+ }
+ return l2;
+}
+
+
#ifdef DEBUG
int debug_print_sa(struct proc *);
int debug_print_lwp(struct lwp *);
@@ -973,6 +988,8 @@
if (sa->sa_idle)
printf("SA idle: %d\n", sa->sa_idle->l_lid);
printf("SAs: %d cached LWPs\n", sa->sa_ncached);
+ printf("%d upcall stacks, %d reserved (unblock) stacks\n",
+ sa->sa_nstacks, sa->sa_nrstacks);
LIST_FOREACH(l, &sa->sa_lwpcache, l_sibling)
debug_print_lwp(l);
}
Home |
Main Index |
Thread Index |
Old Index