@@ -9,6 +9,7 @@ struct QemuMutex {
#ifdef CONFIG_DEBUG_MUTEX
const char *file;
int line;
+ bool locked;
#endif
bool initialized;
};
@@ -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);
}
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 <peterx@redhat.com> --- include/qemu/thread-posix.h | 1 + util/qemu-thread-common.h | 10 ++++++++++ 2 files changed, 11 insertions(+)