Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 11 Aug 2006 18:24:12 GMT
From:      John Baldwin <jhb@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 103646 for review
Message-ID:  <200608111824.k7BIOCPk004348@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=103646

Change 103646 by jhb@jhb_mutex on 2006/08/11 18:23:19

	- Pass the thread index to the event handlers so they can key their
	  behavior off the thread index.
	- Output start messages as well as finish ones per-thread.
	- Just drop the event_mtx around the event handler.  Previously, if
	  crash_thread got a bogus event it would cv_wait on an unlocked
	  mutex.
	- Add events to create intentional sx, lockmgr, and sx+lockmgr
	  cycles to test 'show sleepchain'.

Affected files ...

.. //depot/projects/smpng/sys/modules/crash2/crash2.c#10 edit

Differences ...

==== //depot/projects/smpng/sys/modules/crash2/crash2.c#10 (text+ko) ====

@@ -49,6 +49,7 @@
 #include <sys/kthread.h>
 #include <sys/linker.h>
 #include <sys/lock.h>
+#include <sys/lockmgr.h>
 #include <sys/module.h>
 #include <sys/mutex.h>
 #include <sys/proc.h>
@@ -61,7 +62,7 @@
 
 #define	NTHREADS	4
 
-typedef void (*event_handler)(void);
+typedef void (*event_handler)(int);
 
 struct crash2_event {
 	const char *ev_name;
@@ -87,6 +88,8 @@
 static int event[NTHREADS];
 static struct rwlock foo;
 static struct mtx bar;
+static struct sx one, two, three, four;
+static struct lock fee, fi, fo, fum;
 
 static int	mod_event(struct module *module, int cmd, void *arg);
 static int	load(void *arg);
@@ -96,8 +99,49 @@
 
 /* Events. */
 
+static struct lock *locks[] = { &fee, &fi, &fo, &fum };
+static struct sx *sxs[] = { &one, &two, &three, &four };
+
+static void
+sleep_deadlock(int thread)
+{
+
+	if (thread % 2)
+		sx_xlock(sxs[thread % 4]);
+	else
+		lockmgr(locks[thread % 4], LK_EXCLUSIVE, NULL, curthread);
+	tsleep(sxs, 0, "slp_dead", hz/10);
+	if (thread % 2)
+		lockmgr(locks[(thread + 1) % 4], LK_EXCLUSIVE, NULL, curthread);
+	else
+		sx_xlock(sxs[(thread + 1) % 4]);
+}
+CRASH2_EVENT("sx and lockmgr cycle", sleep_deadlock, sleep_deadlock,
+    sleep_deadlock, sleep_deadlock);
+
 static void
-foo_grades(void)
+lockmgr_deadlock(int thread)
+{
+
+	lockmgr(locks[thread % 4], LK_EXCLUSIVE, NULL, curthread);
+	tsleep(sxs, 0, "lk_dead", hz/10);
+	lockmgr(locks[(thread + 1) % 4], LK_EXCLUSIVE, NULL, curthread);
+}
+CRASH2_EVENT("lockmgr cycle", lockmgr_deadlock, lockmgr_deadlock,
+    lockmgr_deadlock, lockmgr_deadlock);
+
+static void
+sx_deadlock(int thread)
+{
+
+	sx_xlock(sxs[thread % 4]);
+	tsleep(sxs, 0, "sx_dead", hz/10);
+	sx_xlock(sxs[(thread + 1) % 4]);
+}
+CRASH2_EVENT("sx cycle", sx_deadlock, sx_deadlock, sx_deadlock, sx_deadlock);
+
+static void
+foo_grades(int dummy)
 {
 
 	switch (arc4random() % 10) {
@@ -136,12 +180,12 @@
 }
 
 static void
-foo_grades_lots(void)
+foo_grades_lots(int dummy)
 {
 	int i;
 
 	for (i = 0; i < 50000; i++)
-		foo_grades();
+		foo_grades(dummy);
 }
 
 CRASH2_EVENT("lots of foo up/downgrades", foo_grades_lots, foo_grades_lots,
@@ -150,7 +194,7 @@
     foo_grades);
 
 static void
-bar_sleep(void)
+bar_sleep(int dummy)
 {
 
 	mtx_lock(&bar);
@@ -160,7 +204,7 @@
 CRASH2_EVENT("sleep holding bar", bar_sleep, bar_sleep, bar_sleep, bar_sleep);
 
 static void
-whack_foo(void)
+whack_foo(int dummy)
 {
 	switch (arc4random() % 10) {
 	case 0:
@@ -178,16 +222,16 @@
 }
 
 static void
-whack_foo_lots(void)
+whack_foo_lots(int dummy)
 {
 	int i;
 
 	for (i = 0; i < 50000; i++)
-		whack_foo();
+		whack_foo(dummy);
 }
 
 static void
-wlock_foo(void)
+wlock_foo(int dummy)
 {
 
 	rw_wlock(&foo);
@@ -196,7 +240,7 @@
 }
 
 static void
-rlock_foo(void)
+rlock_foo(int dummy)
 {
 
 	rw_rlock(&foo);
@@ -214,7 +258,7 @@
 /* Help event should be last so that it is always event 1. */
 
 static void
-help(void)
+help(int dummy)
 {
 	struct crash2_event **ev;
 
@@ -230,7 +274,7 @@
 /* Null event 0. */
 
 static void
-nop(void)
+nop(int dummy)
 {
 }
 CRASH2_EVENT(NULL, nop);
@@ -277,15 +321,15 @@
 
 	i = (intptr_t)arg;
 	if (i == 0)
-		help();
+		help(0);
 	mtx_lock(&event_mtx);
 	while (1) {
 		while ((ev = event[i]) == 0)
 			cv_wait(&event_cv, &event_mtx);
 		event[i] = 0;
-		mtx_unlock(&event_mtx);
 		if (ev == -1) {
 			printf("crash2[%d]: exiting\n", i);
+			mtx_unlock(&event_mtx);
 			kthread_exit(0);
 			break;
 		}
@@ -294,10 +338,13 @@
 			continue;
 		}
 		evp = event_start[ev];
-		if (evp->ev_handler[i])
-			evp->ev_handler[i]();		
-		mtx_lock(&event_mtx);
-		printf("crash2[%d]: %s\n", i, evp->ev_name);
+		if (evp->ev_handler[i]) {
+			printf("crash2[%d]: started %s\n", i, evp->ev_name);
+			mtx_unlock(&event_mtx);
+			evp->ev_handler[i](i);		
+			mtx_lock(&event_mtx);
+			printf("crash2[%d]: finished %s\n", i, evp->ev_name);
+		}
 	}
 }
 
@@ -320,6 +367,14 @@
 
 	rw_init(&foo, "foo");
 	mtx_init(&bar, "bar", NULL, MTX_DEF);
+	sx_init(&one, "one");
+	sx_init(&two, "two");
+	sx_init(&three, "three");
+	sx_init(&four, "four");
+	lockinit(&fee, PWAIT, "fee", 0, 0);
+	lockinit(&fi, PWAIT, "fi", 0, 0);
+	lockinit(&fo, PWAIT, "fo", 0, 0);
+	lockinit(&fum, PWAIT, "fum", 0, 0);
 	mtx_init(&event_mtx, "crash2 event", NULL, MTX_DEF);
 	cv_init(&event_cv, "crash2");
 	for (i = 0; i < NTHREADS;  i++) {
@@ -351,6 +406,14 @@
 		}
 	mtx_destroy(&event_mtx);
 	cv_destroy(&event_cv);
+	lockdestroy(&fum);
+	lockdestroy(&fo);
+	lockdestroy(&fi);
+	lockdestroy(&fee);
+	sx_destroy(&four);
+	sx_destroy(&three);
+	sx_destroy(&two);
+	sx_destroy(&one);
 	mtx_destroy(&bar);
 	rw_destroy(&foo);
 	return (0);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200608111824.k7BIOCPk004348>