Skip site navigation (1)Skip section navigation (2)
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>