From 183ae52b226898cc34aa51d4153cf0c006212a8a Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Sun, 22 Nov 2020 01:00:46 +0000 Subject: [PATCH] libstdc++: make atomic waiting depend on gthreads or futexes libstdc++-v3/ChangeLog: * include/bits/atomic_wait.h: Do not define anything unless gthreads or futexes are available. * include/bits/atomic_timed_wait.h: Likewise. * include/bits/semaphore_base.h: Likewise. * include/std/semaphore: Likewise. * include/bits/atomic_base.h (atomic_flag::wait) (atomic_flag::notify_one, atomic_flag::notify_all) (__atomic_base::wait, __atomic_base::notify_one) (__atomic_base::notify_all, __atomic_base::wait) (__atomic_base::notify_one, __atomic_base::notify_all) (__atomic_impl::wait, __atomic_impl::notify_one) (__atomic_impl::notify_all, __atomic_float::wait) (__atomic_float::notify_one, __atomic_float::notify_all) (__atomic_ref::wait, __atomic_ref::notify_one) (__atomic_ref::notify_all): Only define if gthreads or futexes are available. * include/std/atomic (atomic::wait, atomic::notify_one) (atomic::notify_all): Likewise. * include/std/version (__cpp_lib_semaphore): Define conditionally. --- libstdc++-v3/include/bits/atomic_base.h | 18 +++ libstdc++-v3/include/bits/atomic_timed_wait.h | 4 +- libstdc++-v3/include/bits/atomic_wait.h | 16 ++- libstdc++-v3/include/bits/semaphore_base.h | 126 +++++++++--------- libstdc++-v3/include/std/atomic | 10 +- libstdc++-v3/include/std/semaphore | 7 +- libstdc++-v3/include/std/version | 4 +- 7 files changed, 111 insertions(+), 74 deletions(-) diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h index 7de02f16997..d7db8612889 100644 --- a/libstdc++-v3/include/bits/atomic_base.h +++ b/libstdc++-v3/include/bits/atomic_base.h @@ -230,6 +230,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __v == __GCC_ATOMIC_TEST_AND_SET_TRUEVAL; } +#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX _GLIBCXX_ALWAYS_INLINE void wait(bool __old, memory_order __m = memory_order_seq_cst) const noexcept @@ -252,6 +253,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { std::__atomic_notify(&_M_i, true); } // TODO add const volatile overload +#endif // GTHREADS || LINUX_FUTEX #endif // C++20 _GLIBCXX_ALWAYS_INLINE void @@ -603,6 +605,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } #if __cplusplus > 201703L +#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX _GLIBCXX_ALWAYS_INLINE void wait(__int_type __old, memory_order __m = memory_order_seq_cst) const noexcept @@ -625,6 +628,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { std::__atomic_notify(&_M_i, true); } // TODO add const volatile overload +#endif // GTHREADS || LINUX_FUTEX #endif // C++2a _GLIBCXX_ALWAYS_INLINE __int_type @@ -897,6 +901,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } #if __cplusplus > 201703L +#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX _GLIBCXX_ALWAYS_INLINE void wait(__pointer_type __old, memory_order __m = memory_order_seq_cst) noexcept @@ -919,6 +924,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { std::__atomic_notify(&_M_p, true); } // TODO add const volatile overload +#endif // GTHREADS || LINUX_FUTEX #endif // C++2a _GLIBCXX_ALWAYS_INLINE __pointer_type @@ -1010,6 +1016,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } #if __cplusplus > 201703L +#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX template _GLIBCXX_ALWAYS_INLINE void wait(const _Tp* __ptr, _Val<_Tp> __old, @@ -1034,6 +1041,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { std::__atomic_notify(__ptr, true); } // TODO add const volatile overload +#endif // GTHREADS || LINUX_FUTEX #endif // C++2a template @@ -1289,6 +1297,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __cmpexch_failure_order(__order)); } +#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX _GLIBCXX_ALWAYS_INLINE void wait(_Fp __old, memory_order __m = memory_order_seq_cst) const noexcept { __atomic_impl::wait(&_M_fp, __old, __m); } @@ -1306,6 +1315,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { __atomic_impl::notify_all(&_M_fp); } // TODO add const volatile overload +#endif // GTHREADS || LINUX_FUTEX value_type fetch_add(value_type __i, @@ -1444,6 +1454,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __cmpexch_failure_order(__order)); } +#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX _GLIBCXX_ALWAYS_INLINE void wait(_Tp __old, memory_order __m = memory_order_seq_cst) const noexcept { __atomic_impl::wait(_M_ptr, __old, __m); } @@ -1461,6 +1472,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { __atomic_impl::notify_all(_M_ptr); } // TODO add const volatile overload +#endif // GTHREADS || LINUX_FUTEX private: _Tp* _M_ptr; @@ -1557,6 +1569,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __cmpexch_failure_order(__order)); } +#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX _GLIBCXX_ALWAYS_INLINE void wait(_Tp __old, memory_order __m = memory_order_seq_cst) const noexcept { __atomic_impl::wait(_M_ptr, __old, __m); } @@ -1574,6 +1587,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { __atomic_impl::notify_all(_M_ptr); } // TODO add const volatile overload +#endif // GTHREADS || LINUX_FUTEX value_type fetch_add(value_type __i, @@ -1730,6 +1744,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __cmpexch_failure_order(__order)); } +#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX _GLIBCXX_ALWAYS_INLINE void wait(_Fp __old, memory_order __m = memory_order_seq_cst) const noexcept { __atomic_impl::wait(_M_ptr, __old, __m); } @@ -1747,6 +1762,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { __atomic_impl::notify_all(_M_ptr); } // TODO add const volatile overload +#endif // GTHREADS || LINUX_FUTEX value_type fetch_add(value_type __i, @@ -1857,6 +1873,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __cmpexch_failure_order(__order)); } +#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX _GLIBCXX_ALWAYS_INLINE void wait(_Tp __old, memory_order __m = memory_order_seq_cst) const noexcept { __atomic_impl::wait(_M_ptr, __old, __m); } @@ -1874,6 +1891,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { __atomic_impl::notify_all(_M_ptr); } // TODO add const volatile overload +#endif // GTHREADS || LINUX_FUTEX _GLIBCXX_ALWAYS_INLINE value_type fetch_add(difference_type __d, diff --git a/libstdc++-v3/include/bits/atomic_timed_wait.h b/libstdc++-v3/include/bits/atomic_timed_wait.h index 405f7e93ca8..b13f8aa1286 100644 --- a/libstdc++-v3/include/bits/atomic_timed_wait.h +++ b/libstdc++-v3/include/bits/atomic_timed_wait.h @@ -33,6 +33,7 @@ #pragma GCC system_header #include +#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX #include #include @@ -286,4 +287,5 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } _GLIBCXX_END_NAMESPACE_VERSION } // namespace std -#endif +#endif // GTHREADS || LINUX_FUTEX +#endif // _GLIBCXX_ATOMIC_TIMED_WAIT_H diff --git a/libstdc++-v3/include/bits/atomic_wait.h b/libstdc++-v3/include/bits/atomic_wait.h index 7b2682a577e..a40cff124d7 100644 --- a/libstdc++-v3/include/bits/atomic_wait.h +++ b/libstdc++-v3/include/bits/atomic_wait.h @@ -33,6 +33,7 @@ #pragma GCC system_header #include +#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX #include #include #include @@ -106,7 +107,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } } - template + template void __platform_notify(const _Tp* __addr, bool __all) noexcept { @@ -175,11 +176,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION bool _M_waiting() const noexcept - { - __platform_wait_t __res; - __atomic_load(&_M_wait, &__res, __ATOMIC_ACQUIRE); - return __res; - } + { + __platform_wait_t __res; + __atomic_load(&_M_wait, &__res, __ATOMIC_ACQUIRE); + return __res; + } void _M_notify(bool __all) noexcept @@ -305,4 +306,5 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } _GLIBCXX_END_NAMESPACE_VERSION } // namespace std -#endif +#endif // GTHREADS || LINUX_FUTEX +#endif // _GLIBCXX_ATOMIC_WAIT_H diff --git a/libstdc++-v3/include/bits/semaphore_base.h b/libstdc++-v3/include/bits/semaphore_base.h index 78a0b6ba26e..5e29d3783fe 100644 --- a/libstdc++-v3/include/bits/semaphore_base.h +++ b/libstdc++-v3/include/bits/semaphore_base.h @@ -33,6 +33,7 @@ #pragma GCC system_header #include +#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX #include #include @@ -161,30 +162,68 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION noexcept { return _M_try_acquire_until(__clock_t::now() + __rtime); } - private: - sem_t _M_semaphore; - }; + private: + sem_t _M_semaphore; + }; #endif // _GLIBCXX_HAVE_POSIX_SEMAPHORE - template - struct __atomic_semaphore + template + struct __atomic_semaphore + { + static_assert(std::is_integral_v<_Tp>); + static_assert(__gnu_cxx::__int_traits<_Tp>::__max + <= __gnu_cxx::__int_traits::__max); + static constexpr ptrdiff_t _S_max = __gnu_cxx::__int_traits<_Tp>::__max; + + explicit __atomic_semaphore(_Tp __count) noexcept + : _M_counter(__count) { - static_assert(std::is_integral_v<_Tp>); - static_assert(__gnu_cxx::__int_traits<_Tp>::__max - <= __gnu_cxx::__int_traits::__max); - static constexpr ptrdiff_t _S_max = __gnu_cxx::__int_traits<_Tp>::__max; + __glibcxx_assert(__count >= 0 && __count <= _S_max); + } - explicit __atomic_semaphore(_Tp __count) noexcept - : _M_counter(__count) - { - __glibcxx_assert(__count >= 0 && __count <= _S_max); - } + __atomic_semaphore(const __atomic_semaphore&) = delete; + __atomic_semaphore& operator=(const __atomic_semaphore&) = delete; - __atomic_semaphore(const __atomic_semaphore&) = delete; - __atomic_semaphore& operator=(const __atomic_semaphore&) = delete; + _GLIBCXX_ALWAYS_INLINE void + _M_acquire() noexcept + { + auto const __pred = [this] + { + auto __old = __atomic_impl::load(&this->_M_counter, + memory_order::acquire); + if (__old == 0) + return false; + return __atomic_impl::compare_exchange_strong(&this->_M_counter, + __old, __old - 1, + memory_order::acquire, + memory_order::release); + }; + auto __old = __atomic_impl::load(&_M_counter, memory_order_relaxed); + std::__atomic_wait(&_M_counter, __old, __pred); + } + + bool + _M_try_acquire() noexcept + { + auto __old = __atomic_impl::load(&_M_counter, memory_order::acquire); + auto const __pred = [this, __old] + { + if (__old == 0) + return false; + + auto __prev = __old; + return __atomic_impl::compare_exchange_weak(&this->_M_counter, + __prev, __prev - 1, + memory_order::acquire, + memory_order::release); + }; + return std::__atomic_spin(__pred); + } - _GLIBCXX_ALWAYS_INLINE void - _M_acquire() noexcept + template + _GLIBCXX_ALWAYS_INLINE bool + _M_try_acquire_until(const chrono::time_point<_Clock, + _Duration>& __atime) noexcept { auto const __pred = [this] { @@ -193,51 +232,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__old == 0) return false; return __atomic_impl::compare_exchange_strong(&this->_M_counter, - __old, __old - 1, - memory_order::acquire, - memory_order::release); - }; - auto __old = __atomic_impl::load(&_M_counter, memory_order_relaxed); - std::__atomic_wait(&_M_counter, __old, __pred); - } - - bool - _M_try_acquire() noexcept - { - auto __old = __atomic_impl::load(&_M_counter, memory_order::acquire); - auto const __pred = [this, __old] - { - if (__old == 0) - return false; - - auto __prev = __old; - return __atomic_impl::compare_exchange_weak(&this->_M_counter, - __prev, __prev - 1, - memory_order::acquire, - memory_order::release); + __old, __old - 1, + memory_order::acquire, + memory_order::release); }; - return std::__atomic_spin(__pred); - } - template - _GLIBCXX_ALWAYS_INLINE bool - _M_try_acquire_until(const chrono::time_point<_Clock, - _Duration>& __atime) noexcept - { - auto const __pred = [this] - { - auto __old = __atomic_impl::load(&this->_M_counter, - memory_order::acquire); - if (__old == 0) - return false; - return __atomic_impl::compare_exchange_strong(&this->_M_counter, - __old, __old - 1, - memory_order::acquire, - memory_order::release); - }; - - auto __old = __atomic_impl::load(&_M_counter, memory_order_relaxed); - return __atomic_wait_until(&_M_counter, __old, __pred, __atime); + auto __old = __atomic_impl::load(&_M_counter, memory_order_relaxed); + return __atomic_wait_until(&_M_counter, __old, __pred, __atime); } template @@ -299,4 +300,5 @@ template _GLIBCXX_END_NAMESPACE_VERSION } // namespace std -#endif +#endif // GTHREADS || LINUX_FUTEX +#endif // _GLIBCXX_SEMAPHORE_BASE_H diff --git a/libstdc++-v3/include/std/atomic b/libstdc++-v3/include/std/atomic index 5afe33b41d9..fe4de244f85 100644 --- a/libstdc++-v3/include/std/atomic +++ b/libstdc++-v3/include/std/atomic @@ -165,6 +165,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return _M_base.compare_exchange_strong(__i1, __i2, __m); } #if __cplusplus > 201703L +#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX void wait(bool __old, memory_order __m = memory_order_seq_cst) const noexcept { _M_base.wait(__old, __m); } @@ -176,6 +177,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void notify_all() const noexcept { _M_base.notify_all(); } +#endif // GTHREADS || LINUX_FUTEX #endif }; @@ -379,6 +381,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __cmpexch_failure_order(__m)); } #if __cplusplus > 201703L +#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX void wait(_Tp __old, memory_order __m = memory_order_seq_cst) const noexcept { std::__atomic_wait(&_M_i, __old, @@ -399,7 +402,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void notify_all() const noexcept { std::__atomic_notify(&_M_i, true); } -#endif +#endif // GTHREADS || LINUX_FUTEX +#endif // C++20 }; #undef _GLIBCXX20_INIT @@ -640,6 +644,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } #if __cplusplus > 201703L +#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX void wait(__pointer_type __old, memory_order __m = memory_order_seq_cst) noexcept { _M_b.wait(__old, __m); } @@ -651,6 +656,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void notify_all() const noexcept { _M_b.notify_all(); } +#endif // GTHREADS || LINUX_FUTEX #endif __pointer_type fetch_add(ptrdiff_t __d, @@ -1406,6 +1412,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus > 201703L +#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX template inline void atomic_wait(const atomic<_Tp>* __a, @@ -1429,6 +1436,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION atomic_notify_all(atomic<_Tp>* __a) noexcept { __a->notify_all(); } +#endif // GTHREADS || LINUX_FUTEX #endif // C++2a // Function templates for atomic_integral and atomic_pointer operations only. diff --git a/libstdc++-v3/include/std/semaphore b/libstdc++-v3/include/std/semaphore index b4facde4ea1..f4b83ab6ae3 100644 --- a/libstdc++-v3/include/std/semaphore +++ b/libstdc++-v3/include/std/semaphore @@ -32,14 +32,16 @@ #pragma GCC system_header #if __cplusplus > 201703L -#define __cpp_lib_semaphore 201907L #include +#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX #include namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION +#define __cpp_lib_semaphore 201907L + template::__max> class counting_semaphore @@ -88,5 +90,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using binary_semaphore = std::counting_semaphore<1>; _GLIBCXX_END_NAMESPACE_VERSION } // namespace -#endif // __cplusplus > 201703L +#endif // GTHREADS || LINUX_FUTEX +#endif // C++20 #endif // _GLIBCXX_SEMAPHORE diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version index 42ed7cb74d3..cf0454dbaf8 100644 --- a/libstdc++-v3/include/std/version +++ b/libstdc++-v3/include/std/version @@ -226,7 +226,9 @@ #if __cpp_lib_concepts # define __cpp_lib_ranges 201911L #endif -#define __cpp_lib_semaphore 201907L +#if defined _GLIBCXX_HAS_GTHREADS || _GLIBCXX_HAVE_LINUX_FUTEX +# define __cpp_lib_semaphore 201907L +#endif #define __cpp_lib_shift 201806L #if __cpp_lib_concepts # define __cpp_lib_span 202002L -- 2.30.2