- 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.
This commit is contained in:
John Baldwin 2013-06-03 17:41:11 +00:00
parent 03e1315345
commit 24150d37d3
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=251326
2 changed files with 26 additions and 10 deletions

View File

@ -511,7 +511,7 @@ __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk,
case LK_SHARED: case LK_SHARED:
if (LK_CAN_WITNESS(flags)) if (LK_CAN_WITNESS(flags))
WITNESS_CHECKORDER(&lk->lock_object, LOP_NEWORDER, WITNESS_CHECKORDER(&lk->lock_object, LOP_NEWORDER,
file, line, ilk); file, line, flags & LK_INTERLOCK ? ilk : NULL);
for (;;) { for (;;) {
x = lk->lk_lock; x = lk->lk_lock;
@ -723,7 +723,8 @@ __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk,
case LK_EXCLUSIVE: case LK_EXCLUSIVE:
if (LK_CAN_WITNESS(flags)) if (LK_CAN_WITNESS(flags))
WITNESS_CHECKORDER(&lk->lock_object, LOP_NEWORDER | 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 * 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: case LK_DRAIN:
if (LK_CAN_WITNESS(flags)) if (LK_CAN_WITNESS(flags))
WITNESS_CHECKORDER(&lk->lock_object, LOP_NEWORDER | 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 * Trying to drain a lock we already own will result in a

View File

@ -1053,7 +1053,7 @@ witness_checkorder(struct lock_object *lock, int flags, const char *file,
{ {
struct lock_list_entry *lock_list, *lle; struct lock_list_entry *lock_list, *lle;
struct lock_instance *lock1, *lock2, *plock; struct lock_instance *lock1, *lock2, *plock;
struct lock_class *class; struct lock_class *class, *iclass;
struct witness *w, *w1; struct witness *w, *w1;
struct thread *td; struct thread *td;
int i, j; int i, j;
@ -1119,7 +1119,7 @@ witness_checkorder(struct lock_object *lock, int flags, const char *file,
fixup_filename(file), line); fixup_filename(file), line);
printf("while exclusively locked from %s:%d\n", printf("while exclusively locked from %s:%d\n",
fixup_filename(lock1->li_file), lock1->li_line); fixup_filename(lock1->li_file), lock1->li_line);
kassert_panic("share->excl"); kassert_panic("excl->share");
} }
if ((lock1->li_flags & LI_EXCLUSIVE) == 0 && if ((lock1->li_flags & LI_EXCLUSIVE) == 0 &&
(flags & LOP_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); fixup_filename(file), line);
printf("while share locked from %s:%d\n", printf("while share locked from %s:%d\n",
fixup_filename(lock1->li_file), lock1->li_line); fixup_filename(lock1->li_file), lock1->li_line);
kassert_panic("excl->share"); kassert_panic("share->excl");
} }
return; 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. * 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]; lock1 = &lle->ll_children[i];
/* /*
* Ignore the interlock the first time we see it. * Ignore the interlock.
*/ */
if (interlock != NULL && interlock == lock1->li_lock) { if (interlock == lock1->li_lock)
interlock = NULL;
continue; continue;
}
/* /*
* If this lock doesn't undergo witness checking, * If this lock doesn't undergo witness checking,