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.
This commit is contained in:
Matt Borgerson 2020-06-17 17:36:23 -07:00 committed by mborgerson
parent 60d3dc8ae1
commit 7d2b038ef6
4 changed files with 49 additions and 0 deletions

View File

@ -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

View File

@ -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);

View File

@ -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);
}

View File

@ -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();