From 589d416977977f32fde82cd623a7a876ab1d397c Mon Sep 17 00:00:00 2001 From: Lennox Ho Date: Tue, 19 Sep 2023 14:53:16 +0800 Subject: [PATCH] Add a more performant SpinLockDelay implementation for Windows based on WaitOnAddress and friends --- CMakeLists.txt | 3 +++ Makefile.am | 1 + src/base/spinlock_win32-inl.h | 19 ++++++++++++++----- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 03c9961..e705f01 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -566,6 +566,9 @@ if(MINGW OR MSVC) # We also need to tell mingw that sysinfo.cc needs shlwapi.lib. # (We do this via a #pragma for msvc, but need to do it here for mingw). target_link_libraries(sysinfo shlwapi) + # spinlock uses WaitOnAddress et al. We need to link to synchronization.lib + # (We also do this via a #pragma for msvc, but need to do it here for mingw). + target_link_libraries(spinlock synchronization) else() set(SPINLOCK_INCLUDES src/base/spinlock.h diff --git a/Makefile.am b/Makefile.am index 7757c68..14aab68 100644 --- a/Makefile.am +++ b/Makefile.am @@ -205,6 +205,7 @@ noinst_LTLIBRARIES += libspinlock.la libspinlock_la_SOURCES = src/base/spinlock.cc \ src/base/spinlock_internal.cc \ $(SPINLOCK_INCLUDES) +libspinlock_la_LIBADD = -lsynchronization LIBSPINLOCK = libwindows.la libspinlock.la libsysinfo.la liblogging.la diff --git a/src/base/spinlock_win32-inl.h b/src/base/spinlock_win32-inl.h index d511999..5f76a8b 100644 --- a/src/base/spinlock_win32-inl.h +++ b/src/base/spinlock_win32-inl.h @@ -35,19 +35,28 @@ #include +#ifdef _MSC_VER +# pragma comment(lib, "Synchronization.lib") +#endif + namespace base { namespace internal { void SpinLockDelay(std::atomic *w, int32 value, int loop) { - if (loop == 0) { - } else if (loop == 1) { - Sleep(0); - } else { - Sleep(base::internal::SuggestedDelayNS(loop) / 1000000); + if (loop != 0) { + auto wait_ns = static_cast(base::internal::SuggestedDelayNS(loop)) * 16; + auto wait_ms = wait_ns / 1000000; + + WaitOnAddress(w, &value, 4, static_cast(wait_ms)); } } void SpinLockWake(std::atomic *w, bool all) { + if (all) { + WakeByAddressAll((void*)w); + } else { + WakeByAddressSingle((void*)w); + } } } // namespace internal