PERFORCE change 103646 for review
John Baldwin
jhb at FreeBSD.org
Fri Aug 11 18:24:57 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=103646
Change 103646 by jhb at 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);
More information about the p4-projects
mailing list