qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v10 01/15] ui & main loop: Redesign of system-specific main t


From: Phil Dennis-Jordan
Subject: Re: [PATCH v10 01/15] ui & main loop: Redesign of system-specific main thread event handling
Date: Thu, 14 Nov 2024 11:32:27 +0100



On Wed, 13 Nov 2024 at 17:38, Paolo Bonzini <pbonzini@redhat.com> wrote:
On 11/13/24 15:23, Phil Dennis-Jordan wrote:
> macOS's Cocoa event handling must be done on the initial (main) thread
> of the process. Furthermore, if library or application code uses
> libdispatch, the main dispatch queue must be handling events on the main
> thread as well.
>
> So far, this has affected Qemu in both the Cocoa and SDL UIs, although
> in different ways: the Cocoa UI replaces the default qemu_main function
> with one that spins Qemu's internal main event loop off onto a
> background thread. SDL (which uses Cocoa internally) on the other hand
> uses a polling approach within Qemu's main event loop. Events are
> polled during the SDL UI's dpy_refresh callback, which happens to run
> on the main thread by default.
>
> As UIs are mutually exclusive, this works OK as long as nothing else
> needs platform-native event handling. In the next patch, a new device is
> introduced based on the ParavirtualizedGraphics.framework in macOS.
> This uses libdispatch internally, and only works when events are being
> handled on the main runloop. With the current system, it works when
> using either the Cocoa or the SDL UI. However, it does not when running
> headless. Moreover, any attempt to install a similar scheme to the
> Cocoa UI's main thread replacement fails when combined with the SDL
> UI.
>
> This change tidies up main thread management to be more flexible.
>
>   * The qemu_main global function pointer is a custom function for the
>     main thread, and it may now be NULL. When it is, the main thread
>     runs the main Qemu loop. This represents the traditional setup.
>   * When non-null, spawning the main Qemu event loop on a separate
>     thread is now done centrally rather than inside the Cocoa UI code.
>   * For most platforms, qemu_main is indeed NULL by default, but on
>     Darwin, it defaults to a function that runs the CFRunLoop.
>   * The Cocoa UI sets qemu_main to a function which runs the
>     NSApplication event handling runloop, as is usual for a Cocoa app.
>   * The SDL UI overrides the qemu_main function to NULL, thus
>     specifying that Qemu's main loop must run on the main
>     thread.
>   * The GTK UI also overrides the qemu_main function to NULL.
>   * For other UIs, or in the absence of UIs, the platform's default
>     behaviour is followed.
>
> This means that on macOS, the platform's runloop events are always
> handled, regardless of chosen UI. The new PV graphics device will
> thus work in all configurations. There is no functional change on other
> operating systems.
>
> Signed-off-by: Phil Dennis-Jordan <phil@philjordan.eu>
> Reviewed-by: Akihiko Odaki <akihiko.odaki@daynix.com>

I checked what GTK+ does and, either way, you have to create another
thread: timers are handled with a CFRunLoopTimer, but file descriptors
are polled in a separate thread and sent to the main thread with a
single CFRunLoopSource.  It's a bit nicer that the main thread is in
charge, but it's more complex and probably slower too.

Just to clarify: is this supposed to be happening inside the GTK+ library itself? i.e. GTK should spawn its own thread to poll file descriptors that are owned by GTK? (As opposed to the file descriptors used by QEMU's own event loop - what on Linux are eventfds, but on macOS I think are just pipes*.)

This doesn't describe what I'm seeing when I run with -display gtk on macOS. There's no extra thread created. There's a dock icon, but it's non-interactive ("Application not responding"), there aren't any menus, and there's no window. QEMU's own simulation is running in the background - I can reach a guest via the network. So I guess there's some function in GTK we're supposed to be calling that will make it crank the native event loop on macOS, but this isn't being done?

Or do you mean there exists a global "block here forever" function in GTK we can call from the main thread and which will make everything spring into life, but that brings with it the same requirement as with the Cocoa UI: moving everything that was originally on the main thread onto a background thread. (I've done some searching for GTK docs and other background info but anything I've found has been rather thin on this topic. The ui/gtk*.c source is also not particularly enlightening - it seems to imply that something in the background ought to be handling events somewhere.)

[* The event loop in QEMU on macOS probably ought to use a kqueue, with EVFILT_USER where eventfds are used on Linux, except the rough equivalent of ioeventfds are Mach ports which can be handled via EVFILT_MACHPORT, but I digress.]

As long as it's clear that any handlers that go through the CFRunLoop
run outside the BQL, as is already the case for the Cocoa UI, I see no
problem with this approach.
 
I'm not entirely sure what you're getting at here, to be honest. The UI thread can definitely not assume to be holding the BQL all the time; we'd have to treat it more like an AIOContext. It could pave the way towards putting the display and UI subsystems on their own AIOContext or AIOContext-like-thing, rather than hogging the BQL for expensive image operations.

(*By the sound of it, Win32 has an all-UI-calls-on-one-thread requirement as well which we may be violating to some degree via the GTK and/or SDL backends as well; my adventures with Win32 are almost 20 years back now so I'm a bit out of the loop there.)
 
Acked-by: Paolo Bonzini <pbonzini@redhat.com>

Paolo



reply via email to

[Prev in Thread] Current Thread [Next in Thread]