Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 3 Jun 2013 17:41:11 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r251326 - head/sys/kern
Message-ID:  <201306031741.r53HfBtp096058@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Mon Jun  3 17:41:11 2013
New Revision: 251326
URL: http://svnweb.freebsd.org/changeset/base/251326

Log:
  - Fix a couple of inverted panic messages for shared/exclusive mismatches
    of a lock within a single thread.
  - Fix handling of interlocks in WITNESS by properly requiring the interlock
    to be held exactly once if it is specified.

Modified:
  head/sys/kern/kern_lock.c
  head/sys/kern/subr_witness.c

Modified: head/sys/kern/kern_lock.c
==============================================================================
--- head/sys/kern/kern_lock.c	Mon Jun  3 17:40:52 2013	(r251325)
+++ head/sys/kern/kern_lock.c	Mon Jun  3 17:41:11 2013	(r251326)
@@ -511,7 +511,7 @@ __lockmgr_args(struct lock *lk, u_int fl
 	case LK_SHARED:
 		if (LK_CAN_WITNESS(flags))
 			WITNESS_CHECKORDER(&lk->lock_object, LOP_NEWORDER,
-			    file, line, ilk);
+			    file, line, flags & LK_INTERLOCK ? ilk : NULL);
 		for (;;) {
 			x = lk->lk_lock;
 
@@ -723,7 +723,8 @@ __lockmgr_args(struct lock *lk, u_int fl
 	case LK_EXCLUSIVE:
 		if (LK_CAN_WITNESS(flags))
 			WITNESS_CHECKORDER(&lk->lock_object, LOP_NEWORDER |
-			    LOP_EXCLUSIVE, file, line, ilk);
+			    LOP_EXCLUSIVE, file, line, flags & LK_INTERLOCK ?
+			    ilk : NULL);
 
 		/*
 		 * If curthread already holds the lock and this one is
@@ -1072,7 +1073,8 @@ __lockmgr_args(struct lock *lk, u_int fl
 	case LK_DRAIN:
 		if (LK_CAN_WITNESS(flags))
 			WITNESS_CHECKORDER(&lk->lock_object, LOP_NEWORDER |
-			    LOP_EXCLUSIVE, file, line, ilk);
+			    LOP_EXCLUSIVE, file, line, flags & LK_INTERLOCK ?
+			    ilk : NULL);
 
 		/*
 		 * Trying to drain a lock we already own will result in a

Modified: head/sys/kern/subr_witness.c
==============================================================================
--- head/sys/kern/subr_witness.c	Mon Jun  3 17:40:52 2013	(r251325)
+++ head/sys/kern/subr_witness.c	Mon Jun  3 17:41:11 2013	(r251326)
@@ -1053,7 +1053,7 @@ witness_checkorder(struct lock_object *l
 {
 	struct lock_list_entry *lock_list, *lle;
 	struct lock_instance *lock1, *lock2, *plock;
-	struct lock_class *class;
+	struct lock_class *class, *iclass;
 	struct witness *w, *w1;
 	struct thread *td;
 	int i, j;
@@ -1119,7 +1119,7 @@ witness_checkorder(struct lock_object *l
 			    fixup_filename(file), line);
 			printf("while exclusively locked from %s:%d\n",
 			    fixup_filename(lock1->li_file), lock1->li_line);
-			kassert_panic("share->excl");
+			kassert_panic("excl->share");
 		}
 		if ((lock1->li_flags & LI_EXCLUSIVE) == 0 &&
 		    (flags & LOP_EXCLUSIVE) != 0) {
@@ -1128,11 +1128,27 @@ witness_checkorder(struct lock_object *l
 			    fixup_filename(file), line);
 			printf("while share locked from %s:%d\n",
 			    fixup_filename(lock1->li_file), lock1->li_line);
-			kassert_panic("excl->share");
+			kassert_panic("share->excl");
 		}
 		return;
 	}
 
+	/* Warn if the interlock is not locked exactly once. */
+	if (interlock != NULL) {
+		iclass = LOCK_CLASS(interlock);
+		lock1 = find_instance(lock_list, interlock);
+		if (lock1 == NULL)
+			kassert_panic("interlock (%s) %s not locked @ %s:%d",
+			    iclass->lc_name, interlock->lo_name,
+			    flags & LOP_EXCLUSIVE ? "exclusive" : "shared",
+			    fixup_filename(file), line);
+		else if ((lock1->li_flags & LI_RECURSEMASK) != 0)
+			kassert_panic("interlock (%s) %s recursed @ %s:%d",
+			    iclass->lc_name, interlock->lo_name,
+			    flags & LOP_EXCLUSIVE ? "exclusive" : "shared",
+			    fixup_filename(file), line);
+	}
+
 	/*
 	 * Find the previously acquired lock, but ignore interlocks.
 	 */
@@ -1205,12 +1221,10 @@ witness_checkorder(struct lock_object *l
 			lock1 = &lle->ll_children[i];
 
 			/*
-			 * Ignore the interlock the first time we see it.
+			 * Ignore the interlock.
 			 */
-			if (interlock != NULL && interlock == lock1->li_lock) {
-				interlock = NULL;
+			if (interlock == lock1->li_lock)
 				continue;
-			}
 
 			/*
 			 * If this lock doesn't undergo witness checking,



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