[PATCH] [libstdc++] Fix "bare" notifications dropped by waiters check

Thomas Rodgers rodgert@appliantology.com
Thu Apr 22 14:40:05 GMT 2021


On 2021-04-22 02:23, Jonathan Wakely wrote:

> On 21/04/21 18:29 -0700, Thomas Rodgers wrote:
> 
>> From: Thomas Rodgers <rodgert@twrodgers.com>
>> 
>> NOTE - This patch also needs to be backported to gcc-11 in order for
>> semaphore release() to work correctly on non-futex platforms.
>> 
>> Tested sparc-sun-solaris2.11
>> 
>> For types that track whether or not there extant waiters (e.g.
>> semaphore) internally, the __atomic_notify_address_bare() call was
>> introduced to avoid the overhead of loading the atomic count of
>> waiters. For platforms that don't have Futex, however, there was
>> still a check for waiters, and seeing that there are none (because
>> in the bare case, the count is not incremented), the notification
>> is dropped. This commit addresses that case.
>> 
>> libstdc++-v3/ChangeLog:
>> * include/bits/atomic_wait.h: Always notify waiters in the
>> in the case of 'bare' address notification.
> 
> Repeated text: "in the in the"
> 
>> ---
>> libstdc++-v3/include/bits/atomic_wait.h | 12 ++++++------
>> 1 file changed, 6 insertions(+), 6 deletions(-)
>> 
>> diff --git a/libstdc++-v3/include/bits/atomic_wait.h 
>> b/libstdc++-v3/include/bits/atomic_wait.h
>> index 0ac5575190c..984ed70f16c 100644
>> --- a/libstdc++-v3/include/bits/atomic_wait.h
>> +++ b/libstdc++-v3/include/bits/atomic_wait.h
>> @@ -226,9 +226,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>> }
>> 
>> void
>> -      _M_notify(const __platform_wait_t* __addr, bool __all) noexcept
>> +      _M_notify(const __platform_wait_t* __addr, bool __all, bool 
>> __bare) noexcept
>> {
>> -    if (!_M_waiting())
>> +    if (!(__bare || _M_waiting()))
> 
> Maybe it's just me, but I would find (!__base && !__waiting) to be a
> clearer expression of the logic here.
> 
> i.e. "return if the wait is not bare and there are no waiters"
> rather than "return if the wait is not either bare or has waiters".
> The latter makes me take a second to grok.
> 

As discussed on IRC, I went back and forth on this a couple of times and 
neither option seemed particularly great to me. I started down the path 
of propagating the std::true_type/std::false_type bits that the RAII 
wrapper type knows about and making this a compile time choice, but felt 
the change was too big to make this late in the release cycle. I will 
revisit this for stage1 (though ideally all of this will be moved into 
the .so for GCC12 and partially rewritten as part of that process 
anyway).

> The patch is OK either way though, with the ChangeLog typo fix.
> 
>> return;
>> 
>> #ifdef _GLIBCXX_HAVE_PLATFORM_WAIT
>> @@ -304,11 +304,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>> }
>> 
>> void
>> -    _M_notify(bool __all)
>> +    _M_notify(bool __all, bool __bare = false)
>> {
>> if (_M_addr == &_M_w._M_ver)
>> __atomic_fetch_add(_M_addr, 1, __ATOMIC_ACQ_REL);
>> -      _M_w._M_notify(_M_addr, __all);
>> +      _M_w._M_notify(_M_addr, __all, __bare);
>> }
>> 
>> template<typename _Up, typename _ValFn,
>> @@ -452,7 +452,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>> __atomic_notify_address(const _Tp* __addr, bool __all) noexcept
>> {
>> __detail::__bare_wait __w(__addr);
>> -      __w._M_notify(__all);
>> +      __w._M_notify(__all, true);
>> }
>> 
>> // This call is to be used by atomic types which track contention 
>> externally
>> @@ -464,7 +464,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>> __detail::__platform_notify(__addr, __all);
>> #else
>> __detail::__bare_wait __w(__addr);
>> -    __w._M_notify(__all);
>> +    __w._M_notify(__all, true);
>> #endif
>> }
>> _GLIBCXX_END_NAMESPACE_VERSION
>> -- 2.30.2

Tested sparc-sun-solaris2.11.
Committed to master, backported to release/gcc-11.


More information about the Libstdc++ mailing list