ui: Exit from main thread and finalize display

This commit is contained in:
Matt Borgerson
2026-01-31 13:16:21 -07:00
committed by mborgerson
parent 3b7a83d64b
commit d96a472116
3 changed files with 54 additions and 52 deletions
+3 -20
View File
@@ -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 <CoreFoundation/CoreFoundation.h>
#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
-1
View File
@@ -902,7 +902,6 @@ int qemu_main_loop(void)
while (!main_loop_should_exit(&status)) {
main_loop_wait(false);
}
return status;
}
+51 -31
View File
@@ -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)