mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-09-18 23:09:29 +02:00
srcu: expose srcu_readers_active()
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. To achive this: 1- Move the srcu_readers_active() implementation from "kernel/rcu/srcutree.c" to "include/linux/srcutree.h". 2- Implement a matching srcu_readers_active() in "include/linux/srcutiny.h" and use it on the existing open-coded WARN_ON() check in cleanup_srcu_struct(). Signed-off-by: Onur Özkan <work@onurozkan.dev> Reviewed-by: Gary Guo <gary@garyguo.net> Reviewed-by: Alice Ryhl <aliceryhl@google.com> Reviewed-by: Boqun Feng <boqun@kernel.org> Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
This commit is contained in:
committed by
Paul E. McKenney
parent
8f63d947be
commit
91d5185187
@@ -154,4 +154,17 @@ static inline void srcu_torture_stats_print(struct srcu_struct *ssp,
|
||||
data_race(READ_ONCE(ssp->srcu_idx_max)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
return READ_ONCE(ssp->srcu_lock_nesting[0]) || READ_ONCE(ssp->srcu_lock_nesting[1]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -374,4 +374,28 @@ static inline void srcu_check_read_flavor(struct srcu_struct *ssp, int read_flav
|
||||
__srcu_check_read_flavor(ssp, read_flavor);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
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
|
||||
|
||||
@@ -85,7 +85,7 @@ EXPORT_SYMBOL_GPL(init_srcu_struct_generic);
|
||||
*/
|
||||
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);
|
||||
|
||||
@@ -599,31 +599,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
|
||||
|
||||
@@ -9,6 +9,11 @@ __rust_helper int rust_helper_init_srcu_struct_with_key(struct srcu_struct *ssp,
|
||||
return __init_srcu_struct(ssp, name, key);
|
||||
}
|
||||
|
||||
__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);
|
||||
|
||||
Reference in New Issue
Block a user