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