diff --git a/system/main.c b/system/main.c index fea264b992..2f08b204c5 100644 --- a/system/main.c +++ b/system/main.c @@ -22,13 +22,14 @@ * THE SOFTWARE. */ +#ifndef XBOX + #include "qemu/osdep.h" #include "qemu-main.h" #include "qemu/main-loop.h" #include "system/replay.h" #include "system/system.h" -#ifndef XBOX #ifdef CONFIG_SDL /* * SDL insists on wrapping the main() function with its own implementation on @@ -41,7 +42,6 @@ #ifdef CONFIG_DARWIN #include #endif -#endif static void *qemu_default_main(void *opaque) { @@ -59,23 +59,6 @@ static void *qemu_default_main(void *opaque) int (*qemu_main)(void); - -#ifdef XBOX - -static int qemu_xemu_main(void) -{ - /* Called after qemu_init, inheriting bql */ - bql_unlock(); - replay_mutex_unlock(); - - qemu_default_main(NULL); - g_assert_not_reached(); -} - -int (*qemu_main)(void) = qemu_xemu_main; - -#else - #ifdef CONFIG_DARWIN static int os_darwin_cfrunloop_main(void) { @@ -114,4 +97,4 @@ int main(int argc, char **argv) } } -#endif /* XBOX */ +#endif diff --git a/system/runstate.c b/system/runstate.c index ff69f18655..5340df6801 100644 --- a/system/runstate.c +++ b/system/runstate.c @@ -902,7 +902,6 @@ int qemu_main_loop(void) while (!main_loop_should_exit(&status)) { main_loop_wait(false); } - return status; } diff --git a/ui/xemu.c b/ui/xemu.c index c2a544e138..cc632141e2 100644 --- a/ui/xemu.c +++ b/ui/xemu.c @@ -33,7 +33,6 @@ #include "qemu/main-loop.h" #include "qemu/rcu.h" #include "qemu-version.h" -#include "qemu-main.h" #include "qapi/error.h" #include "qapi/qapi-commands-block.h" #include "qobject/qdict.h" @@ -114,7 +113,11 @@ static Notifier mouse_mode_notifier; static SDL_Window *m_window; static SDL_GLContext m_context; static QemuSemaphore display_init_sem; +static QemuSemaphore display_shutdown_sem; static QEMUTimer *vblank_timer; +static QemuThread vblank_thread; +static bool qemu_exiting; +static int exit_status; void tcg_register_init_ctx(void); // tcg.c @@ -749,7 +752,7 @@ static void *vblank_timer_thread(void *opaque) struct xemu_console *scon = (struct xemu_console *)opaque; int64_t next_vblank = qemu_clock_get_ns(QEMU_CLOCK_REALTIME); - while (true) { + while (!qatomic_read(&qemu_exiting)) { // Schedule next vblank at fixed interval (absolute deadline) next_vblank += vblank_interval_ns; @@ -763,9 +766,11 @@ static void *vblank_timer_thread(void *opaque) next_vblank = now; } - xemu_main_loop_lock(); - process_vblank(scon); - xemu_main_loop_unlock(); + if (!qatomic_read(&qemu_exiting)) { + xemu_main_loop_lock(); + process_vblank(scon); + xemu_main_loop_unlock(); + } } return NULL; @@ -798,7 +803,7 @@ static void report_stats(void) static void gl_render_frame(struct xemu_console *scon) { static bool rendering; - if (qatomic_xchg(&rendering, true)) { + if (qatomic_xchg(&rendering, true) || qatomic_read(&qemu_exiting)) { return; } @@ -1082,8 +1087,6 @@ static void display_very_early_init(DisplayOptions *o) // Initialize offscreen rendering context now nv2a_context_init(); SDL_GL_MakeCurrent(NULL, NULL); - - // FIXME: atexit(sdl_cleanup); } static void display_early_init(DisplayOptions *o) @@ -1157,11 +1160,30 @@ static void display_init(DisplayState *ds, DisplayOptions *o) // Register event watch to handle rendering during these operations. SDL_AddEventWatch(event_watch_callback, &scon_list[0]); + if (use_vblank_timer_thread) { + qemu_thread_create(&vblank_thread, "vblank-timer", vblank_timer_thread, + &scon_list[0], QEMU_THREAD_JOINABLE); + } else { + vblank_timer = timer_new_ns(QEMU_CLOCK_REALTIME, vblank_timer_callback, &scon_list[0]); + timer_mod_ns(vblank_timer, qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + vblank_interval_ns); + } + /* Tell main thread to go ahead and create the app and enter the run loop */ SDL_GL_MakeCurrent(NULL, NULL); qemu_sem_post(&display_init_sem); } +static void display_finalize(void) +{ + if (use_vblank_timer_thread) { + qemu_thread_join(&vblank_thread); + } + + SDL_RemoveEventWatch(event_watch_callback, &scon_list[0]); + SDL_DestroyWindow(m_window); + SDL_Quit(); +} + static QemuDisplay qemu_display_xemu = { .type = DISPLAY_TYPE_XEMU, .early_init = display_early_init, @@ -1178,15 +1200,20 @@ type_init(register_xemu_display); int gArgc; char **gArgv; -static void *call_qemu_main(void *opaque) +static void *qemu_main(void *opaque) { - int status; - - DPRINTF("Second thread: calling qemu_main()\n"); qemu_init(gArgc, gArgv); - status = qemu_main(); - DPRINTF("Second thread: qemu_main() returned, exiting\n"); - exit(status); + exit_status = qemu_main_loop(); + qatomic_set(&qemu_exiting, true); + bql_unlock(); + qemu_mutex_unlock_main_loop(); + + qemu_sem_wait(&display_shutdown_sem); + bql_lock(); + qemu_cleanup(exit_status); + bql_unlock(); + + return NULL; } #ifdef _WIN32 @@ -1281,7 +1308,6 @@ int main(int argc, char **argv) init_sdl_app_metadata(); - DPRINTF("Entered main()\n"); gArgc = argc; gArgv = argv; @@ -1316,10 +1342,9 @@ int main(int argc, char **argv) display_very_early_init(NULL); qemu_sem_init(&display_init_sem, 0); - qemu_thread_create(&thread, "qemu_main", call_qemu_main, - NULL, QEMU_THREAD_DETACHED); - - DPRINTF("Main thread: waiting for display_init_sem\n"); + qemu_sem_init(&display_shutdown_sem, 0); + qemu_thread_create(&thread, "qemu_main", qemu_main, + NULL, QEMU_THREAD_JOINABLE); qemu_sem_wait(&display_init_sem); gui_grab = 0; @@ -1339,20 +1364,15 @@ int main(int argc, char **argv) xemu_input_init(); xemu_main_loop_unlock(); - if (use_vblank_timer_thread) { - QemuThread vblank_thread; - qemu_thread_create(&vblank_thread, "vblank-timer", vblank_timer_thread, - &scon_list[0], QEMU_THREAD_DETACHED); - } else { - vblank_timer = timer_new_ns(QEMU_CLOCK_REALTIME, vblank_timer_callback, &scon_list[0]); - timer_mod_ns(vblank_timer, qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + vblank_interval_ns); - } - - while (1) { - struct xemu_console *scon = &scon_list[0]; + struct xemu_console *scon = &scon_list[0]; + while (!qatomic_read(&qemu_exiting)) { poll_events(scon); gl_render_frame(scon); } + qemu_sem_post(&display_shutdown_sem); + qemu_thread_join(&thread); + display_finalize(); + return exit_status; } void xemu_eject_disc(Error **errp)