From owner-p4-projects@FreeBSD.ORG Fri Aug 11 18:24:57 2006 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id CD9AD16A64E; Fri, 11 Aug 2006 18:24:56 +0000 (UTC) X-Original-To: perforce@freebsd.org Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 8B7C916A5D2 for ; Fri, 11 Aug 2006 18:24:56 +0000 (UTC) (envelope-from jhb@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id B5CCE43EB2 for ; Fri, 11 Aug 2006 18:24:26 +0000 (GMT) (envelope-from jhb@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.6/8.13.6) with ESMTP id k7BIODeR004353 for ; Fri, 11 Aug 2006 18:24:13 GMT (envelope-from jhb@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.6/8.13.4/Submit) id k7BIOCPk004348 for perforce@freebsd.org; Fri, 11 Aug 2006 18:24:12 GMT (envelope-from jhb@freebsd.org) Date: Fri, 11 Aug 2006 18:24:12 GMT Message-Id: <200608111824.k7BIOCPk004348@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to jhb@freebsd.org using -f From: John Baldwin To: Perforce Change Reviews Cc: Subject: PERFORCE change 103646 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 11 Aug 2006 18:24:57 -0000 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 #include #include +#include #include #include #include @@ -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);