[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