From 6c6615337251e0d74ac941b5d6cab3782a939ce3 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Tue, 3 Mar 2020 16:36:59 +0300 Subject: [PATCH] Threads: move linux m_timer to static thread_local variable Allows lazy allocation of the timer handle. --- Utilities/Thread.cpp | 48 +++++++++++++++++++++++++++----------------- Utilities/Thread.h | 5 ----- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index e4744bf655..b4da25526c 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -1800,14 +1800,6 @@ void thread_base::initialize(bool(*wait_cb)(const void*)) name.resize(std::min(15, name.size())); pthread_setname_np(pthread_self(), name.c_str()); #endif - -#ifdef __linux__ - m_timer = timerfd_create(CLOCK_MONOTONIC, 0); - if (m_timer == -1) - { - sig_log.error("Linux timer allocation failed, use wait_unlock() only"); - } -#endif } void thread_base::notify_abort() noexcept @@ -1823,13 +1815,6 @@ bool thread_base::finalize(int) noexcept // Report pending errors error_code::error_report(0, 0, 0, 0); -#ifdef __linux__ - if (m_timer != -1) - { - close(m_timer); - } -#endif - #ifdef _WIN32 ULONG64 cycles{}; QueryThreadCycleTime(GetCurrentThread(), &cycles); @@ -1892,7 +1877,34 @@ void thread_ctrl::_wait_for(u64 usec, bool alert /* true */) auto _this = g_tls_this_thread; #ifdef __linux__ - if (!alert && _this->m_timer != -1 && usec > 0 && usec <= 1000) + static thread_local struct linux_timer_handle_t + { + // Allocate timer only if needed (i.e. someone calls _wait_for with alert and short period) + const int m_timer = timerfd_create(CLOCK_MONOTONIC, 0); + + linux_timer_handle_t() noexcept + { + if (m_timer == -1) + { + sig_log.error("Linux timer allocation failed, using the fallback instead."); + } + } + + operator int() const + { + return m_timer; + } + + ~linux_timer_handle_t() + { + if (m_timer != -1) + { + close(m_timer); + } + } + } fd_timer; + + if (!alert && usec > 0 && usec <= 1000 && fd_timer != -1) { struct itimerspec timeout; u64 missed; @@ -1902,8 +1914,8 @@ void thread_ctrl::_wait_for(u64 usec, bool alert /* true */) timeout.it_value.tv_sec = nsec / 1000000000ull; timeout.it_interval.tv_sec = 0; timeout.it_interval.tv_nsec = 0; - timerfd_settime(_this->m_timer, 0, &timeout, NULL); - if (read(_this->m_timer, &missed, sizeof(missed)) != sizeof(missed)) + timerfd_settime(fd_timer, 0, &timeout, NULL); + if (read(fd_timer, &missed, sizeof(missed)) != sizeof(missed)) sig_log.error("timerfd: read() failed"); return; } diff --git a/Utilities/Thread.h b/Utilities/Thread.h index 2e3f4afd6a..d32a6f51c2 100644 --- a/Utilities/Thread.h +++ b/Utilities/Thread.h @@ -97,11 +97,6 @@ class thread_base using native_entry = void*(*)(void* arg); #endif -#ifdef __linux__ - // Linux thread timer - int m_timer = -1; -#endif - // Thread handle (platform-specific) atomic_t m_thread{0};