diff options
author | jhb <jhb@FreeBSD.org> | 2008-09-10 19:13:30 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2008-09-10 19:13:30 +0000 |
commit | af0471aaecf118efcab5180cdca70a1151722ae3 (patch) | |
tree | 5defb101ad58952942e4cc44e94404cf65868d19 /sys/kern/subr_witness.c | |
parent | bc107b3828d742160ad1da66c6e2577731499014 (diff) | |
download | FreeBSD-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.c | 39 |
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); |