On Fri, Jan 9, 2026 at 7:43 PM Jonathan Wakely <[email protected]> wrote:

> On Fri, 9 Jan 2026 at 17:55, Tomasz Kaminski <[email protected]> wrote:
> >
> >
> >
> > On Fri, Jan 9, 2026 at 6:44 PM Jonathan Wakely <[email protected]>
> wrote:
> >>
> >> As noted in Bug 122878 comment 2, the _M_try_acquire_for implementation
> >> doesn't reduce the remaining timeout each time it returns from an atomic
> >> waiting function. This means that it can wait longer than requested, or
> >> even loop forever. If there is a spurious wake from the timed waiting
> >> function (__wait_until_impl) it will return indicating no timeout
> >> occurred, which means the caller will check the value and potentially
> >> sleep again. If spurious wakes happen every time, it will just keep
> >> sleeping in a loop forever. This is observed to actually happen on
> >> FreeBSD 14.0-STABLE where pthread_cond_timedwait gets a spurious wake
> >> and so never times out.
> >>
> >> The solution in this commit is to replace the implementation of
> >> _M_try_acquire_for with a call to _M_try_acquire_until, converting the
> >> relative timeout to an absolute timeout against the steady clock.
> >
> > Could you mention that __atomic_wait"_for was already doing that anyway,
> > for non-zero durations, as we only define __platform_wait_until
> primitive.
> >>
> >>
> >> As noted in comment 4 of the PR, this requires some changes to
> >> _M_try_acquire which was relying on an implementation detail of
> >> _M_try_acquire_for, namely that waiting for a zero duration will just
> >> check if the value changes in a spinloop, without actually sleeping.
> >> This behaviour is desirable for _M_try_acquire so that it can handle
> >> short-lived contention without failing immediately. To preserve that
> >> behaviour of _M_try_acquire it is changed to do its own loop and to call
> >> __atomic_wait_address_for directly to do the spinloop.
> >
> > I would add to call  __atomic_wait_address_for with zero duration.
>
> How's this?
>
Looks good.

>
>
> The solution in this commit is to replace the implementation of
> _M_try_acquire_for with a call to _M_try_acquire_until, converting the
> relative timeout to an absolute timeout against the steady clock. This
> is what ends up happening anyway, because we only have a
> __wait_until_impl entry point into the library internals, so
> __atomic_wait_address_for already converts the relative timeout to an
> absolute timeout (except for the special case of a zero-value duration,
> which only checks for an update while spinning for a finite number of
> iterations, and doesn't sleep).
>
> As noted in comment 4 of the PR, this requires some changes to
> _M_try_acquire which was relying on the behaviour of _M_try_acquire_for
> for zero-value durations.  That behaviour is desirable for
> _M_try_acquire so that it can handle short-lived contention without
> failing immediately. To preserve that behaviour of _M_try_acquire it is
> changed to do its own loop and to call __atomic_wait_address_for
> directly with a zero duration, to do the spinloop.
>
>

Reply via email to