On Wed, May 27, 2026 at 12:37:14PM -0700, Boqun Feng wrote:
> On Wed, May 27, 2026 at 08:40:43PM +0300, Onur Özkan wrote:
> > Move srcu_readers_active() from kernel/rcu/srcutree.c into
> > include/linux/srcu.h so it can be reused by Rust SRCU helpers.
> > 
> > Provide a CONFIG_TINY_SRCU implementation in the header as well
> > so the helper is available regardless of the selected SRCU backend.
> > 
> > This is needed by rust/helpers/srcu.c which now adds
> > rust_helper_srcu_readers_active() as a wrapper around the SRCU helper
> > for Rust callers.
> > 
> > Signed-off-by: Onur Özkan <[email protected]>
> > ---
> >  include/linux/srcu.h  | 29 +++++++++++++++++++++++++++++
> >  kernel/rcu/srcutiny.c |  2 +-
> >  kernel/rcu/srcutree.c | 25 -------------------------
> >  rust/helpers/srcu.c   |  5 +++++
> >  4 files changed, 35 insertions(+), 26 deletions(-)
> > 
> > diff --git a/include/linux/srcu.h b/include/linux/srcu.h
> > index 81b1938512d5..5ca35efb4536 100644
> > --- a/include/linux/srcu.h
> > +++ b/include/linux/srcu.h
> > @@ -92,6 +92,35 @@ void call_srcu(struct srcu_struct *ssp, struct rcu_head 
> > *head,
> >  void cleanup_srcu_struct(struct srcu_struct *ssp);
> >  void synchronize_srcu(struct srcu_struct *ssp);
> >  
> > +/**
> > + * srcu_readers_active - returns true if there are readers, and false 
> > otherwise
> > + * @ssp: which srcu_struct to count active readers (holding 
> > srcu_read_lock).
> > + *
> > + * Note that this is not an atomic primitive, and can therefore suffer
> > + * severe errors when invoked on an active srcu_struct. That said, it can 
> > be
> > + * useful as an error check at cleanup time.
> > + */
> > +static inline bool srcu_readers_active(struct srcu_struct *ssp)
> > +{
> > +#ifdef CONFIG_TINY_SRCU
> 
> Having a "#ifdef" in a function body is generally considered as bad code
> (I know we have some of these in rust helpers, but helpers are a bit
> special and maybe we should clean them up). So could you move this
> function into include/linux/srcutiny.h and include/linux/srcutree.h?

What Boqun said, please!

                                                        Thanx, Paul

> Thanks!
> 
> Regards,
> Boqun
> 
> > +   return READ_ONCE(ssp->srcu_lock_nesting[0]) || 
> > READ_ONCE(ssp->srcu_lock_nesting[1]);
> > +#else
> > +   int cpu;
> > +   unsigned long sum = 0;
> > +
> > +   for_each_possible_cpu(cpu) {
> > +           struct srcu_data *sdp = per_cpu_ptr(ssp->sda, cpu);
> > +
> > +           sum += atomic_long_read(&sdp->srcu_ctrs[0].srcu_locks);
> > +           sum += atomic_long_read(&sdp->srcu_ctrs[1].srcu_locks);
> > +           sum -= atomic_long_read(&sdp->srcu_ctrs[0].srcu_unlocks);
> > +           sum -= atomic_long_read(&sdp->srcu_ctrs[1].srcu_unlocks);
> > +   }
> > +
> > +   return sum;
> > +#endif
> > +}
> > +
> >  #define SRCU_GET_STATE_COMPLETED 0x1
> >  
> >  /**
> > diff --git a/kernel/rcu/srcutiny.c b/kernel/rcu/srcutiny.c
> > index a2e2d516e51b..5dc26af604bf 100644
> > --- a/kernel/rcu/srcutiny.c
> > +++ b/kernel/rcu/srcutiny.c
> > @@ -85,7 +85,7 @@ EXPORT_SYMBOL_GPL(init_srcu_struct);
> >   */
> >  void cleanup_srcu_struct(struct srcu_struct *ssp)
> >  {
> > -   WARN_ON(ssp->srcu_lock_nesting[0] || ssp->srcu_lock_nesting[1]);
> > +   WARN_ON(srcu_readers_active(ssp));
> >     irq_work_sync(&ssp->srcu_irq_work);
> >     flush_work(&ssp->srcu_work);
> >     WARN_ON(ssp->srcu_gp_running);
> > diff --git a/kernel/rcu/srcutree.c b/kernel/rcu/srcutree.c
> > index 0d01cd8c4b4a..b1e97ba2e53f 100644
> > --- a/kernel/rcu/srcutree.c
> > +++ b/kernel/rcu/srcutree.c
> > @@ -598,31 +598,6 @@ static bool srcu_readers_active_idx_check(struct 
> > srcu_struct *ssp, int idx)
> >     return srcu_readers_lock_idx(ssp, idx, did_gp, unlocks);
> >  }
> >  
> > -/**
> > - * srcu_readers_active - returns true if there are readers. and false
> > - *                       otherwise
> > - * @ssp: which srcu_struct to count active readers (holding 
> > srcu_read_lock).
> > - *
> > - * Note that this is not an atomic primitive, and can therefore suffer
> > - * severe errors when invoked on an active srcu_struct.  That said, it
> > - * can be useful as an error check at cleanup time.
> > - */
> > -static bool srcu_readers_active(struct srcu_struct *ssp)
> > -{
> > -   int cpu;
> > -   unsigned long sum = 0;
> > -
> > -   for_each_possible_cpu(cpu) {
> > -           struct srcu_data *sdp = per_cpu_ptr(ssp->sda, cpu);
> > -
> > -           sum += atomic_long_read(&sdp->srcu_ctrs[0].srcu_locks);
> > -           sum += atomic_long_read(&sdp->srcu_ctrs[1].srcu_locks);
> > -           sum -= atomic_long_read(&sdp->srcu_ctrs[0].srcu_unlocks);
> > -           sum -= atomic_long_read(&sdp->srcu_ctrs[1].srcu_unlocks);
> > -   }
> > -   return sum;
> > -}
> > -
> >  /*
> >   * We use an adaptive strategy for synchronize_srcu() and especially for
> >   * synchronize_srcu_expedited().  We spin for a fixed time period
> > diff --git a/rust/helpers/srcu.c b/rust/helpers/srcu.c
> > index 79dd24a104ef..fa4b5879dda5 100644
> > --- a/rust/helpers/srcu.c
> > +++ b/rust/helpers/srcu.c
> > @@ -13,6 +13,11 @@ __rust_helper int 
> > rust_helper_init_srcu_struct_with_key(struct srcu_struct *ssp,
> >  #endif /* CONFIG_DEBUG_LOCK_ALLOC */
> >  }
> >  
> > +__rust_helper bool rust_helper_srcu_readers_active(struct srcu_struct *ssp)
> > +{
> > +   return srcu_readers_active(ssp);
> > +}
> > +
> >  __rust_helper int rust_helper_srcu_read_lock(struct srcu_struct *ssp)
> >  {
> >     return srcu_read_lock(ssp);
> > -- 
> > 2.51.2
> > 

Reply via email to