With the change to the title, this looks good to me. On Tue, Jun 3, 2025 at 12:02 PM Tomasz Kaminski <tkami...@redhat.com> wrote:
> The tile says that you are doing only comment fixes, while there is code > change > in __spin_until_impl. Could you please adjust it: > Fix incorrect returns and comments on atomic timed waits > > On Mon, Jun 2, 2025 at 7:24 PM Jonathan Wakely <jwak...@redhat.com> wrote: > >> The __detail::__wait_until function has a comment that should have been >> removed when r16-1000-g225622398a9631 changed the return type from a >> std::pair to a struct with three members. >> >> __atomic_wait_address_until_v returns __res.first which should have been >> changed when __res was no longer a std::pair. >> >> Fix _M_spin_until_impl so that the _M_has_val member of the result is >> accurate. If the deadline has passed then it never enters the loop and >> so never loads a fresh value, so _M_has_val should be false. >> >> libstdc++-v3/ChangeLog: >> >> * include/bits/atomic_timed_wait.h (__detail::__wait_until): >> Remove incorrect comment. >> (__atomic_wait_address_until_v): Fix return statement. >> * src/c++20/atomic.cc (__spin_until_impl): Fix incorrect >> return value. Reuse result of first call to clock. >> --- >> >> Tested x86_64-linux. >> >> libstdc++-v3/include/bits/atomic_timed_wait.h | 3 +-- >> libstdc++-v3/src/c++20/atomic.cc | 24 ++++++++++++------- >> 2 files changed, 16 insertions(+), 11 deletions(-) >> >> diff --git a/libstdc++-v3/include/bits/atomic_timed_wait.h >> b/libstdc++-v3/include/bits/atomic_timed_wait.h >> index 230afbc96e7d..e22c13f47b18 100644 >> --- a/libstdc++-v3/include/bits/atomic_timed_wait.h >> +++ b/libstdc++-v3/include/bits/atomic_timed_wait.h >> @@ -87,7 +87,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> __wait_until_impl(const void* __addr, __wait_args_base& __args, >> const __wait_clock_t::duration& __atime); >> >> - // Returns {true, val} if wait ended before a timeout. >> template<typename _Clock, typename _Dur> >> __wait_result_type >> __wait_until(const void* __addr, __wait_args_base& __args, >> @@ -159,7 +158,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >> { >> __detail::__wait_args __args{ __addr, __old, __order, __bare_wait >> }; >> auto __res = __detail::__wait_until(__addr, &__args, __atime); >> - return __res.first; // C++26 will also return last observed __val >> + return !__res._M_timeout; // C++26 will also return last observed >> __val >> } >> >> template<typename _Tp, typename _ValFn, >> diff --git a/libstdc++-v3/src/c++20/atomic.cc >> b/libstdc++-v3/src/c++20/atomic.cc >> index a3ec92a10d56..4120e1a0817f 100644 >> --- a/libstdc++-v3/src/c++20/atomic.cc >> +++ b/libstdc++-v3/src/c++20/atomic.cc >> @@ -397,17 +397,18 @@ __cond_wait_until(__condvar& __cv, mutex& __mx, >> } >> #endif // ! HAVE_PLATFORM_TIMED_WAIT >> >> -// Like __spin_impl, always returns _M_has_val == true. >> +// Unlike __spin_impl, does not always return _M_has_val == true. >> +// If the deadline has already passed then no fresh value is loaded. >> > This is indeed true now. > >> __wait_result_type >> __spin_until_impl(const __platform_wait_t* __addr, >> const __wait_args_base& __args, >> const __wait_clock_t::time_point& __deadline) >> { >> - auto __t0 = __wait_clock_t::now(); >> using namespace literals::chrono_literals; >> >> - __platform_wait_t __val{}; >> - auto __now = __wait_clock_t::now(); >> + __wait_result_type __res{}; >> + auto __t0 = __wait_clock_t::now(); >> + auto __now = __t0; >> for (; __now < __deadline; __now = __wait_clock_t::now()) >> { >> auto __elapsed = __now - __t0; >> @@ -422,16 +423,21 @@ __spin_until_impl(const __platform_wait_t* __addr, >> __thread_yield(); >> else >> { >> - auto __res = __detail::__spin_impl(__addr, __args); >> + __res = __detail::__spin_impl(__addr, __args); >> if (!__res._M_timeout) >> return __res; >> } >> >> - __atomic_load(__addr, &__val, __args._M_order); >> - if (__val != __args._M_old) >> - return { ._M_val = __val, ._M_has_val = true, ._M_timeout = false >> }; >> + __atomic_load(__addr, &__res._M_val, __args._M_order); >> + __res._M_has_val = true; >> + if (__res._M_val != __args._M_old) >> + { >> + __res._M_timeout = false; >> + return __res; >> + } >> } >> - return { ._M_val = __val, ._M_has_val = true, ._M_timeout = true }; >> + __res._M_timeout = true; >> + return __res; >> } >> } // namespace >> >> -- >> 2.49.0 >> >>