[libcxx-commits] [libcxx] [libc++] atomic_wait refactor experiment (PR #85086)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Wed Mar 13 10:14:03 PDT 2024


================
@@ -120,40 +122,83 @@ static __libcpp_contention_table_entry* __libcpp_contention_state(void const vol
 /* Given an atomic to track contention and an atomic to actually wait on, which may be
    the same atomic, we try to detect contention to avoid spuriously calling the platform. */
 
-static void __libcpp_contention_notify(__cxx_atomic_contention_t volatile* __contention_state,
+static void __libcpp_contention_notify(__cxx_atomic_contention_t volatile* __waiter_count,
                                        __cxx_atomic_contention_t const volatile* __platform_state,
                                        bool __notify_one) {
-  if (0 != __cxx_atomic_load(__contention_state, memory_order_seq_cst))
+  if (0 != __cxx_atomic_load(__waiter_count, memory_order_seq_cst))
     // We only call 'wake' if we consumed a contention bit here.
     __libcpp_platform_wake_by_address(__platform_state, __notify_one);
 }
-static __cxx_contention_t
-__libcpp_contention_monitor_for_wait(__cxx_atomic_contention_t volatile* /*__contention_state*/,
-                                     __cxx_atomic_contention_t const volatile* __platform_state) {
-  // We will monitor this value.
-  return __cxx_atomic_load(__platform_state, memory_order_acquire);
-}
-static void __libcpp_contention_wait(__cxx_atomic_contention_t volatile* __contention_state,
+static void __libcpp_contention_wait(__cxx_atomic_contention_t volatile* __waiter_count,
                                      __cxx_atomic_contention_t const volatile* __platform_state,
                                      __cxx_contention_t __old_value) {
-  __cxx_atomic_fetch_add(__contention_state, __cxx_contention_t(1), memory_order_seq_cst);
+  __cxx_atomic_fetch_add(__waiter_count, __cxx_contention_t(1), memory_order_seq_cst);
   // We sleep as long as the monitored value hasn't changed.
   __libcpp_platform_wait_on_address(__platform_state, __old_value);
-  __cxx_atomic_fetch_sub(__contention_state, __cxx_contention_t(1), memory_order_release);
+  __cxx_atomic_fetch_sub(__waiter_count, __cxx_contention_t(1), memory_order_release);
+}
+
+namespace {
+
+_LIBCPP_EXPORTED_FROM_ABI const auto __get_contention_table_entry = &__libcpp_contention_state;
+
+}
+
+_LIBCPP_EXPORTED_FROM_ABI __atomic_waitable_contention_self::__atomic_waitable_contention_self(
+    const volatile __cxx_atomic_contention_t* __contention_address)
+    : __waiter_count_(&__get_contention_table_entry(__contention_address)->__waiter_count()),
+      __platform_state_(__contention_address) {}
+
+_LIBCPP_EXPORTED_FROM_ABI __cxx_contention_t __atomic_waitable_contention_self::__monitor() {
+  return __cxx_atomic_load(__platform_state_, memory_order_acquire);
+}
+
+_LIBCPP_EXPORTED_FROM_ABI void __atomic_waitable_contention_self::__wait(__cxx_contention_t __old_value) {
+  __libcpp_contention_wait(__waiter_count_, __platform_state_, __old_value);
+}
+
+_LIBCPP_EXPORTED_FROM_ABI void __atomic_waitable_contention_self::__notify_one() {
+  __libcpp_contention_notify(__waiter_count_, __platform_state_, true);
+}
+
+_LIBCPP_EXPORTED_FROM_ABI void __atomic_waitable_contention_self::__notify_all() {
+  __libcpp_contention_notify(__waiter_count_, __platform_state_, false);
+}
+
+_LIBCPP_EXPORTED_FROM_ABI __atomic_waitable_contention_global::__atomic_waitable_contention_global(
----------------
ldionne wrote:

It seems to me that we really need two tables here. First, we have a table containing just waiter counts for the `self` case, and we also have a table containing `{waiter-count, platform-state}`s for the `global` case. Otherwise, we seem to be reusing waiter counts across the `self` and `global` implementations for different platform-states.

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


More information about the libcxx-commits mailing list