summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_witness.c
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2008-09-10 19:13:30 +0000
committerjhb <jhb@FreeBSD.org>2008-09-10 19:13:30 +0000
commitaf0471aaecf118efcab5180cdca70a1151722ae3 (patch)
tree5defb101ad58952942e4cc44e94404cf65868d19 /sys/kern/subr_witness.c
parentbc107b3828d742160ad1da66c6e2577731499014 (diff)
downloadFreeBSD-src-af0471aaecf118efcab5180cdca70a1151722ae3.zip
FreeBSD-src-af0471aaecf118efcab5180cdca70a1151722ae3.tar.gz
Teach WITNESS about the interlocks used with lockmgr. This removes a bunch
of spurious witness warnings since lockmgr grew witness support. Before this, every time you passed an interlock to a lockmgr lock WITNESS treated it as a LOR. Reviewed by: attilio
Diffstat (limited to 'sys/kern/subr_witness.c')
-rw-r--r--sys/kern/subr_witness.c39
1 files changed, 30 insertions, 9 deletions
diff --git a/sys/kern/subr_witness.c b/sys/kern/subr_witness.c
index 5548224..15f960e 100644
--- a/sys/kern/subr_witness.c
+++ b/sys/kern/subr_witness.c
@@ -1011,10 +1011,10 @@ witness_defineorder(struct lock_object *lock1, struct lock_object *lock2)
void
witness_checkorder(struct lock_object *lock, int flags, const char *file,
- int line)
+ int line, struct lock_object *interlock)
{
struct lock_list_entry **lock_list, *lle;
- struct lock_instance *lock1, *lock2;
+ struct lock_instance *lock1, *lock2, *plock;
struct lock_class *class;
struct witness *w, *w1;
struct thread *td;
@@ -1094,11 +1094,25 @@ witness_checkorder(struct lock_object *lock, int flags, const char *file,
}
/*
+ * Find the previously acquired lock, but ignore interlocks.
+ */
+ plock = &(*lock_list)->ll_children[(*lock_list)->ll_count - 1];
+ if (interlock != NULL && plock->li_lock == interlock) {
+ if ((*lock_list)->ll_count == 1) {
+ /*
+ * The interlock is the only lock we hold, so
+ * nothing to do.
+ */
+ return;
+ }
+ plock = &(*lock_list)->ll_children[(*lock_list)->ll_count - 2];
+ }
+
+ /*
* Try to perform most checks without a lock. If this succeeds we
* can skip acquiring the lock and return success.
*/
- lock1 = &(*lock_list)->ll_children[(*lock_list)->ll_count - 1];
- w1 = lock1->li_lock->lo_witness;
+ w1 = plock->li_lock->lo_witness;
if (witness_lock_order_check(w1, w))
return;
@@ -1141,12 +1155,20 @@ witness_checkorder(struct lock_object *lock, int flags, const char *file,
MPASS(j < WITNESS_COUNT);
lock1 = &lle->ll_children[i];
- w1 = lock1->li_lock->lo_witness;
+
+ /*
+ * Ignore the interlock the first time we see it.
+ */
+ if (interlock != NULL && interlock == lock1->li_lock) {
+ interlock = NULL;
+ continue;
+ }
/*
* If this lock doesn't undergo witness checking,
* then skip it.
*/
+ w1 = lock1->li_lock->lo_witness;
if (w1 == NULL) {
KASSERT((lock1->li_lock->lo_flags & LO_WITNESS) == 0,
("lock missing witness structure"));
@@ -1271,7 +1293,6 @@ witness_checkorder(struct lock_object *lock, int flags, const char *file,
return;
}
}
- lock1 = &(*lock_list)->ll_children[(*lock_list)->ll_count - 1];
/*
* If requested, build a new lock order. However, don't build a new
@@ -1280,11 +1301,11 @@ witness_checkorder(struct lock_object *lock, int flags, const char *file,
* always come before Giant.
*/
if (flags & LOP_NEWORDER &&
- !(lock1->li_lock == &Giant.lock_object &&
+ !(plock->li_lock == &Giant.lock_object &&
(lock->lo_flags & LO_SLEEPABLE) != 0)) {
CTR3(KTR_WITNESS, "%s: adding %s as a child of %s", __func__,
- w->w_name, lock1->li_lock->lo_witness->w_name);
- itismychild(lock1->li_lock->lo_witness, w);
+ w->w_name, plock->li_lock->lo_witness->w_name);
+ itismychild(plock->li_lock->lo_witness, w);
}
out:
mtx_unlock_spin(&w_mtx);
OpenPOWER on IntegriCloud