https://gcc.gnu.org/g:3e9fff1b7f9a31e6bc635880b09cbc32f8be353d
commit r16-999-g3e9fff1b7f9a31e6bc635880b09cbc32f8be353d Author: Jonathan Wakely <jwak...@redhat.com> Date: Wed Jan 15 09:05:28 2025 +0000 libstdc++: Rewrite std::counting_semaphore base class [PR118494] Remove __platform_semaphore. Replace __atomic_semaphore with __semaphore_base<bool> and change its counter to be ptrdiff_t when the count doesn't fit in __platform_wait_t (PR 118494). Make the std::counting_semaphore constructor constexpr to support constant initialization (PR 110854). Add precondition checks to the constructor and release member functions (PR 98749). libstdc++-v3/ChangeLog: PR libstdc++/118494 PR libstdc++/110854 PR libstdc++/98749 * acinclude.m4 (GLIBCXX_CHECK_GTHREADS): Remove checks for sem_timedwait. Do not define _GLIBCXX_HAVE_POSIX_SEMAPHORE. * config.h.in: Regenerate. * configure: Regenerate. * include/bits/semaphore_base.h (__platform_semaphore): Remove. (__atomic_semaphore): Replace with __semaphore_base<bool> and make type of _M_count depend on template parameter. Fix _S_max constant to use correct type. (__semaphore_base::_M_try_acquire): Qualify to avoid ADL. (__semaphore_base::_M_release): Return old value. Remove FIXME comment. (__semaphore_impl): Replace typedef with alias template. * include/bits/version.def (semaphore): Do not depend on _GLIBCXX_HAVE_POSIX_SEMAPHORE. * include/bits/version.h: Regenerate. * include/std/semaphore (semaphore): Adjust type of _M_sem member. Add constexpr to constructor. Add assertions to (semaphore::semaphore(ptrdiff_t)): Add constexpr. Add assertion for precondition. (semaphore::release): Add assertion using value returned from _M_release. * testsuite/30_threads/semaphore/100806.cc: Increase template argument for std::counting_semaphore, so constructor precondition is met. * testsuite/30_threads/semaphore/cons.cc: New test. * testsuite/30_threads/semaphore/try_acquire_posix.cc: Remove. * testsuite/30_threads/semaphore/platform_try_acquire_for.cc: Removed. Diff: --- libstdc++-v3/acinclude.m4 | 37 ---- libstdc++-v3/config.h.in | 4 - libstdc++-v3/configure | 60 +----- libstdc++-v3/include/bits/semaphore_base.h | 224 +++++---------------- libstdc++-v3/include/bits/version.def | 2 +- libstdc++-v3/include/bits/version.h | 2 +- libstdc++-v3/include/std/semaphore | 32 +-- .../testsuite/30_threads/semaphore/100806.cc | 2 +- .../testsuite/30_threads/semaphore/cons.cc | 7 + .../semaphore/platform_try_acquire_for.cc | 9 - .../30_threads/semaphore/try_acquire_posix.cc | 153 -------------- 11 files changed, 82 insertions(+), 450 deletions(-) diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4 index d1ecb1ad9566..080a4fca9b57 100644 --- a/libstdc++-v3/acinclude.m4 +++ b/libstdc++-v3/acinclude.m4 @@ -4293,43 +4293,6 @@ AC_DEFUN([GLIBCXX_CHECK_GTHREADS], [ fi fi - AC_CHECK_HEADER(semaphore.h, [ - AC_MSG_CHECKING([for POSIX Semaphores and sem_timedwait]) - AC_TRY_COMPILE([ - #include <unistd.h> - #include <semaphore.h> - #include <limits.h> - ], - [ - #if !defined _POSIX_TIMEOUTS || _POSIX_TIMEOUTS <= 0 - # error "POSIX Timeouts option not supported" - #elif !defined _POSIX_SEMAPHORES || _POSIX_SEMAPHORES <= 0 - # error "POSIX Semaphores option not supported" - #else - #if defined SEM_VALUE_MAX - constexpr int sem_value_max = SEM_VALUE_MAX; - #elif defined _POSIX_SEM_VALUE_MAX - constexpr int sem_value_max = _POSIX_SEM_VALUE_MAX; - #else - # error "SEM_VALUE_MAX not available" - #endif - sem_t sem; - sem_init(&sem, 0, sem_value_max); - struct timespec ts = { 0 }; - sem_timedwait(&sem, &ts); - #endif - ], - [ac_have_posix_semaphore=yes], - [ac_have_posix_semaphore=no])], - [ac_have_posix_semaphore=no]) - - if test $ac_have_posix_semaphore = yes ; then - AC_DEFINE(HAVE_POSIX_SEMAPHORE, - 1, - [Define to 1 if POSIX Semaphores with sem_timedwait are available in <semaphore.h>.]) - fi - AC_MSG_RESULT([$ac_have_posix_semaphore]) - CXXFLAGS="$ac_save_CXXFLAGS" AC_LANG_RESTORE ]) diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in index 3dbe00bae508..ffacdabac854 100644 --- a/libstdc++-v3/config.h.in +++ b/libstdc++-v3/config.h.in @@ -314,10 +314,6 @@ /* Define to 1 if you have the `posix_memalign' function. */ #undef HAVE_POSIX_MEMALIGN -/* Define to 1 if POSIX Semaphores with sem_timedwait are available in - <semaphore.h>. */ -#undef HAVE_POSIX_SEMAPHORE - /* Define to 1 if you have the `powf' function. */ #undef HAVE_POWF diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure index d6891e544cfe..69aa246ec7fb 100755 --- a/libstdc++-v3/configure +++ b/libstdc++-v3/configure @@ -51990,64 +51990,6 @@ fi fi fi - ac_fn_cxx_check_header_mongrel "$LINENO" "semaphore.h" "ac_cv_header_semaphore_h" "$ac_includes_default" -if test "x$ac_cv_header_semaphore_h" = xyes; then : - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for POSIX Semaphores and sem_timedwait" >&5 -$as_echo_n "checking for POSIX Semaphores and sem_timedwait... " >&6; } - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - #include <unistd.h> - #include <semaphore.h> - #include <limits.h> - -int -main () -{ - - #if !defined _POSIX_TIMEOUTS || _POSIX_TIMEOUTS <= 0 - # error "POSIX Timeouts option not supported" - #elif !defined _POSIX_SEMAPHORES || _POSIX_SEMAPHORES <= 0 - # error "POSIX Semaphores option not supported" - #else - #if defined SEM_VALUE_MAX - constexpr int sem_value_max = SEM_VALUE_MAX; - #elif defined _POSIX_SEM_VALUE_MAX - constexpr int sem_value_max = _POSIX_SEM_VALUE_MAX; - #else - # error "SEM_VALUE_MAX not available" - #endif - sem_t sem; - sem_init(&sem, 0, sem_value_max); - struct timespec ts = { 0 }; - sem_timedwait(&sem, &ts); - #endif - - ; - return 0; -} -_ACEOF -if ac_fn_cxx_try_compile "$LINENO"; then : - ac_have_posix_semaphore=yes -else - ac_have_posix_semaphore=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -else - ac_have_posix_semaphore=no -fi - - - - if test $ac_have_posix_semaphore = yes ; then - -$as_echo "#define HAVE_POSIX_SEMAPHORE 1" >>confdefs.h - - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_have_posix_semaphore" >&5 -$as_echo "$ac_have_posix_semaphore" >&6; } - CXXFLAGS="$ac_save_CXXFLAGS" ac_ext=c ac_cpp='$CPP $CPPFLAGS' @@ -53601,7 +53543,7 @@ $as_echo "$glibcxx_cv_libbacktrace_atomics" >&6; } CXXFLAGS='-O0 -S' cat > conftest.$ac_ext << EOF -#line 53604 "configure" +#line 53546 "configure" #include <stddef.h> int main() { diff --git a/libstdc++-v3/include/bits/semaphore_base.h b/libstdc++-v3/include/bits/semaphore_base.h index 444a1589fb5a..5b5a1c982317 100644 --- a/libstdc++-v3/include/bits/semaphore_base.h +++ b/libstdc++-v3/include/bits/semaphore_base.h @@ -34,162 +34,44 @@ #pragma GCC system_header #endif +#include <bits/version.h> + +#ifdef __glibcxx_semaphore // C++ >= 20 && hosted && atomic_wait #include <bits/atomic_base.h> #include <bits/chrono.h> -#if __glibcxx_atomic_wait #include <bits/atomic_timed_wait.h> #include <ext/numeric_traits.h> -#endif // __cpp_lib_atomic_wait - -#ifdef _GLIBCXX_HAVE_POSIX_SEMAPHORE -# include <cerrno> // errno, EINTR, EAGAIN etc. -# include <limits.h> // SEM_VALUE_MAX -# include <semaphore.h> // sem_t, sem_init, sem_wait, sem_post etc. -#elif defined(_GLIBCXX_USE_POSIX_SEMAPHORE) -# warning "POSIX semaphore not available, ignoring _GLIBCXX_USE_POSIX_SEMAPHORE" -# undef _GLIBCXX_USE_POSIX_SEMAPHORE -#endif namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION -#ifdef _GLIBCXX_HAVE_POSIX_SEMAPHORE - struct __platform_semaphore + template<bool _Platform_wait> + struct __semaphore_base { - using __clock_t = chrono::system_clock; -#ifdef SEM_VALUE_MAX - static constexpr ptrdiff_t _S_max = SEM_VALUE_MAX; -#else - static constexpr ptrdiff_t _S_max = _POSIX_SEM_VALUE_MAX; -#endif - - explicit __platform_semaphore(ptrdiff_t __count) noexcept - { - sem_init(&_M_semaphore, 0, __count); - } - - __platform_semaphore(const __platform_semaphore&) = delete; - __platform_semaphore& operator=(const __platform_semaphore&) = delete; - - ~__platform_semaphore() - { sem_destroy(&_M_semaphore); } - - _GLIBCXX_ALWAYS_INLINE void - _M_acquire() noexcept - { - while (sem_wait(&_M_semaphore)) - if (errno != EINTR) - std::__terminate(); - } - - _GLIBCXX_ALWAYS_INLINE bool - _M_try_acquire() noexcept - { - while (sem_trywait(&_M_semaphore)) - { - if (errno == EAGAIN) // already locked - return false; - else if (errno != EINTR) - std::__terminate(); - // else got EINTR so retry - } - return true; - } - - _GLIBCXX_ALWAYS_INLINE void - _M_release(ptrdiff_t __update) noexcept - { - for(; __update != 0; --__update) - if (sem_post(&_M_semaphore)) - std::__terminate(); - } - - bool - _M_try_acquire_until_impl(const chrono::time_point<__clock_t>& __atime) - noexcept - { - auto __s = chrono::time_point_cast<chrono::seconds>(__atime); - auto __ns = chrono::duration_cast<chrono::nanoseconds>(__atime - __s); + using __count_type = __conditional_t<_Platform_wait, + __detail::__platform_wait_t, + ptrdiff_t>; - struct timespec __ts = - { - static_cast<std::time_t>(__s.time_since_epoch().count()), - static_cast<long>(__ns.count()) - }; + static constexpr ptrdiff_t _S_max + = __gnu_cxx::__int_traits<__count_type>::__max; - while (sem_timedwait(&_M_semaphore, &__ts)) - { - if (errno == ETIMEDOUT) - return false; - else if (errno != EINTR) - std::__terminate(); - } - return true; - } - - template<typename _Clock, typename _Duration> - bool - _M_try_acquire_until(const chrono::time_point<_Clock, - _Duration>& __atime) noexcept - { - if constexpr (std::is_same_v<__clock_t, _Clock>) - { - using _Dur = __clock_t::duration; - return _M_try_acquire_until_impl(chrono::ceil<_Dur>(__atime)); - } - else - { - // TODO: if _Clock is monotonic_clock we could use - // sem_clockwait with CLOCK_MONOTONIC. + constexpr explicit + __semaphore_base(__count_type __count) noexcept + : _M_counter(__count) + { } - const typename _Clock::time_point __c_entry = _Clock::now(); - const auto __s_entry = __clock_t::now(); - const auto __delta = __atime - __c_entry; - const auto __s_atime = __s_entry + __delta; - if (_M_try_acquire_until_impl(__s_atime)) - return true; + __semaphore_base(const __semaphore_base&) = delete; + __semaphore_base& operator=(const __semaphore_base&) = delete; - // We got a timeout when measured against __clock_t but - // we need to check against the caller-supplied clock - // to tell whether we should return a timeout. - return (_Clock::now() < __atime); - } - } - - template<typename _Rep, typename _Period> - _GLIBCXX_ALWAYS_INLINE bool - _M_try_acquire_for(const chrono::duration<_Rep, _Period>& __rtime) - noexcept - { return _M_try_acquire_until(__clock_t::now() + __rtime); } - - private: - sem_t _M_semaphore; - }; -#endif // _GLIBCXX_HAVE_POSIX_SEMAPHORE - -#if __glibcxx_atomic_wait - struct __atomic_semaphore - { - static constexpr ptrdiff_t _S_max = __gnu_cxx::__int_traits<int>::__max; - explicit __atomic_semaphore(__detail::__platform_wait_t __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; - - static _GLIBCXX_ALWAYS_INLINE __detail::__platform_wait_t - _S_get_current(__detail::__platform_wait_t* __counter) noexcept + static _GLIBCXX_ALWAYS_INLINE __count_type + _S_get_current(__count_type* __counter) noexcept { return __atomic_impl::load(__counter, memory_order::acquire); } static _GLIBCXX_ALWAYS_INLINE bool - _S_do_try_acquire(__detail::__platform_wait_t* __counter, - __detail::__platform_wait_t __old) noexcept + _S_do_try_acquire(__count_type* __counter, __count_type __old) noexcept { if (__old == 0) return false; @@ -204,8 +86,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_acquire() noexcept { auto const __vfn = [this]{ return _S_get_current(&this->_M_counter); }; - auto const __pred = [this](__detail::__platform_wait_t __cur) - { return _S_do_try_acquire(&this->_M_counter, __cur); }; + auto const __pred = [this](__count_type __cur) { + return _S_do_try_acquire(&this->_M_counter, __cur); + }; std::__atomic_wait_address(&_M_counter, __pred, __vfn, true); } @@ -213,23 +96,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_try_acquire() noexcept { auto const __vfn = [this]{ return _S_get_current(&this->_M_counter); }; - auto const __pred = [this](__detail::__platform_wait_t __cur) - { return _S_do_try_acquire(&this->_M_counter, __cur); }; - return __atomic_wait_address_for(&_M_counter, __pred, __vfn, - __detail::__wait_clock_t::duration(), - true); + auto const __pred = [this](__count_type __cur) { + return _S_do_try_acquire(&this->_M_counter, __cur); + }; + using __detail::__wait_clock_t; + return std::__atomic_wait_address_for(&_M_counter, __pred, __vfn, + __wait_clock_t::duration(), + true); } template<typename _Clock, typename _Duration> _GLIBCXX_ALWAYS_INLINE bool - _M_try_acquire_until(const chrono::time_point<_Clock, - _Duration>& __atime) noexcept + _M_try_acquire_until(const chrono::time_point<_Clock, _Duration>& __atime) noexcept { auto const __vfn = [this]{ return _S_get_current(&this->_M_counter); }; - auto const __pred = [this](__detail::__platform_wait_t __cur) - { return _S_do_try_acquire(&this->_M_counter, __cur); }; - return std::__atomic_wait_address_until(&_M_counter, - __pred, __vfn, __atime, true); + auto const __pred = [this](__count_type __cur) { + return _S_do_try_acquire(&this->_M_counter, __cur); + }; + return std::__atomic_wait_address_until(&_M_counter, __pred, __vfn, + __atime, true); } template<typename _Rep, typename _Period> @@ -237,39 +122,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_try_acquire_for(const chrono::duration<_Rep, _Period>& __rtime) noexcept { auto const __vfn = [this]{ return _S_get_current(&this->_M_counter); }; - auto const __pred = [this](__detail::__platform_wait_t __cur) - { return _S_do_try_acquire(&this->_M_counter, __cur); }; - return std::__atomic_wait_address_for(&_M_counter, - __pred, __vfn, __rtime, true); + auto const __pred = [this](__count_type __cur) { + return _S_do_try_acquire(&this->_M_counter, __cur); + }; + return std::__atomic_wait_address_for(&_M_counter, __pred, __vfn, + __rtime, true); } - _GLIBCXX_ALWAYS_INLINE void + _GLIBCXX_ALWAYS_INLINE ptrdiff_t _M_release(ptrdiff_t __update) noexcept { - if (0 < __atomic_impl::fetch_add(&_M_counter, __update, memory_order_release)) - return; - if (__update > 1) - __atomic_notify_address(&_M_counter, true, true); - else + auto __old = __atomic_impl::fetch_add(&_M_counter, __update, + memory_order::release); + if (__old == 0 && __update > 0) __atomic_notify_address(&_M_counter, true, true); -// FIXME - Figure out why this does not wake a waiting thread -// __atomic_notify_address_bare(&_M_counter, false); + return __old; } private: - alignas(__detail::__platform_wait_alignment) - __detail::__platform_wait_t _M_counter; + alignas(_Platform_wait ? __detail::__platform_wait_alignment + : __alignof__(__count_type)) + __count_type _M_counter; }; -#endif // __cpp_lib_atomic_wait -// Note: the _GLIBCXX_USE_POSIX_SEMAPHORE macro can be used to force the -// use of Posix semaphores (sem_t). Doing so however, alters the ABI. -#if defined __glibcxx_atomic_wait && !_GLIBCXX_USE_POSIX_SEMAPHORE - using __semaphore_impl = __atomic_semaphore; -#elif _GLIBCXX_HAVE_POSIX_SEMAPHORE - using __semaphore_impl = __platform_semaphore; -#endif + template<ptrdiff_t _Max> + using __semaphore_impl + = __semaphore_base<(_Max <= __semaphore_base<true>::_S_max)>; _GLIBCXX_END_NAMESPACE_VERSION } // namespace std +#endif // __glibcxx_semaphore #endif // _GLIBCXX_SEMAPHORE_BASE_H diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def index 5a981caffe9b..9ab14a0310ed 100644 --- a/libstdc++-v3/include/bits/version.def +++ b/libstdc++-v3/include/bits/version.def @@ -1363,7 +1363,7 @@ ftms = { v = 201907; cxxmin = 20; hosted = yes; - extra_cond = "__glibcxx_atomic_wait || _GLIBCXX_HAVE_POSIX_SEMAPHORE"; + extra_cond = "__glibcxx_atomic_wait"; }; }; diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h index 06646110a914..3358e84f1607 100644 --- a/libstdc++-v3/include/bits/version.h +++ b/libstdc++-v3/include/bits/version.h @@ -1499,7 +1499,7 @@ #undef __glibcxx_want_move_iterator_concept #if !defined(__cpp_lib_semaphore) -# if (__cplusplus >= 202002L) && _GLIBCXX_HOSTED && (__glibcxx_atomic_wait || _GLIBCXX_HAVE_POSIX_SEMAPHORE) +# if (__cplusplus >= 202002L) && _GLIBCXX_HOSTED && (__glibcxx_atomic_wait) # define __glibcxx_semaphore 201907L # if defined(__glibcxx_want_all) || defined(__glibcxx_want_semaphore) # define __cpp_lib_semaphore 201907L diff --git a/libstdc++-v3/include/std/semaphore b/libstdc++-v3/include/std/semaphore index bec5ac301aa2..ca1bffe371a0 100644 --- a/libstdc++-v3/include/std/semaphore +++ b/libstdc++-v3/include/std/semaphore @@ -35,29 +35,29 @@ #include <bits/requires_hosted.h> // concurrency -#if __cplusplus > 201703L -#include <bits/semaphore_base.h> - #define __glibcxx_want_semaphore #include <bits/version.h> -#ifdef __cpp_lib_semaphore // C++ >= 20 && hosted && (atomic_wait || posix_sem) +#ifdef __cpp_lib_semaphore // C++ >= 20 && hosted && atomic_wait +#include <bits/semaphore_base.h> + namespace std _GLIBCXX_VISIBILITY(default) { _GLIBCXX_BEGIN_NAMESPACE_VERSION - template<ptrdiff_t __least_max_value = __semaphore_impl::_S_max> + template<ptrdiff_t __least_max_value = __semaphore_base<true>::_S_max> class counting_semaphore { static_assert(__least_max_value >= 0); - static_assert(__least_max_value <= __semaphore_impl::_S_max); - __semaphore_impl _M_sem; + using _Impl = __semaphore_impl<__least_max_value>; + _Impl _M_sem; public: - explicit counting_semaphore(ptrdiff_t __desired) noexcept - : _M_sem(__desired) - { } + constexpr explicit + counting_semaphore(ptrdiff_t __desired) noexcept + : _M_sem(__desired) + { __glibcxx_assert(__desired >= 0 && __desired <= max()); } ~counting_semaphore() = default; @@ -69,8 +69,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __least_max_value; } void - release(ptrdiff_t __update = 1) noexcept(noexcept(_M_sem._M_release(1))) - { _M_sem._M_release(__update); } + release(ptrdiff_t __update = 1) noexcept + { + [[maybe_unused]] ptrdiff_t __old = _M_sem._M_release(__update); + __glibcxx_assert(__update >= 0 && __update <= max() - __old); + } void acquire() noexcept(noexcept(_M_sem._M_acquire())) @@ -91,10 +94,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return _M_sem._M_try_acquire_until(__atime); } }; + /** @brief A binary semaphore + * + * @since C++20 + */ using binary_semaphore = std::counting_semaphore<1>; _GLIBCXX_END_NAMESPACE_VERSION } // namespace -#endif // cpp_lib_atomic_wait || _GLIBCXX_HAVE_POSIX_SEMAPHORE #endif // __cpp_lib_semaphore #endif // _GLIBCXX_SEMAPHORE diff --git a/libstdc++-v3/testsuite/30_threads/semaphore/100806.cc b/libstdc++-v3/testsuite/30_threads/semaphore/100806.cc index c770f05be009..4b761cef2024 100644 --- a/libstdc++-v3/testsuite/30_threads/semaphore/100806.cc +++ b/libstdc++-v3/testsuite/30_threads/semaphore/100806.cc @@ -12,7 +12,7 @@ #include <chrono> #include <vector> -std::counting_semaphore<4> semaphore{6}; +std::counting_semaphore<6> semaphore{6}; std::mutex mtx; std::vector<std::string> results; diff --git a/libstdc++-v3/testsuite/30_threads/semaphore/cons.cc b/libstdc++-v3/testsuite/30_threads/semaphore/cons.cc new file mode 100644 index 000000000000..920f7423332b --- /dev/null +++ b/libstdc++-v3/testsuite/30_threads/semaphore/cons.cc @@ -0,0 +1,7 @@ +// { dg-do compile { target c++20 } } + +#include <semaphore> + +// PR 110854 Constructor of std::counting_semaphore is not constexpr +constinit std::binary_semaphore b(0); +constinit std::counting_semaphore<5> c(2); diff --git a/libstdc++-v3/testsuite/30_threads/semaphore/platform_try_acquire_for.cc b/libstdc++-v3/testsuite/30_threads/semaphore/platform_try_acquire_for.cc deleted file mode 100644 index 6d90564ea8ac..000000000000 --- a/libstdc++-v3/testsuite/30_threads/semaphore/platform_try_acquire_for.cc +++ /dev/null @@ -1,9 +0,0 @@ -// { dg-options "-D_GLIBCXX_USE_POSIX_SEMAPHORE" } -// { dg-do run { target c++20 } } -// { dg-additional-options "-pthread" { target pthread } } -// { dg-require-gthreads "" } -// { dg-add-options libatomic } - -#include "try_acquire_for.cc" - -// { dg-prune-output "ignoring _GLIBCXX_USE_POSIX_SEMAPHORE" } diff --git a/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_posix.cc b/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_posix.cc deleted file mode 100644 index cf5745584c8d..000000000000 --- a/libstdc++-v3/testsuite/30_threads/semaphore/try_acquire_posix.cc +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright (C) 2020-2025 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License along -// with this library; see the file COPYING3. If not see -// <http://www.gnu.org/licenses/>. - -// { dg-do run { target c++20 } } -// { dg-additional-options "-pthread" { target pthread } } -// { dg-require-gthreads "" } -// { dg-add-options libatomic } - -#include <semaphore> -#ifdef _GLIBCXX_HAVE_POSIX_SEMAPHORE -#include <chrono> -#include <thread> -#include <atomic> -#include <testsuite_hooks.h> - -void test01() -{ - using namespace std::chrono_literals; - std::__platform_semaphore s(2); - s._M_acquire(); - - auto const dur = 250ms; - { - auto const t0 = std::chrono::steady_clock::now(); - VERIFY( s._M_try_acquire_for(dur) ); - auto const diff = std::chrono::steady_clock::now() - t0; - VERIFY( diff < dur ); - } - - { - auto const t0 = std::chrono::steady_clock::now(); - VERIFY( !s._M_try_acquire_for(dur) ); - auto const diff = std::chrono::steady_clock::now() - t0; - VERIFY( diff >= dur ); - } -} - -void test02() -{ - using namespace std::chrono_literals; - std::__platform_semaphore s(1); - std::atomic<int> a(0), b(0); - std::thread t([&] { - a.wait(0); - auto const dur = 250ms; - VERIFY( !s._M_try_acquire_for(dur) ); - b++; - b.notify_one(); - - a.wait(1); - VERIFY( s._M_try_acquire_for(dur) ); - b++; - b.notify_one(); - }); - t.detach(); - - s._M_acquire(); - a++; - a.notify_one(); - b.wait(0); - s._M_release(1); - a++; - a.notify_one(); - - b.wait(1); -} - -void test03() -{ - using namespace std::chrono_literals; - std::__platform_semaphore s(2); - s._M_acquire(); - - auto const dur = 250ms; - { - auto const at = std::chrono::system_clock::now() + dur; - auto const t0 = std::chrono::steady_clock::now(); - VERIFY( s._M_try_acquire_until(at) ); - auto const diff = std::chrono::steady_clock::now() - t0; - VERIFY( diff < dur ); - } - - { - auto const at = std::chrono::system_clock::now() + dur; - auto const t0 = std::chrono::steady_clock::now(); - VERIFY( !s._M_try_acquire_until(at) ); - auto const diff = std::chrono::steady_clock::now() - t0; - VERIFY( diff >= dur ); - } -} - -void test04() -{ - using namespace std::chrono_literals; - std::__platform_semaphore s(1); - std::atomic<int> a(0), b(0); - std::thread t([&] { - a.wait(0); - auto const dur = 250ms; - { - auto const at = std::chrono::system_clock::now() + dur; - VERIFY( !s._M_try_acquire_until(at) ); - - b++; - b.notify_one(); - } - - a.wait(1); - { - auto const at = std::chrono::system_clock::now() + dur; - VERIFY( s._M_try_acquire_until(at) ); - } - b++; - b.notify_one(); - }); - t.detach(); - - s._M_acquire(); - a++; - a.notify_one(); - b.wait(0); - s._M_release(1); - a++; - a.notify_one(); - - b.wait(1); -} -#endif - -int main() -{ -#ifdef _GLIBCXX_HAVE_POSIX_SEMAPHORE - test01(); - test02(); - test03(); - test04(); -#endif - return 0; -}