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)

