Index: subr_witness.c =================================================================== --- subr_witness.c (revision 183666) +++ subr_witness.c (working copy) @@ -103,6 +103,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -1015,7 +1016,7 @@ void witness_checkorder(struct lock_object *lock, int flags, const char *file, int line, struct lock_object *interlock) { - struct lock_list_entry **lock_list, *lle; + struct lock_list_entry *lock_list, *lle; struct lock_instance *lock1, *lock2, *plock; struct lock_class *class; struct witness *w, *w1; @@ -1043,38 +1044,36 @@ witness_checkorder(struct lock_object *lock, int f class->lc_name, lock->lo_name, file, line); /* - * If this is the first lock acquired then just return as - * no order checking is needed. + * If this is the first lock acquired then just return + * as no order checking is needed. */ - if (td->td_sleeplocks == NULL) + lock_list = td->td_sleeplocks; + if (lock_list == NULL || lock_list->ll_count == 0) return; - lock_list = &td->td_sleeplocks; } else { /* * If this is the first lock, just return as no order - * checking is needed. We check this in both if clauses - * here as unifying the check would require us to use a - * critical section to ensure we don't migrate while doing - * the check. Note that if this is not the first lock, we - * are already in a critical section and are safe for the - * rest of the check. + * checking is needed. We have to disable migration + * while doing this check. If we have another spin + * lock already, it will protect the list for the rest + * of this routine. */ - if (PCPU_GET(spinlocks) == NULL) + sched_pin(); + lock_list = PCPU_GET(spinlocks); + if (lock_list == NULL || lock_list->ll_count == 0) { + sched_unpin(); return; - lock_list = PCPU_PTR(spinlocks); + } + sched_unpin(); } - /* Empty list? */ - if ((*lock_list)->ll_count == 0) - return; - /* * Check to see if we are recursing on a lock we already own. If * so, make sure that we don't mismatch exclusive and shared lock * acquires. */ - lock1 = find_instance(*lock_list, lock); + lock1 = find_instance(lock_list, lock); if (lock1 != NULL) { if ((lock1->li_flags & LI_EXCLUSIVE) != 0 && (flags & LOP_EXCLUSIVE) == 0) { @@ -1098,17 +1097,21 @@ witness_checkorder(struct lock_object *lock, int f /* * Find the previously acquired lock, but ignore interlocks. */ - plock = &(*lock_list)->ll_children[(*lock_list)->ll_count - 1]; + 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; + if (lock_list->ll_count > 1) + plock = &lock_list->ll_children[lock_list->ll_count + - 2]; + else { + lle = lock_list->ll_next; + if (lle == NULL) + /* + * The interlock is the only lock we + * hold, so nothing to do. + */ + return; + plock = &lle->ll_children[lle->ll_count - 1]; } - plock = &(*lock_list)->ll_children[(*lock_list)->ll_count - 2]; } /* @@ -1154,7 +1157,7 @@ witness_checkorder(struct lock_object *lock, int f if (isitmychild(w1, w)) goto out; - for (j = 0, lle = *lock_list; lle != NULL; lle = lle->ll_next) { + for (j = 0, lle = lock_list; lle != NULL; lle = lle->ll_next) { for (i = lle->ll_count - 1; i >= 0; i--, j++) { MPASS(j < WITNESS_COUNT);