Date: Wed, 5 Mar 2003 12:40:51 -0800 (PST) From: John Baldwin <jhb@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 26389 for review Message-ID: <200303052040.h25Kepb6091906@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=26389 Change 26389 by jhb@jhb_laptop on 2003/03/05 12:40:27 Split itismychild() out into two separate functions and axe the silly static recursed variable. Also, handle one place where we ignored itismychild() failure and more cleanly handle the failure in witness_lock(). This is mostly a WIP in support of better handling witness's going away. Affected files ... .. //depot/projects/smpng/sys/kern/subr_witness.c#76 edit Differences ... ==== //depot/projects/smpng/sys/kern/subr_witness.c#76 (text+ko) ==== @@ -154,10 +154,12 @@ static struct witness *enroll(const char *description, struct lock_class *lock_class); +static int insertchild(struct witness *parent, struct witness *child); static int itismychild(struct witness *parent, struct witness *child); static void removechild(struct witness *parent, struct witness *child); static int isitmychild(struct witness *parent, struct witness *child); static int isitmydescendant(struct witness *parent, struct witness *child); +static int rebalancetree(void); #ifdef BLESSING static int blessed(struct witness *, struct witness *); #endif @@ -376,7 +378,8 @@ if (w1 == NULL) continue; w1->w_file = "order list"; - itismychild(w, w1); + if (!itismychild(w, w1)) + panic("Not enough memory for static orders!"); w = w1; } } @@ -785,15 +788,15 @@ * Giant if it is the wrong direction. The real lock order is that * sleepable locks come before Giant. */ - if (lock1->li_lock == &Giant.mtx_object && - (lock->lo_flags & LO_SLEEPABLE) != 0) - mtx_unlock_spin(&w_mtx); - else { + if (!(lock1->li_lock == &Giant.mtx_object && + (lock->lo_flags & LO_SLEEPABLE) != 0)) { CTR3(KTR_WITNESS, "%s: adding %s as a child of %s", __func__, lock->lo_type, lock1->li_lock->lo_type); if (!itismychild(lock1->li_lock->lo_witness, w)) - mtx_unlock_spin(&w_mtx); + /* Witness is dead. */ + return; } + mtx_unlock_spin(&w_mtx); out: #ifdef DDB @@ -1116,20 +1119,48 @@ return (w); } +/* + * Prune the whole tree. We look for cases where a lock is now + * both a descendant and a direct child of a given lock. In that + * case, we want to remove the direct child link from the tree. + * + * Returns false if insertchild() fails. + */ static int -itismychild(struct witness *parent, struct witness *child) +rebalancetree(void) +{ + struct witness *child, *parent; + struct witness_list *list; + + if (parent->w_class->lc_flags & LC_SLEEPLOCK) + list = &w_sleep; + else + list = &w_spin; + STAILQ_FOREACH(child, list, w_typelist) { + STAILQ_FOREACH(parent, list, w_typelist) { + if (!isitmychild(parent, child)) + continue; + removechild(parent, child); + if (isitmydescendant(parent, child)) + continue; + if (!insertchild(parent, child)) + return (0); + } + } + witness_levelall(); + return (1); +} + +/* + * Add "child" as a direct child of "parent". Returns false if + * we fail due to out of memory. + */ +static int +insertchild(struct witness *parent, struct witness *child) { - static int recursed; struct witness_child_list_entry **wcl; - struct witness_list *list; MPASS(child != NULL && parent != NULL); - if ((parent->w_class->lc_flags & (LC_SLEEPLOCK | LC_SPINLOCK)) != - (child->w_class->lc_flags & (LC_SLEEPLOCK | LC_SPINLOCK))) - panic( - "%s: parent (%s) and child (%s) are not the same lock type", - __func__, parent->w_class->lc_name, - child->w_class->lc_name); /* * Insert "child" after "parent" @@ -1140,35 +1171,29 @@ if (*wcl == NULL) { *wcl = witness_child_get(); if (*wcl == NULL) - return (1); + return (0); } (*wcl)->wcl_children[(*wcl)->wcl_count++] = child; - /* - * Now prune whole tree. We look for cases where a lock is now - * both a descendant and a direct child of a given lock. In that - * case, we want to remove the direct child link from the tree. - */ - if (recursed) + return (1); +} + +static int +itismychild(struct witness *parent, struct witness *child) +{ + + MPASS(child != NULL && parent != NULL); + if ((parent->w_class->lc_flags & (LC_SLEEPLOCK | LC_SPINLOCK)) != + (child->w_class->lc_flags & (LC_SLEEPLOCK | LC_SPINLOCK))) + panic( + "%s: parent (%s) and child (%s) are not the same lock type", + __func__, parent->w_class->lc_name, + child->w_class->lc_name); + + if (!insertchild(parent, child)) return (0); - recursed = 1; - if (parent->w_class->lc_flags & LC_SLEEPLOCK) - list = &w_sleep; - else - list = &w_spin; - STAILQ_FOREACH(child, list, w_typelist) { - STAILQ_FOREACH(parent, list, w_typelist) { - if (!isitmychild(parent, child)) - continue; - removechild(parent, child); - if (isitmydescendant(parent, child)) - continue; - itismychild(parent, child); - } - } - recursed = 0; - witness_levelall(); - return (0); + + return (rebalancetree()); } static void To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe p4-projects" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200303052040.h25Kepb6091906>