From 840619197e32c43a697b3479179b007aa0e3fab5 Mon Sep 17 00:00:00 2001 From: Mahmoud Al-Qudsi Date: Sun, 30 Dec 2018 19:25:50 -0600 Subject: [PATCH] Optimize ASSERT_IS_MAIN_THREAD() By using a user-land thread-local integer and lock-free (at least under x86/x64) atomics, we can implement a safe `assert_is_main_thread()` without calling into the kernel. Thread-local variables are part of C++11. This is called a lot in some performance-sensitive areas, so it is worth optimizing. --- src/common.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/common.cpp b/src/common.cpp index 8dabeb570..688ed30d2 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -37,6 +37,7 @@ #endif #include +#include #include // IWYU pragma: keep #include @@ -53,8 +54,7 @@ constexpr wint_t NOT_A_WCHAR = static_cast(WEOF); struct termios shell_modes; -// Note we foolishly assume that pthread_t is just a primitive. But it might be a struct. -static pthread_t main_thread_id = 0; +static std::atomic thread_id { 0 }; static bool thread_asserts_cfg_for_testing = false; wchar_t ellipsis_char; @@ -2162,7 +2162,11 @@ __attribute__((noinline)) void debug_thread_error(void) { } } -void set_main_thread() { main_thread_id = pthread_self(); } +void set_main_thread() { + // Just call is_main_thread() once to force increment of thread_id + // We store the result as `volatile` to guarantee the function call is not optimized away + volatile bool _x = is_main_thread(); +} void configure_thread_assertions_for_testing() { thread_asserts_cfg_for_testing = true; } @@ -2198,8 +2202,8 @@ void restore_term_foreground_process_group() { } bool is_main_thread() { - assert(main_thread_id != 0); - return main_thread_id == pthread_self(); + static thread_local int local_thread_id = thread_id++; + return local_thread_id == 0; } void assert_is_main_thread(const char *who) {