|
@@ -500,10 +500,17 @@ void qemu_plugin_user_exit(void)
|
|
|
enum qemu_plugin_event ev;
|
|
|
CPUState *cpu;
|
|
|
|
|
|
- QEMU_LOCK_GUARD(&plugin.lock);
|
|
|
-
|
|
|
+ /*
|
|
|
+ * Locking order: we must acquire locks in an order that is consistent
|
|
|
+ * with the one in fork_start(). That is:
|
|
|
+ * - start_exclusive(), which acquires qemu_cpu_list_lock,
|
|
|
+ * must be called before acquiring plugin.lock.
|
|
|
+ * - tb_flush(), which acquires mmap_lock(), must be called
|
|
|
+ * while plugin.lock is not held.
|
|
|
+ */
|
|
|
start_exclusive();
|
|
|
|
|
|
+ qemu_rec_mutex_lock(&plugin.lock);
|
|
|
/* un-register all callbacks except the final AT_EXIT one */
|
|
|
for (ev = 0; ev < QEMU_PLUGIN_EV_MAX; ev++) {
|
|
|
if (ev != QEMU_PLUGIN_EV_ATEXIT) {
|
|
@@ -513,13 +520,12 @@ void qemu_plugin_user_exit(void)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- tb_flush(current_cpu);
|
|
|
-
|
|
|
CPU_FOREACH(cpu) {
|
|
|
qemu_plugin_disable_mem_helpers(cpu);
|
|
|
}
|
|
|
+ qemu_rec_mutex_unlock(&plugin.lock);
|
|
|
|
|
|
+ tb_flush(current_cpu);
|
|
|
end_exclusive();
|
|
|
|
|
|
/* now it's safe to handle the exit case */
|