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 | |
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')
-rw-r--r-- | sys/kern/kern_lock.c | 6 | ||||
-rw-r--r-- | sys/kern/kern_mutex.c | 6 | ||||
-rw-r--r-- | sys/kern/kern_rmlock.c | 4 | ||||
-rw-r--r-- | sys/kern/kern_rwlock.c | 4 | ||||
-rw-r--r-- | sys/kern/kern_sx.c | 4 | ||||
-rw-r--r-- | sys/kern/subr_witness.c | 39 | ||||
-rw-r--r-- | sys/sys/lock.h | 13 |
7 files changed, 49 insertions, 27 deletions
diff --git a/sys/kern/kern_lock.c b/sys/kern/kern_lock.c index df123a5..2bb02fd 100644 --- a/sys/kern/kern_lock.c +++ b/sys/kern/kern_lock.c @@ -375,7 +375,7 @@ __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk, case LK_SHARED: if (LK_CAN_WITNESS(flags)) WITNESS_CHECKORDER(&lk->lock_object, LOP_NEWORDER, - file, line); + file, line, ilk); for (;;) { x = lk->lk_lock; @@ -505,7 +505,7 @@ __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk, case LK_EXCLUSIVE: if (LK_CAN_WITNESS(flags)) WITNESS_CHECKORDER(&lk->lock_object, LOP_NEWORDER | - LOP_EXCLUSIVE, file, line); + LOP_EXCLUSIVE, file, line, ilk); /* * If curthread already holds the lock and this one is @@ -724,7 +724,7 @@ __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk, case LK_DRAIN: if (LK_CAN_WITNESS(flags)) WITNESS_CHECKORDER(&lk->lock_object, LOP_NEWORDER | - LOP_EXCLUSIVE, file, line); + LOP_EXCLUSIVE, file, line, ilk); /* * Trying to drain a lock we already own will result in a diff --git a/sys/kern/kern_mutex.c b/sys/kern/kern_mutex.c index e36f65c..523d911 100644 --- a/sys/kern/kern_mutex.c +++ b/sys/kern/kern_mutex.c @@ -177,7 +177,7 @@ _mtx_lock_flags(struct mtx *m, int opts, const char *file, int line) ("mtx_lock() of spin mutex %s @ %s:%d", m->lock_object.lo_name, file, line)); WITNESS_CHECKORDER(&m->lock_object, opts | LOP_NEWORDER | LOP_EXCLUSIVE, - file, line); + file, line, NULL); _get_sleep_lock(m, curthread, opts, file, line); LOCK_LOG_LOCK("LOCK", &m->lock_object, opts, m->mtx_recurse, file, @@ -221,7 +221,7 @@ _mtx_lock_spin_flags(struct mtx *m, int opts, const char *file, int line) ("mtx_lock_spin: recursed on non-recursive mutex %s @ %s:%d\n", m->lock_object.lo_name, file, line)); WITNESS_CHECKORDER(&m->lock_object, opts | LOP_NEWORDER | LOP_EXCLUSIVE, - file, line); + file, line, NULL); _get_spin_lock(m, curthread, opts, file, line); LOCK_LOG_LOCK("LOCK", &m->lock_object, opts, m->mtx_recurse, file, line); @@ -506,7 +506,7 @@ retry: ("thread_lock: recursed on non-recursive mutex %s @ %s:%d\n", m->lock_object.lo_name, file, line)); WITNESS_CHECKORDER(&m->lock_object, - opts | LOP_NEWORDER | LOP_EXCLUSIVE, file, line); + opts | LOP_NEWORDER | LOP_EXCLUSIVE, file, line, NULL); while (!_obtain_lock(m, tid)) { if (m->mtx_lock == tid) { m->mtx_recurse++; diff --git a/sys/kern/kern_rmlock.c b/sys/kern/kern_rmlock.c index cbf5cc5..f2bd721 100644 --- a/sys/kern/kern_rmlock.c +++ b/sys/kern/kern_rmlock.c @@ -433,7 +433,7 @@ void _rm_wlock_debug(struct rmlock *rm, const char *file, int line) WITNESS_CHECKORDER(&rm->lock_object, LOP_NEWORDER | LOP_EXCLUSIVE, - file, line); + file, line, NULL); _rm_wlock(rm); @@ -460,7 +460,7 @@ _rm_rlock_debug(struct rmlock *rm, struct rm_priotracker *tracker, { - WITNESS_CHECKORDER(&rm->lock_object, LOP_NEWORDER , file, line); + WITNESS_CHECKORDER(&rm->lock_object, LOP_NEWORDER , file, line, NULL); _rm_rlock(rm, tracker); diff --git a/sys/kern/kern_rwlock.c b/sys/kern/kern_rwlock.c index dcc833f..84c344a 100644 --- a/sys/kern/kern_rwlock.c +++ b/sys/kern/kern_rwlock.c @@ -206,7 +206,7 @@ _rw_wlock(struct rwlock *rw, const char *file, int line) KASSERT(rw->rw_lock != RW_DESTROYED, ("rw_wlock() of destroyed rwlock @ %s:%d", file, line)); WITNESS_CHECKORDER(&rw->lock_object, LOP_NEWORDER | LOP_EXCLUSIVE, file, - line); + line, NULL); __rw_wlock(rw, curthread, file, line); LOCK_LOG_LOCK("WLOCK", &rw->lock_object, 0, rw->rw_recurse, file, line); WITNESS_LOCK(&rw->lock_object, LOP_EXCLUSIVE, file, line); @@ -283,7 +283,7 @@ _rw_rlock(struct rwlock *rw, const char *file, int line) KASSERT(rw_wowner(rw) != curthread, ("%s (%s): wlock already held @ %s:%d", __func__, rw->lock_object.lo_name, file, line)); - WITNESS_CHECKORDER(&rw->lock_object, LOP_NEWORDER, file, line); + WITNESS_CHECKORDER(&rw->lock_object, LOP_NEWORDER, file, line, NULL); for (;;) { /* diff --git a/sys/kern/kern_sx.c b/sys/kern/kern_sx.c index 5006793..e1e34ec 100644 --- a/sys/kern/kern_sx.c +++ b/sys/kern/kern_sx.c @@ -211,7 +211,7 @@ _sx_slock(struct sx *sx, int opts, const char *file, int line) MPASS(curthread != NULL); KASSERT(sx->sx_lock != SX_LOCK_DESTROYED, ("sx_slock() of destroyed sx @ %s:%d", file, line)); - WITNESS_CHECKORDER(&sx->lock_object, LOP_NEWORDER, file, line); + WITNESS_CHECKORDER(&sx->lock_object, LOP_NEWORDER, file, line, NULL); error = __sx_slock(sx, opts, file, line); if (!error) { LOCK_LOG_LOCK("SLOCK", &sx->lock_object, 0, 0, file, line); @@ -254,7 +254,7 @@ _sx_xlock(struct sx *sx, int opts, const char *file, int line) KASSERT(sx->sx_lock != SX_LOCK_DESTROYED, ("sx_xlock() of destroyed sx @ %s:%d", file, line)); WITNESS_CHECKORDER(&sx->lock_object, LOP_NEWORDER | LOP_EXCLUSIVE, file, - line); + line, NULL); error = __sx_xlock(sx, curthread, opts, file, line); if (!error) { LOCK_LOG_LOCK("XLOCK", &sx->lock_object, 0, sx->sx_recurse, 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); diff --git a/sys/sys/lock.h b/sys/sys/lock.h index b10cc23..b2f7782 100644 --- a/sys/sys/lock.h +++ b/sys/sys/lock.h @@ -203,7 +203,8 @@ void spinlock_exit(void); void witness_init(struct lock_object *, const char *); void witness_destroy(struct lock_object *); int witness_defineorder(struct lock_object *, struct lock_object *); -void witness_checkorder(struct lock_object *, int, const char *, int); +void witness_checkorder(struct lock_object *, int, const char *, int, + struct lock_object *); void witness_lock(struct lock_object *, int, const char *, int); void witness_upgrade(struct lock_object *, int, const char *, int); void witness_downgrade(struct lock_object *, int, const char *, int); @@ -231,8 +232,8 @@ void witness_thread_exit(struct thread *); #define WITNESS_DESTROY(lock) \ witness_destroy(lock) -#define WITNESS_CHECKORDER(lock, flags, file, line) \ - witness_checkorder((lock), (flags), (file), (line)) +#define WITNESS_CHECKORDER(lock, flags, file, line, interlock) \ + witness_checkorder((lock), (flags), (file), (line), (interlock)) #define WITNESS_DEFINEORDER(lock1, lock2) \ witness_defineorder((struct lock_object *)(lock1), \ @@ -276,7 +277,7 @@ void witness_thread_exit(struct thread *); #define WITNESS_INIT(lock, type) #define WITNESS_DESTROY(lock) #define WITNESS_DEFINEORDER(lock1, lock2) 0 -#define WITNESS_CHECKORDER(lock, flags, file, line) +#define WITNESS_CHECKORDER(lock, flags, file, line, interlock) #define WITNESS_LOCK(lock, flags, file, line) #define WITNESS_UPGRADE(lock, flags, file, line) #define WITNESS_DOWNGRADE(lock, flags, file, line) @@ -296,10 +297,10 @@ void witness_thread_exit(struct thread *); */ #define witness_check(l) \ WITNESS_CHECKORDER(&(l)->lock_object, LOP_EXCLUSIVE, LOCK_FILE, \ - LOCK_LINE) + LOCK_LINE, NULL) #define witness_check_shared(l) \ - WITNESS_CHECKORDER(&(l)->lock_object, 0, LOCK_FILE, LOCK_LINE) + WITNESS_CHECKORDER(&(l)->lock_object, 0, LOCK_FILE, LOCK_LINE, NULL) #endif /* _KERNEL */ #endif /* _SYS_LOCK_H_ */ |