Skip to content

Commit bc11102

Browse files
committed
exp
1 parent 526740f commit bc11102

File tree

5 files changed

+49
-38
lines changed

5 files changed

+49
-38
lines changed

libcxx/include/__thread/poll_with_backoff.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,13 @@ static _LIBCPP_CONSTEXPR const int __libcpp_polling_count = 64;
3131
//
3232
// - __max_elapsed is the maximum duration to try polling for. If the maximum duration is exceeded,
3333
// the polling loop will return false to report a timeout.
34-
template<class _Fn, class _BFn>
34+
template<class _Atp, class _Fn, class _Mo, class _BFn>
3535
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_HIDE_FROM_ABI
36-
bool __libcpp_thread_poll_with_backoff(_Fn&& __f, _BFn&& __bf, chrono::nanoseconds __max_elapsed = chrono::nanoseconds::zero()) {
36+
bool __libcpp_thread_poll_with_backoff(_Atp *__a, _Fn&& __f, _Mo __order, _BFn&& __bf, chrono::nanoseconds __max_elapsed = chrono::nanoseconds::zero()) {
3737
auto const __start = chrono::high_resolution_clock::now();
3838
for (int __count = 0;;) {
39-
if (__f())
39+
auto __current_val = __cxx_atomic_load(__a, __order);
40+
if (__f(__current_val))
4041
return true; // _Fn completion means success
4142
if (__count < __libcpp_polling_count) {
4243
__count += 1;
@@ -45,7 +46,7 @@ bool __libcpp_thread_poll_with_backoff(_Fn&& __f, _BFn&& __bf, chrono::nanosecon
4546
chrono::nanoseconds const __elapsed = chrono::high_resolution_clock::now() - __start;
4647
if (__max_elapsed != chrono::nanoseconds::zero() && __max_elapsed < __elapsed)
4748
return false; // timeout failure
48-
if (__bf(__elapsed))
49+
if (__bf(__elapsed, __current_val))
4950
return false; // _BFn completion means failure
5051
}
5152
}

libcxx/include/atomic

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1482,14 +1482,28 @@ template <class _Atp, class _Fn>
14821482
struct __libcpp_atomic_wait_backoff_impl {
14831483
_Atp* __a;
14841484
_Fn __test_fn;
1485+
memory_order __order;
1486+
_LIBCPP_AVAILABILITY_SYNC
1487+
_LIBCPP_INLINE_VISIBILITY bool __use_directly(void const volatile*) const { return false; }
14851488
_LIBCPP_AVAILABILITY_SYNC
1486-
_LIBCPP_INLINE_VISIBILITY bool operator()(chrono::nanoseconds __elapsed) const
1489+
_LIBCPP_INLINE_VISIBILITY bool __use_directly(__cxx_atomic_contention_t const volatile*) const { return true; }
1490+
template <class _Tp>
1491+
_LIBCPP_INLINE_VISIBILITY bool operator()(chrono::nanoseconds __elapsed, _Tp __current_val) const
14871492
{
14881493
if(__elapsed > chrono::microseconds(64))
14891494
{
1490-
auto const __monitor = __libcpp_atomic_monitor(__a);
1491-
if(__test_fn())
1492-
return true;
1495+
__cxx_contention_t __monitor;
1496+
1497+
if (!__use_directly(__a))
1498+
{
1499+
__monitor = __libcpp_atomic_monitor(__a);
1500+
__current_val = __cxx_atomic_load(__a, __order);
1501+
if (__test_fn(__current_val))
1502+
return true;
1503+
}
1504+
else
1505+
__monitor = __current_val;
1506+
14931507
__libcpp_atomic_wait(__a, __monitor);
14941508
}
14951509
else if(__elapsed > chrono::microseconds(4))
@@ -1502,10 +1516,10 @@ struct __libcpp_atomic_wait_backoff_impl {
15021516

15031517
template <class _Atp, class _Fn>
15041518
_LIBCPP_AVAILABILITY_SYNC
1505-
_LIBCPP_INLINE_VISIBILITY bool __cxx_atomic_wait(_Atp* __a, _Fn && __test_fn)
1519+
_LIBCPP_INLINE_VISIBILITY bool __cxx_atomic_wait_fn(_Atp* __a, _Fn && __test_fn, memory_order __order)
15061520
{
1507-
__libcpp_atomic_wait_backoff_impl<_Atp, typename decay<_Fn>::type> __backoff_fn = {__a, __test_fn};
1508-
return __libcpp_thread_poll_with_backoff(__test_fn, __backoff_fn);
1521+
__libcpp_atomic_wait_backoff_impl<_Atp, typename decay<_Fn>::type> __backoff_fn = {__a, __test_fn, __order};
1522+
return __libcpp_thread_poll_with_backoff(__a, __test_fn, __order, __backoff_fn);
15091523
}
15101524

15111525
#else // _LIBCPP_HAS_NO_PLATFORM_WAIT
@@ -1515,14 +1529,14 @@ _LIBCPP_INLINE_VISIBILITY void __cxx_atomic_notify_all(__cxx_atomic_impl<_Tp> co
15151529
template <class _Tp>
15161530
_LIBCPP_INLINE_VISIBILITY void __cxx_atomic_notify_one(__cxx_atomic_impl<_Tp> const volatile*) { }
15171531
template <class _Atp, class _Fn>
1518-
_LIBCPP_INLINE_VISIBILITY bool __cxx_atomic_wait(_Atp*, _Fn && __test_fn)
1532+
_LIBCPP_INLINE_VISIBILITY bool __cxx_atomic_wait_fn(_Atp* __a, _Fn && __test_fn, memory_order __order)
15191533
{
15201534
#if defined(_LIBCPP_HAS_NO_THREADS)
15211535
using _Policy = __spinning_backoff_policy;
15221536
#else
15231537
using _Policy = __libcpp_timed_backoff_policy;
15241538
#endif
1525-
return __libcpp_thread_poll_with_backoff(__test_fn, _Policy());
1539+
return __libcpp_thread_poll_with_backoff(__a, __test_fn, __order, _Policy());
15261540
}
15271541

15281542
#endif // _LIBCPP_HAS_NO_PLATFORM_WAIT
@@ -1531,19 +1545,18 @@ template <class _Atp, class _Tp>
15311545
struct __cxx_atomic_wait_test_fn_impl {
15321546
_Atp* __a;
15331547
_Tp __val;
1534-
memory_order __order;
1535-
_LIBCPP_INLINE_VISIBILITY bool operator()() const
1548+
_LIBCPP_INLINE_VISIBILITY bool operator()(_Tp& __current_val) const
15361549
{
1537-
return !__cxx_nonatomic_compare_equal(__cxx_atomic_load(__a, __order), __val);
1550+
return !__cxx_nonatomic_compare_equal(__current_val, __val);
15381551
}
15391552
};
15401553

15411554
template <class _Atp, class _Tp>
15421555
_LIBCPP_AVAILABILITY_SYNC
15431556
_LIBCPP_INLINE_VISIBILITY bool __cxx_atomic_wait(_Atp* __a, _Tp const __val, memory_order __order)
15441557
{
1545-
__cxx_atomic_wait_test_fn_impl<_Atp, _Tp> __test_fn = {__a, __val, __order};
1546-
return __cxx_atomic_wait(__a, __test_fn);
1558+
__cxx_atomic_wait_test_fn_impl<_Atp, _Tp> __test_fn = {__a, __val};
1559+
return __cxx_atomic_wait_fn(__a, __test_fn, __order);
15471560
}
15481561

15491562
// general atomic<T>

libcxx/include/latch

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,10 @@ public:
9090
inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
9191
void wait() const
9292
{
93-
auto const __test_fn = [=]() -> bool {
94-
return try_wait();
93+
auto const __test_fn = [=](ptrdiff_t& __val) -> bool {
94+
return 0 == __val;
9595
};
96-
__cxx_atomic_wait(&__a.__a_, __test_fn);
96+
__cxx_atomic_wait_fn(&__a.__a_, __test_fn, memory_order_acquire);
9797
}
9898
inline _LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
9999
void arrive_and_wait(ptrdiff_t __update = 1)

libcxx/include/semaphore

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -85,21 +85,24 @@ public:
8585
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
8686
void release(ptrdiff_t __update = 1)
8787
{
88-
if(0 < __a.fetch_add(__update, memory_order_release))
89-
;
90-
else if(__update > 1)
88+
__a.fetch_add(__update, memory_order_release);
89+
if(__update > 1)
9190
__a.notify_all();
9291
else
9392
__a.notify_one();
9493
}
9594
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
9695
void acquire()
9796
{
98-
auto const __test_fn = [this]() -> bool {
99-
auto __old = __a.load(memory_order_relaxed);
100-
return (__old != 0) && __a.compare_exchange_strong(__old, __old - 1, memory_order_acquire, memory_order_relaxed);
97+
auto const __test_fn = [this](ptrdiff_t& __old) -> bool {
98+
while (true) {
99+
if (__old == 0)
100+
return false;
101+
if (__a.compare_exchange_weak(__old, __old - 1, memory_order_acquire, memory_order_relaxed))
102+
return true;
103+
}
101104
};
102-
__cxx_atomic_wait(&__a.__a_, __test_fn);
105+
__cxx_atomic_wait_fn(&__a.__a_, __test_fn, memory_order_relaxed);
103106
}
104107
template <class Rep, class Period>
105108
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
@@ -113,11 +116,11 @@ public:
113116
_LIBCPP_AVAILABILITY_SYNC _LIBCPP_INLINE_VISIBILITY
114117
bool try_acquire()
115118
{
116-
auto __old = __a.load(memory_order_acquire);
119+
auto __old = __a.load(memory_order_relaxed);
117120
while (true) {
118121
if (__old == 0)
119122
return false;
120-
if (__a.compare_exchange_strong(__old, __old - 1, memory_order_acquire, memory_order_relaxed))
123+
if (__a.compare_exchange_weak(__old, __old - 1, memory_order_acquire, memory_order_relaxed))
121124
return true;
122125
}
123126
}

libcxx/src/atomic.cpp

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -117,12 +117,6 @@ static void __libcpp_contention_notify(__cxx_atomic_contention_t volatile* __con
117117
// We only call 'wake' if we consumed a contention bit here.
118118
__libcpp_platform_wake_by_address(__platform_state, __notify_one);
119119
}
120-
static __cxx_contention_t __libcpp_contention_monitor_for_wait(__cxx_atomic_contention_t volatile* __contention_state,
121-
__cxx_atomic_contention_t const volatile* __platform_state)
122-
{
123-
// We will monitor this value.
124-
return __cxx_atomic_load(__platform_state, memory_order_acquire);
125-
}
126120
static void __libcpp_contention_wait(__cxx_atomic_contention_t volatile* __contention_state,
127121
__cxx_atomic_contention_t const volatile* __platform_state,
128122
__cxx_contention_t __old_value)
@@ -155,7 +149,7 @@ _LIBCPP_EXPORTED_FROM_ABI
155149
__cxx_contention_t __libcpp_atomic_monitor(void const volatile* __location)
156150
{
157151
auto const __entry = __libcpp_contention_state(__location);
158-
return __libcpp_contention_monitor_for_wait(&__entry->__contention_state, &__entry->__platform_state);
152+
return __cxx_atomic_load(&__entry->__platform_state, memory_order_acquire);
159153
}
160154
_LIBCPP_EXPORTED_FROM_ABI
161155
void __libcpp_atomic_wait(void const volatile* __location, __cxx_contention_t __old_value)
@@ -180,7 +174,7 @@ void __cxx_atomic_notify_all(__cxx_atomic_contention_t const volatile* __locatio
180174
_LIBCPP_EXPORTED_FROM_ABI
181175
__cxx_contention_t __libcpp_atomic_monitor(__cxx_atomic_contention_t const volatile* __location)
182176
{
183-
return __libcpp_contention_monitor_for_wait(&__libcpp_contention_state(__location)->__contention_state, __location);
177+
return __cxx_atomic_load(__location, memory_order_acquire);
184178
}
185179
_LIBCPP_EXPORTED_FROM_ABI
186180
void __libcpp_atomic_wait(__cxx_atomic_contention_t const volatile* __location, __cxx_contention_t __old_value)

0 commit comments

Comments
 (0)