summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2013-06-03 17:41:11 +0000
committerjhb <jhb@FreeBSD.org>2013-06-03 17:41:11 +0000
commitfbe58039391c863167ca77024f95b85e67f14ce5 (patch)
treebe1bd195336606e60192d4440ae2e532344031e2 /sys/kern
parenta2b00a43740f58ac5f2b7f65c4a89092fcea32e9 (diff)
downloadFreeBSD-src-fbe58039391c863167ca77024f95b85e67f14ce5.zip
FreeBSD-src-fbe58039391c863167ca77024f95b85e67f14ce5.tar.gz
- 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.
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_lock.c8
-rw-r--r--sys/kern/subr_witness.c28
2 files changed, 26 insertions, 10 deletions
diff --git a/sys/kern/kern_lock.c b/sys/kern/kern_lock.c
index 849f583..f0eedd8 100644
--- a/sys/kern/kern_lock.c
+++ b/sys/kern/kern_lock.c
@@ -511,7 +511,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, ilk);
+ file, line, flags & LK_INTERLOCK ? ilk : NULL);
for (;;) {
x = lk->lk_lock;
@@ -723,7 +723,8 @@ __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, 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 flags, struct lock_object *ilk,
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
diff --git a/sys/kern/subr_witness.c b/sys/kern/subr_witness.c
index ac7636ae..bf28a88 100644
--- a/sys/kern/subr_witness.c
+++ b/sys/kern/subr_witness.c
@@ -1053,7 +1053,7 @@ witness_checkorder(struct lock_object *lock, int flags, const char *file,
{
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 *lock, int flags, const char *file,
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 *lock, int flags, const char *file,
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 *lock, int flags, const char *file,
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,
OpenPOWER on IntegriCloud