[libcxx-commits] [libcxx] [libc++] Improve performance of std::atomic_flag on Windows (PR #163524)

Roger Sanders via libcxx-commits libcxx-commits at lists.llvm.org
Wed Oct 15 02:28:02 PDT 2025


================
@@ -101,6 +105,37 @@ static void __libcpp_platform_wake_by_address(__cxx_atomic_contention_t const vo
   _umtx_op(const_cast<__cxx_atomic_contention_t*>(__ptr), UMTX_OP_WAKE, __notify_one ? 1 : INT_MAX, nullptr, nullptr);
 }
 
+#elif defined(_WIN32)
+
+static void
+__libcpp_platform_wait_on_address(__cxx_atomic_contention_t const volatile* __ptr, __cxx_contention_t __val) {
+  static auto pWaitOnAddress = reinterpret_cast<BOOL(WINAPI*)(volatile void*, PVOID, SIZE_T, DWORD)>(
+      GetProcAddress(GetModuleHandleW(L"api-ms-win-core-synch-l1-2-0.dll"), "WaitOnAddress"));
+  if (pWaitOnAddress != nullptr) {
+    pWaitOnAddress(const_cast<__cxx_atomic_contention_t*>(__ptr), &__val, sizeof(__val), INFINITE);
+  } else {
+    __libcpp_thread_poll_with_backoff(
+        [=]() -> bool { return !__cxx_nonatomic_compare_equal(__cxx_atomic_load(__ptr, memory_order_relaxed), __val); },
+        __libcpp_timed_backoff_policy());
+  }
+}
+
+static void __libcpp_platform_wake_by_address(__cxx_atomic_contention_t const volatile* __ptr, bool __notify_one) {
+  if (__notify_one) {
+    static auto pWakeByAddressSingle = reinterpret_cast<void(WINAPI*)(PVOID)>(
+        GetProcAddress(GetModuleHandleW(L"api-ms-win-core-synch-l1-2-0.dll"), "WakeByAddressSingle"));
+    if (pWakeByAddressSingle != nullptr) {
+      pWakeByAddressSingle(const_cast<__cxx_atomic_contention_t*>(__ptr));
+    }
+  } else {
+    static auto pWakeByAddressAll = reinterpret_cast<void(WINAPI*)(PVOID)>(
+        GetProcAddress(GetModuleHandleW(L"api-ms-win-core-synch-l1-2-0.dll"), "WakeByAddressAll"));
+    if (pWakeByAddressAll != nullptr) {
+      pWakeByAddressAll(const_cast<__cxx_atomic_contention_t*>(__ptr));
----------------
RogerSanders wrote:

The fallback implementation (that Windows was using before) is a no-op. Since the thread can't actually be woken (it's just in a spin loop with backoff, checking an atomic for when the flag changes), the correct fallback here is to do nothing, as waiting threads won't be listening for wake events where these functions aren't available.

https://github.com/llvm/llvm-project/pull/163524


More information about the libcxx-commits mailing list