diff --git a/sys/kern/kern_mutex.c b/sys/kern/kern_mutex.c index 13502b42122d..2a933eb74cf0 100644 --- a/sys/kern/kern_mutex.c +++ b/sys/kern/kern_mutex.c @@ -809,6 +809,7 @@ _thread_lock(struct thread *td) { struct mtx *m; uintptr_t tid, v; + int recursed = 0; tid = (uintptr_t)curthread; @@ -823,16 +824,16 @@ _thread_lock(struct thread *td) goto slowpath_unlocked; } else if (v == tid) { m->mtx_recurse++; + recursed = 1; } else goto slowpath_unlocked; if (__predict_true(m == td->td_lock)) { WITNESS_LOCK(&m->lock_object, LOP_EXCLUSIVE, file, line); return; } - if (m->mtx_recurse != 0) - m->mtx_recurse--; - else - _mtx_release_lock_quick(m); + if (recursed) + panic("%s: mismatch on a recursed lock\n", __func__); + _mtx_release_lock_quick(m); slowpath_unlocked: spinlock_exit(); slowpath_noirq: @@ -860,6 +861,7 @@ thread_lock_flags_(struct thread *td, int opts, const char *file, int line) #if defined(KDTRACE_HOOKS) || defined(LOCK_PROFILING) int doing_lockprof = 1; #endif + int recursed; tid = (uintptr_t)curthread; @@ -886,9 +888,10 @@ thread_lock_flags_(struct thread *td, int opts, const char *file, int line) if (__predict_false(doing_lockprof)) spin_time -= lockstat_nsecs(&td->td_lock->lock_object); #endif + spinlock_enter(); + for (;;) { retry: - spinlock_enter(); m = td->td_lock; thread_lock_validate(m, opts, file, line); v = MTX_READ_VALUE(m); @@ -899,6 +902,7 @@ thread_lock_flags_(struct thread *td, int opts, const char *file, int line) continue; } if (v == tid) { + recursed = 1; m->mtx_recurse++; break; } @@ -912,15 +916,19 @@ thread_lock_flags_(struct thread *td, int opts, const char *file, int line) } else { _mtx_lock_indefinite_check(m, &lda); } - if (m != td->td_lock) + if (m != td->td_lock) { + spinlock_enter(); goto retry; + } v = MTX_READ_VALUE(m); } while (v != MTX_UNOWNED); spinlock_enter(); } if (m == td->td_lock) break; - __mtx_unlock_spin(m); /* does spinlock_exit() */ + if (recursed) + panic("%s: mismatch on a recursed lock\n", __func__); + _mtx_release_lock_quick(m); } LOCK_LOG_LOCK("LOCK", &m->lock_object, opts, m->mtx_recurse, file, line);