mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-12-05 01:10:24 +00:00
LibCore: Signal an event to queue a wake completion packet on Windows
The initial IOCP event loop implementation adjusted wake() to manually queue a completion packet onto the current threads IOCP. This caused us to now be dependent on the current threads IOCP, when the previous behaviour did not depend on any data from the thread that was waking the event loop. Restoring that old behaviour allows https://hardwaretester.com/gamepad to be loaded again.
This commit is contained in:
committed by
Jelle Raaijmakers
parent
540bbae480
commit
d5e5dbdf3d
Notes:
github-actions[bot]
2025-11-18 17:50:49 +00:00
Author: https://github.com/ayeteadoe Commit: https://github.com/LadybirdBrowser/ladybird/commit/d5e5dbdf3de Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/6838 Reviewed-by: https://github.com/R-Goc ✅ Reviewed-by: https://github.com/gmta ✅
@@ -72,6 +72,11 @@ struct CompletionPacket {
|
||||
CompletionType type;
|
||||
};
|
||||
|
||||
struct EventLoopWake final : CompletionPacket {
|
||||
OwnHandle wait_packet;
|
||||
OwnHandle wait_event;
|
||||
};
|
||||
|
||||
struct EventLoopTimer final : CompletionPacket {
|
||||
|
||||
~EventLoopTimer()
|
||||
@@ -112,11 +117,24 @@ struct ThreadData {
|
||||
}
|
||||
|
||||
ThreadData()
|
||||
: wake_completion_key(make<CompletionPacket>(CompletionType::Wake))
|
||||
: wake_data(make<EventLoopWake>())
|
||||
{
|
||||
wake_data->type = CompletionType::Wake;
|
||||
wake_data->wait_event.handle = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
|
||||
// Consider a way for different event loops to have a different number of threads
|
||||
iocp.handle = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);
|
||||
VERIFY(iocp.handle);
|
||||
|
||||
NTSTATUS status = g_system.NtCreateWaitCompletionPacket(&wake_data->wait_packet.handle, GENERIC_READ | GENERIC_WRITE, NULL);
|
||||
VERIFY(NT_SUCCESS(status));
|
||||
status = g_system.NtAssociateWaitCompletionPacket(wake_data->wait_packet.handle, iocp.handle, wake_data->wait_event.handle, wake_data.ptr(), NULL, 0, 0, NULL);
|
||||
VERIFY(NT_SUCCESS(status));
|
||||
}
|
||||
~ThreadData()
|
||||
{
|
||||
NTSTATUS status = g_system.NtCancelWaitCompletionPacket(wake_data->wait_packet.handle, TRUE);
|
||||
VERIFY(NT_SUCCESS(status));
|
||||
}
|
||||
|
||||
OwnHandle iocp;
|
||||
@@ -125,12 +143,12 @@ struct ThreadData {
|
||||
HashMap<intptr_t, NonnullOwnPtr<EventLoopTimer>> timers;
|
||||
HashMap<Notifier*, NonnullOwnPtr<EventLoopNotifier>> notifiers;
|
||||
|
||||
// The wake completion key is posted to the thread's event loop to wake it.
|
||||
NonnullOwnPtr<CompletionPacket> wake_completion_key;
|
||||
// The wake completion packet is posted to the thread's event loop to wake it.
|
||||
NonnullOwnPtr<EventLoopWake> wake_data;
|
||||
};
|
||||
|
||||
EventLoopImplementationWindows::EventLoopImplementationWindows()
|
||||
: m_wake_completion_key((void*)ThreadData::the()->wake_completion_key.ptr())
|
||||
: m_wake_event(ThreadData::the()->wake_data->wait_event.handle)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -175,7 +193,10 @@ size_t EventLoopImplementationWindows::pump(PumpMode pump_mode)
|
||||
auto& entry = entries[i];
|
||||
auto* packet = reinterpret_cast<CompletionPacket*>(entry.lpCompletionKey);
|
||||
|
||||
if (packet == thread_data->wake_completion_key) {
|
||||
if (packet->type == CompletionType::Wake) {
|
||||
auto* wake_data = static_cast<EventLoopWake*>(packet);
|
||||
NTSTATUS status = g_system.NtAssociateWaitCompletionPacket(wake_data->wait_packet.handle, thread_data->iocp.handle, wake_data->wait_event.handle, wake_data, NULL, 0, 0, NULL);
|
||||
VERIFY(NT_SUCCESS(status));
|
||||
continue;
|
||||
}
|
||||
if (packet->type == CompletionType::Timer) {
|
||||
@@ -223,8 +244,7 @@ void EventLoopImplementationWindows::post_event(EventReceiver& receiver, Nonnull
|
||||
|
||||
void EventLoopImplementationWindows::wake()
|
||||
{
|
||||
auto* thread_data = ThreadData::the();
|
||||
PostQueuedCompletionStatus(thread_data->iocp.handle, 0, (ULONG_PTR)m_wake_completion_key, NULL);
|
||||
SetEvent(m_wake_event);
|
||||
}
|
||||
|
||||
static int notifier_type_to_network_event(NotificationType type)
|
||||
|
||||
@@ -48,7 +48,8 @@ private:
|
||||
bool m_exit_requested { false };
|
||||
int m_exit_code { 0 };
|
||||
|
||||
void const* m_wake_completion_key;
|
||||
// The wake event handle of this event loop needs to be accessible from other threads.
|
||||
void*& m_wake_event;
|
||||
};
|
||||
|
||||
using EventLoopManagerPlatform = EventLoopManagerWindows;
|
||||
|
||||
Reference in New Issue
Block a user