panic on HEAD
Matthew Dillon
dillon at apollo.backplane.com
Wed Sep 7 17:47:20 PDT 2005
::After a week of uptime:
::
::panic: assertion: tok->t_cpu == gd in lwkt_reltoken
::panic messages:
I found another case that could cause the panic. It's a fairly rare
case but 1-week-to-crash is believable if this turns out to be the
cqause. Peter, I would appreciate it if you would run the enclosed
patch in addition to the KTR options I previously suggested.
Other people with SMP boxes who would like to help test, please run
this patch as well! I will commit it in a week if no issues crop up.
On a more general note, I am clearly going to have to rethink the whole
token business. I like the API, but my implementation seems a little
more bug-prone then I would like.
-Matt
Index: lwkt_token.c
===================================================================
RCS file: /cvs/src/sys/kern/lwkt_token.c,v
retrieving revision 1.22
diff -u -r1.22 lwkt_token.c
--- lwkt_token.c 7 Jul 2005 20:28:26 -0000 1.22
+++ lwkt_token.c 7 Sep 2005 23:51:09 -0000
@@ -85,9 +85,6 @@
#endif
-#define MAKE_TOKENS_SPIN
-/* #define MAKE_TOKENS_YIELD */
-
#ifndef LWKT_NUM_POOL_TOKENS
#define LWKT_NUM_POOL_TOKENS 1024 /* power of 2 */
#endif
@@ -299,6 +296,14 @@
* If we are preempting another thread which owns the token we have to
* yield to get out from the preemption because we cannot obtain a token
* owned by the thread we are preempting.
+ *
+ * If we are preempting another thread and do not own the token,
+ * we must yield to get out from the preemption because we cannot
+ * safely call lwkt_drain_token_requests() and give away tokens
+ * that the thread we preempted might own.
+ *
+ * The act of yielding performs a thread switch and we will own all
+ * tokens on our td_toks list when it switches back to us and returns.
*/
if (td->td_preempted) {
while ((td = td->td_preempted) != NULL) {
@@ -306,22 +311,35 @@
if (scan->tr_tok == tok) {
lwkt_yield();
KKASSERT(tok->t_cpu == gd);
- goto breakout;
+ return;
}
}
}
-breakout: ;
td = gd->gd_curthread; /* our thread, again */
+ if (tok->t_cpu != gd) {
+ lwkt_yield();
+ KKASSERT(tok->t_cpu == gd);
+ }
+ return;
}
/*
- * If our cpu does not own the token then (currently) spin while we
- * await it. XXX we should yield here but some testing is required
- * before we do so, there could be some interlock issues with e.g.
- * softupdates before we can yield. ZZZ
+ * If we are not preempting another thread we can safely give
+ * away tokens while we busy loop.
+ *
+ * Currently tokens acquired by mainline threads are not assumed to
+ * break the big giant lock, so we have to spin when acquiring them.
+ * It would be nice to be able to yield here instead but we could
+ * run up against unexpected problems with e.g. softupdates or other
+ * subsystems. It's safest to spin. XXX
+ *
+ * XXX we should use some sort of time-slot synchronization and delay
+ * for these giveaways (with each cpu given a different timeslot) to
+ * avoid livelocks.
*/
#ifdef SMP
if (tok->t_cpu != gd) {
+#define MAKE_TOKENS_SPIN
#if defined(MAKE_TOKENS_SPIN)
int x = 40000000;
int y = 10;
@@ -340,10 +358,8 @@
splz();
}
crit_exit();
-#elif defined(MAKE_TOKENS_YIELD)
- lwkt_yield();
#else
-#error MAKE_TOKENS_XXX ?
+ lwkt_yield();
#endif
KKASSERT(tok->t_cpu == gd);
}
@@ -525,10 +541,8 @@
#endif
splz();
crit_exit();
-#elif defined(MAKE_TOKENS_YIELD)
- lwkt_yield();
#else
-#error MAKE_TOKENS_XXX ?
+ lwkt_yield();
#endif
}
KKASSERT(ref->tr_magic == LWKT_TOKREF_MAGIC1);
More information about the Bugs
mailing list