Add a more performant SpinLockDelay implementation for Windows based on WaitOnAddress and friends

This commit is contained in:
Lennox Ho 2023-09-19 14:53:16 +08:00
parent fd0fabe183
commit 589d416977
3 changed files with 18 additions and 5 deletions

View File

@ -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

View File

@ -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

View File

@ -35,19 +35,28 @@
#include <windows.h>
#ifdef _MSC_VER
# pragma comment(lib, "Synchronization.lib")
#endif
namespace base {
namespace internal {
void SpinLockDelay(std::atomic<int> *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<uint64_t>(base::internal::SuggestedDelayNS(loop)) * 16;
auto wait_ms = wait_ns / 1000000;
WaitOnAddress(w, &value, 4, static_cast<DWORD>(wait_ms));
}
}
void SpinLockWake(std::atomic<int> *w, bool all) {
if (all) {
WakeByAddressAll((void*)w);
} else {
WakeByAddressSingle((void*)w);
}
}
} // namespace internal