Hi David,

Thanks for the patch.

On Wed, 12 Aug 2026 13:32:48 +0100 David Woodhouse <[email protected]> wrote:
> From: David Woodhouse <[email protected]>
> 
> For a dedicated srcu_struct whose read-side critical sections are
> short, atomic, and usually absent — such as one converted from a
> spinning lock — the common case at synchronize time is that there are
> no readers at all. Even synchronize_srcu_expedited() still costs the
> caller an unconditional sleep and two trips through the SRCU workqueue

If the common case is that there are no readers and the new fast path
is intended to avoid the SRCU grace-period machinery, could you explain
what property of SRCU is still required by the proposed users that
prevents using ordinary RCU instead?

> And synchronize_srcu()'s auto-expedite heuristic explicitly
> declines to expedite within exp_holdoff (25µs) of the previous grace
> period, which is exactly the regime a burst of back-to-back
> invalidations puts such a domain in.
> 

Could this use case instead be addressed by making exp_holdoff
configurable per srcu_struct, or otherwise allowing a dedicated SRCU
domain to use a more aggressive expedite policy?

If not, what makes the proposed try path preferable to changing the
expedite policy?

> Provide try_synchronize_srcu(), which proves the no-readers case
> inline and returns true without sleeping, without the workqueue, and
> without advancing the grace-period sequence (so cookies from
> get_state_synchronize_srcu() and queued callbacks are unaffected). If

Could you also clarify why observing no readers during this
check is sufficient for the reclamation/happens-before guarantee
required by the proposed callers?

Since a successful try_synchronize_srcu() does not advance srcu_gp_seq, 
flip the SRCU index, or process callbacks, could we document more 
explicitly that a successful try provides the required 
reclamation/happens-before guarantee to the caller, but does not 
constitute an SRCU grace-period completion for the state/callback APIs?


> the proof fails, it returns false and the caller falls back:
> 
>       if (!try_synchronize_srcu(ssp))
>               synchronize_srcu_expedited(ssp);
> 
> For Tree SRCU the proof sums both epochs' unlock counters, executes a
> full barrier, then sums both epochs' lock counters. Equality proves a

One question about the barriers: the existing
srcu_readers_active_idx_check() relies on the barrier between the
unlock-counter and lock-counter reads to provide the ordering with the
reader-side barrier; the !did_gp path there has no barrier before the
unlock-counter read.
 
[...]
> +     smp_mb();
> +
> +     unlocks0 = srcu_readers_unlock_idx(ssp, 0, &rdm0);
> +     unlocks1 = srcu_readers_unlock_idx(ssp, 1, &rdm1);
> +
> +     /*
> +      * Reader flavors which elide the read-side smp_mb() that the
> +      * pairing above depends on cannot be proven absent this way;
> +      * they need a real grace period.
> +      */
> +     if ((rdm0 | rdm1) & SRCU_READ_FLAVOR_SLOWGP)
> +             return false;
> +
> +     /*
> +      * As in srcu_readers_active_idx_check(): ensure that a lock is
> +      * always counted if the corresponding unlock is counted, so that
> +      * a reader racing with these sums can only inflate the lock sum
> +      * and force the (safe) fallback. Summing both epochs means no
> +      * index flip is needed: a stable equality proves there was a
> +      * moment in this function at which no readers existed at all.
> +      */
> +     smp_mb();

And, the middle smp_mb() appears to occupy the same position, while
the final smp_mb() orders the caller's subsequent accesses after a
successful proof.

What ordering edge does the first smp_mb() establish that is not
already provided by the middle and final barriers? I couldn't identify
a specific execution requiring it from the current comment or code
structure.

Could you point out the ordering requirement for the first smp_mb(),
or provide an LKMM argument showing why it is needed?

If there is no additional ordering requirement, could it be removed to
avoid an extra full memory barrier in this fast path?

> +
> +     if (!srcu_readers_lock_idx(ssp, 0, false, unlocks0))
> +             return false;
> +     if (!srcu_readers_lock_idx(ssp, 1, false, unlocks1))
> +             return false;
> +
> +     /* Order the caller's subsequent accesses after the proof. */
> +     smp_mb();
> +     return true;
> +}
> +EXPORT_SYMBOL_GPL(try_synchronize_srcu);

One more question about the documented fallback: synchronize_srcu()
and __synchronize_srcu() use
RCU_LOCKDEP_WARN(lockdep_is_held(ssp) || ...) to catch invocation from
within a same-type SRCU read-side critical section.

try_synchronize_srcu() does not appear to perform the corresponding
check. A caller inside an SRCU read-side critical section would fail
the fast-path proof and then follow the documented expedited fallback,
resulting in a self-deadlock without the corresponding lockdep diagnostic.

Would it make sense to perform the same lockdep check in the try path?

When applying this to current rcu/dev, the patch also needs to account
for the additional bool is_atomic argument to
check_init_srcu_struct(). Please rebase accordingly.

Thanks,
KunWu
> +
>  /**
>   * get_state_synchronize_srcu - Provide an end-of-grace-period cookie
>   * @ssp: srcu_struct to provide cookie for.
> -- 
> 2.43.0
> 
> 

Sent using hkml (https://github.com/sjp38/hackermail)

Reply via email to