From 7d2b038ef64e1f64fd4dce63d3a990b139c9c3b9 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Wed, 17 Jun 2020 17:36:23 -0700 Subject: [PATCH] main-loop: Add an outer lock on QEMU main loop Ensures monitor commands run from the UI thread are synchronous and not interfered with by things running on the QEMU main loop. e.g. savevm which gives up the iothread lock. There's likely a nicer way to do this, but for now this will do. --- include/qemu/main-loop.h | 6 ++++++ softmmu/vl.c | 4 ++++ ui/xemu.c | 4 ++++ util/main-loop.c | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 49 insertions(+) diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h index a6d20b0719..4c29dedd97 100644 --- a/include/qemu/main-loop.h +++ b/include/qemu/main-loop.h @@ -325,4 +325,10 @@ typedef struct MainLoopPoll { void main_loop_poll_add_notifier(Notifier *notify); void main_loop_poll_remove_notifier(Notifier *notify); +#ifdef XBOX +void qemu_init_main_loop_lock(void); +void qemu_mutex_lock_main_loop(void); +void qemu_mutex_unlock_main_loop(void); +#endif + #endif diff --git a/softmmu/vl.c b/softmmu/vl.c index 0d1eb7d5e0..63da28ebd4 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -2993,6 +2993,10 @@ void qemu_init(int argc, char **argv, char **envp) qemu_init_cpu_list(); qemu_init_cpu_loop(); +#ifdef XBOX + qemu_init_main_loop_lock(); + qemu_mutex_lock_main_loop(); +#endif qemu_mutex_lock_iothread(); atexit(qemu_run_exit_notifiers); diff --git a/ui/xemu.c b/ui/xemu.c index 709a7e04d1..73a0ead944 100644 --- a/ui/xemu.c +++ b/ui/xemu.c @@ -1085,9 +1085,11 @@ static void xemu_sdl2_gl_render_surface(struct sdl2_console *scon) glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_INT, NULL); // FIXME: Finer locking + qemu_mutex_lock_main_loop(); qemu_mutex_lock_iothread(); xemu_hud_render(); qemu_mutex_unlock_iothread(); + qemu_mutex_unlock_main_loop(); // xb_surface_gl_render_texture(scon->surface); pre_swap(); @@ -1172,6 +1174,7 @@ void sdl2_gl_refresh(DisplayChangeListener *dcl) SDL_GL_MakeCurrent(scon->real_window, scon->winctx); + qemu_mutex_lock_main_loop(); qemu_mutex_lock_iothread(); graphic_hw_update(dcl->con); @@ -1180,6 +1183,7 @@ void sdl2_gl_refresh(DisplayChangeListener *dcl) } sdl2_poll_events(scon); qemu_mutex_unlock_iothread(); + qemu_mutex_unlock_main_loop(); xemu_sdl2_gl_render_surface(scon); } diff --git a/util/main-loop.c b/util/main-loop.c index 9d7ad8dd4c..bf5e590bd3 100644 --- a/util/main-loop.c +++ b/util/main-loop.c @@ -48,6 +48,12 @@ */ GMainContext *qemu_main_context = NULL; GMainLoop *qemu_main_loop_obj = NULL; + +/* *Another* main loop lock. Used for ensuring the main loop does not get a + * chance to continue when some action is being handled on the UI interaction + * thread that gives up the BQL but expects the main loop to not be running. + */ +QemuMutex qemu_main_loop_lock; #endif #ifndef _WIN32 @@ -160,6 +166,23 @@ void qemu_notify_event(void) static GArray *gpollfds; +#ifdef XBOX +void qemu_init_main_loop_lock(void) +{ + qemu_mutex_init(&qemu_main_loop_lock); +} + +void qemu_mutex_lock_main_loop(void) +{ + qemu_mutex_lock(&qemu_main_loop_lock); +} + +void qemu_mutex_unlock_main_loop(void) +{ + qemu_mutex_unlock(&qemu_main_loop_lock); +} +#endif + int qemu_init_main_loop(Error **errp) { int ret; @@ -277,7 +300,13 @@ static int os_host_main_loop_wait(int64_t timeout) qemu_mutex_unlock_iothread(); replay_mutex_unlock(); +#ifdef XBOX + qemu_mutex_unlock_main_loop(); +#endif ret = qemu_poll_ns((GPollFD *)gpollfds->data, gpollfds->len, timeout); +#ifdef XBOX + qemu_mutex_lock_main_loop(); +#endif replay_mutex_lock(); qemu_mutex_lock_iothread(); @@ -494,7 +523,13 @@ static int os_host_main_loop_wait(int64_t timeout) replay_mutex_unlock(); +#ifdef XBOX + qemu_mutex_unlock_main_loop(); +#endif g_poll_ret = qemu_poll_ns(poll_fds, n_poll_fds + w->num, poll_timeout_ns); +#ifdef XBOX + qemu_mutex_lock_main_loop(); +#endif replay_mutex_lock();