PERFORCE change 134047 for review
John Baldwin
jhb at FreeBSD.org
Thu Jan 24 17:34:31 PST 2008
http://perforce.freebsd.org/chv.cgi?CH=134047
Change 134047 by jhb at jhb_mutex on 2008/01/25 01:33:43
- Compile (catch up to kdb_enter() API change).
- Add a test for the tsleep/pause race.
Affected files ...
.. //depot/projects/smpng/sys/modules/crash/crash.c#42 edit
Differences ...
==== //depot/projects/smpng/sys/modules/crash/crash.c#42 (text+ko) ====
@@ -52,11 +52,14 @@
#include <sys/refcount.h>
#include <sys/rwlock.h>
#include <sys/sched.h>
+#include <sys/sleepqueue.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
#include <sys/sx.h>
#include <sys/unistd.h>
+#define KDB_WHY_CRASH "crash"
+
struct crash_event {
const char *ev_name;
void (*ev_handler)(void);
@@ -86,6 +89,48 @@
/* Events. */
+static int race_wchan;
+
+static void
+tsleep_race_fallback(void *dummy)
+{
+
+ wakeup(&race_wchan);
+}
+
+static void
+exercise_tsleep_race(void)
+{
+ struct callout c;
+ struct bintime start, finish;
+ struct timeval elapsed;
+ int rval;
+
+ /*
+ * Inline copy of tsleep() with a long DELAY() to open up the
+ * race window where the thread lock is dropped in between
+ * sleepq_add() and sleepq_*wait*().
+ */
+ callout_init(&c, CALLOUT_MPSAFE);
+ callout_reset(&c, 5 * hz, tsleep_race_fallback, NULL);
+ getbinuptime(&start);
+ sleepq_lock(&race_wchan);
+ DROP_GIANT();
+ sleepq_add(&race_wchan, NULL, "race", SLEEPQ_SLEEP, 0);
+ sleepq_set_timeout(&race_wchan, 1);
+ DELAY(2 * 1000 * 1000);
+ rval = sleepq_timedwait(&race_wchan);
+ getbinuptime(&finish);
+ PICKUP_GIANT();
+ printf("crash: sleepq_timedwait() returned %d\n", rval);
+ bintime_sub(&finish, &start);
+ bintime2timeval(&finish, &elapsed);
+ printf("crash: slept for %d.%04ld sec\n", elapsed.tv_sec,
+ elapsed.tv_usec / 1000);
+ callout_drain(&c);
+}
+CRASH_EVENT("exercise tsleep() race", exercise_tsleep_race);
+
static void
sx_recurse(void)
{
@@ -93,7 +138,7 @@
sx_init_flags(&qux, "qux", SX_RECURSE);
sx_xlock(&qux);
sx_xlock(&qux);
- kdb_enter("qux should be recursed");
+ kdb_enter(KDB_WHY_CRASH, "qux should be recursed");
sx_xunlock(&qux);
if (sx_try_xlock(&qux) == 0)
panic("try_xlock failed!");
@@ -200,9 +245,9 @@
sx_init(&qux, "qux");
sx_destroy(&qux);
- kdb_enter("examine qux");
+ kdb_enter(KDB_WHY_CRASH, "examine qux");
sx_xlock(&qux);
- kdb_enter("examine again");
+ kdb_enter(KDB_WHY_CRASH, "examine again");
}
CRASH_EVENT("lock destroyed sx", lock_destroyed_sx);
@@ -212,9 +257,9 @@
rw_init(&baz, "baz");
rw_destroy(&baz);
- kdb_enter("examine baz");
+ kdb_enter(KDB_WHY_CRASH, "examine baz");
rw_wlock(&baz);
- kdb_enter("examine again");
+ kdb_enter(KDB_WHY_CRASH, "examine again");
}
CRASH_EVENT("lock destroyed rwlock", lock_destroyed_rw);
@@ -226,9 +271,9 @@
mtx_init(&test1_mtx, "test1", NULL, MTX_DEF | MTX_RECURSE);
mtx_lock(&test1_mtx);
mtx_destroy(&test1_mtx);
- kdb_enter("examine test1");
+ kdb_enter(KDB_WHY_CRASH, "examine test1");
mtx_lock(&test1_mtx);
- kdb_enter("examine again");
+ kdb_enter(KDB_WHY_CRASH, "examine again");
}
CRASH_EVENT("lock destroyed mutex", lock_destroyed_mtx);
@@ -408,11 +453,11 @@
{
rw_init(&baz, "baz");
- kdb_enter("baz exists");
+ kdb_enter(KDB_WHY_CRASH, "baz exists");
rw_wlock(&baz);
- kdb_enter("baz has a writer");
+ kdb_enter(KDB_WHY_CRASH, "baz has a writer");
rw_wunlock(&baz);
- kdb_enter("baz is unlocked");
+ kdb_enter(KDB_WHY_CRASH, "baz is unlocked");
rw_destroy(&baz);
}
CRASH_EVENT("rw_wlock", rwlock_wlock);
@@ -422,11 +467,11 @@
{
rw_init(&baz, "baz");
- kdb_enter("baz exists");
+ kdb_enter(KDB_WHY_CRASH, "baz exists");
rw_rlock(&baz);
- kdb_enter("baz has a reader");
+ kdb_enter(KDB_WHY_CRASH, "baz has a reader");
rw_runlock(&baz);
- kdb_enter("baz is unlocked");
+ kdb_enter(KDB_WHY_CRASH, "baz is unlocked");
rw_destroy(&baz);
}
CRASH_EVENT("rw_rlock", rwlock_rlock);
@@ -448,11 +493,11 @@
mtx_lock_spin(&test1_mtx);
error = msleep_spin(&test1_mtx, &test1_mtx, "spincr", 5);
printf("msleep_spin returned %d\n", error);
- kdb_enter("timed out");
+ kdb_enter(KDB_WHY_CRASH, "timed out");
timeout(msleep_spin_callout, NULL, 5);
error = msleep_spin(&test1_mtx, &test1_mtx, "spincr2", 0);
printf("msleep_spin returned %d\n", error);
- kdb_enter("awoke from spin");
+ kdb_enter(KDB_WHY_CRASH, "awoke from spin");
mtx_unlock_spin(&test1_mtx);
mtx_destroy(&test1_mtx);
}
@@ -463,18 +508,18 @@
{
mtx_lock(&Giant);
- kdb_enter("Giant locked");
+ kdb_enter(KDB_WHY_CRASH, "Giant locked");
mtx_lock(&Giant);
- kdb_enter("Giant recursed");
+ kdb_enter(KDB_WHY_CRASH, "Giant recursed");
mtx_unlock(&Giant);
mtx_unlock(&Giant);
sx_slock(&foo);
- kdb_enter("foo slocked");
+ kdb_enter(KDB_WHY_CRASH, "foo slocked");
sx_sunlock(&foo);
sx_xlock(&foo);
- kdb_enter("foo xlocked");
+ kdb_enter(KDB_WHY_CRASH, "foo xlocked");
sx_xunlock(&foo);
- kdb_enter("both unlocked");
+ kdb_enter(KDB_WHY_CRASH, "both unlocked");
}
CRASH_EVENT("ddb lock commands", ddblock_test);
@@ -620,9 +665,9 @@
static void
double_mtx_init(void)
{
- kdb_enter("about to init again");
+ kdb_enter(KDB_WHY_CRASH, "about to init again");
mtx_init(&test_mtx, "test", NULL, MTX_DEF);
- kdb_enter("if we haven't panic'd by now, ouch. :(");
+ kdb_enter(KDB_WHY_CRASH, "if we haven't panic'd by now, ouch. :(");
mtx_destroy(&test_mtx);
}
CRASH_EVENT("re-init of test_mtx", double_mtx_init);
@@ -664,18 +709,19 @@
bzero(&test2_mtx, sizeof(test2_mtx));
mtx_init(&test1_mtx, "test1", NULL, MTX_DEF);
mtx_init(&test2_mtx, "test2", NULL, MTX_DEF);
- kdb_enter("no order yet");
+ kdb_enter(KDB_WHY_CRASH, "no order yet");
mtx_lock(&Giant);
mtx_lock(&test1_mtx);
mtx_lock(&test2_mtx);
mtx_unlock(&test2_mtx);
mtx_unlock(&test1_mtx);
mtx_unlock(&Giant);
- kdb_enter("test1 and test2 should be ordered");
+ kdb_enter(KDB_WHY_CRASH, "test1 and test2 should be ordered");
mtx_destroy(&test1_mtx);
- kdb_enter("test1 should be gone, test2 should be after Giant");
+ kdb_enter(KDB_WHY_CRASH,
+ "test1 should be gone, test2 should be after Giant");
mtx_destroy(&test2_mtx);
- kdb_enter("test1 and test2 should be gone");
+ kdb_enter(KDB_WHY_CRASH, "test1 and test2 should be gone");
}
CRASH_EVENT("use test1 and test2 mutexes to test witness removal",
test_witness_removal);
@@ -721,10 +767,10 @@
bzero(&test2_mtx, sizeof(test2_mtx));
mtx_init(&test1_mtx, "test1", NULL, MTX_DEF);
mtx_init(&test2_mtx, "test2", NULL, MTX_DEF);
- kdb_enter("no order yet");
+ kdb_enter(KDB_WHY_CRASH, "no order yet");
status = WITNESS_DEFINEORDER(&test1_mtx, &test2_mtx);
printf("Status of test1 -> test2 set order should be 0: %d\n", status);
- kdb_enter("order should be test1 then test2");
+ kdb_enter(KDB_WHY_CRASH, "order should be test1 then test2");
printf("Check order of test1 -> test2 should succeed.\n");
mtx_lock(&test1_mtx);
witness_check(&test2_mtx);
@@ -786,7 +832,7 @@
if (depth == 20) {
kdb_backtrace();
- kdb_enter(__func__);
+ kdb_enter(KDB_WHY_CRASH, __func__);
} else
recurse_deep(depth + 1);
}
More information about the p4-projects
mailing list