From a501b9c7df595f044cac4c474032447318a4979a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?kleines=20Filmr=C3=B6llchen?= Date: Sun, 2 Jan 2022 15:14:25 +0100 Subject: [PATCH] LibCore: Create wake pipe on each thread After the previous change, the wake pipe was only being created on the main thread by the main event loop. This change utilizes a flag to always initialize the wake pipe on other threads. Because the pipe is quite expensive (it will count towards the file descriptor limit, for instance), we do the initialization "lazily": Only when an event loop is constructed and it notices that there hasn't been a wake pipe created on its thread, it will create the pipe. Conversely, this means that there are no pipes on threads that never use an event loop. --- Userland/Libraries/LibCore/EventLoop.cpp | 32 ++++++++++++++++-------- Userland/Libraries/LibCore/EventLoop.h | 2 ++ 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/Userland/Libraries/LibCore/EventLoop.cpp b/Userland/Libraries/LibCore/EventLoop.cpp index a7804bddc9..387ddd72dc 100644 --- a/Userland/Libraries/LibCore/EventLoop.cpp +++ b/Userland/Libraries/LibCore/EventLoop.cpp @@ -66,6 +66,23 @@ static thread_local Vector* s_event_loop_stack; static thread_local HashMap>* s_timers; static thread_local HashTable* s_notifiers; thread_local int EventLoop::s_wake_pipe_fds[2]; +thread_local bool EventLoop::s_wake_pipe_initialized { false }; + +void EventLoop::initialize_wake_pipes() +{ + if (!s_wake_pipe_initialized) { +#if defined(SOCK_NONBLOCK) + int rc = pipe2(s_wake_pipe_fds, O_CLOEXEC); +#else + int rc = pipe(s_wake_pipe_fds); + fcntl(s_wake_pipe_fds[0], F_SETFD, FD_CLOEXEC); + fcntl(s_wake_pipe_fds[1], F_SETFD, FD_CLOEXEC); + +#endif + VERIFY(rc == 0); + s_wake_pipe_initialized = true; + } +} bool EventLoop::has_been_instantiated() { @@ -273,19 +290,8 @@ EventLoop::EventLoop([[maybe_unused]] MakeInspectable make_inspectable) } s_main_event_loop.with_locked([&, this](auto*& main_event_loop) { if (main_event_loop == nullptr) { - // FIXME: The compiler complains that we don't use main_event_loop although we set it. main_event_loop = this; s_pid = getpid(); - // FIXME: We only create the wake pipe for the main thread -#if defined(SOCK_NONBLOCK) - int rc = pipe2(s_wake_pipe_fds, O_CLOEXEC); -#else - int rc = pipe(s_wake_pipe_fds); - fcntl(s_wake_pipe_fds[0], F_SETFD, FD_CLOEXEC); - fcntl(s_wake_pipe_fds[1], F_SETFD, FD_CLOEXEC); - -#endif - VERIFY(rc == 0); s_event_loop_stack->append(*this); #ifdef __serenity__ @@ -300,6 +306,8 @@ EventLoop::EventLoop([[maybe_unused]] MakeInspectable make_inspectable) } }); + initialize_wake_pipes(); + dbgln_if(EVENTLOOP_DEBUG, "{} Core::EventLoop constructed :)", getpid()); } @@ -587,6 +595,8 @@ void EventLoop::notify_forked(ForkEvent event) s_event_loop_stack->clear(); s_timers->clear(); s_notifiers->clear(); + s_wake_pipe_initialized = false; + initialize_wake_pipes(); if (auto* info = signals_info()) { info->signal_handlers.clear(); info->next_signal_id = 0; diff --git a/Userland/Libraries/LibCore/EventLoop.h b/Userland/Libraries/LibCore/EventLoop.h index e2de367f48..a6efab523d 100644 --- a/Userland/Libraries/LibCore/EventLoop.h +++ b/Userland/Libraries/LibCore/EventLoop.h @@ -36,6 +36,7 @@ public: explicit EventLoop(MakeInspectable = MakeInspectable::No); ~EventLoop(); + static void initialize_wake_pipes(); int exec(); @@ -123,6 +124,7 @@ private: int m_exit_code { 0 }; static thread_local int s_wake_pipe_fds[2]; + static thread_local bool s_wake_pipe_initialized; struct Private; NonnullOwnPtr m_private;