Add a field for QemuMutex to remember the locked status, then assert properly when CONFIG_DEBUG_MUTEX enabled on illegal unlocks.
The pthread library is by default quite loose on this by allowing the unlock to quietly succeed. But that could cause the follow up things very unpredictable so if there's a bug it'll be harder to track than failing early at the illegal unlock. Signed-off-by: Peter Xu <pet...@redhat.com> --- include/qemu/thread-posix.h | 1 + util/qemu-thread-common.h | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/include/qemu/thread-posix.h b/include/qemu/thread-posix.h index 5f2f3d1386..e13bd5492c 100644 --- a/include/qemu/thread-posix.h +++ b/include/qemu/thread-posix.h @@ -9,6 +9,7 @@ struct QemuMutex { #ifdef CONFIG_DEBUG_MUTEX const char *file; int line; + bool locked; #endif bool initialized; }; diff --git a/util/qemu-thread-common.h b/util/qemu-thread-common.h index 2af6b12085..ed74bdb0d1 100644 --- a/util/qemu-thread-common.h +++ b/util/qemu-thread-common.h @@ -21,6 +21,7 @@ static inline void qemu_mutex_post_init(QemuMutex *mutex) #ifdef CONFIG_DEBUG_MUTEX mutex->file = NULL; mutex->line = 0; + mutex->locked = false; #endif mutex->initialized = true; } @@ -37,6 +38,7 @@ static inline void qemu_mutex_post_lock(QemuMutex *mutex, #ifdef CONFIG_DEBUG_MUTEX mutex->file = file; mutex->line = line; + mutex->locked = true; #endif trace_qemu_mutex_locked(mutex, file, line); } @@ -47,6 +49,14 @@ static inline void qemu_mutex_pre_unlock(QemuMutex *mutex, #ifdef CONFIG_DEBUG_MUTEX mutex->file = NULL; mutex->line = 0; + /* + * pthread_mutex_unlock() by default silently ignore unlocking a mutex + * even if it's not locked. Make it strict with QEMU when DEBUG_MUTEX + * is enabled, so that we can capture it at the exact wrong unlock. + * It'll be easier to track this than having misterious deadlock later. + */ + assert(mutex->locked); + mutex->locked = false; #endif trace_qemu_mutex_unlock(mutex, file, line); } -- 2.37.3