Skip to content

Commit 7d13d30

Browse files
committed
rcu-tasks: Count trylocks to estimate call_rcu_tasks() contention
This commit converts the unconditional raw_spin_lock_rcu_node() lock acquisition in call_rcu_tasks_generic() to a trylock followed by an unconditional acquisition if the trylock fails. If the trylock fails, the failure is counted, but the count is reset to zero on each new jiffy. This statistic will be used to determine when to move from a single callback queue to per-CPU callback queues. Reported-by: Martin Lau <kafai@fb.com> Cc: Neeraj Upadhyay <neeraj.iitr10@gmail.com> Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
1 parent 8610b65 commit 7d13d30

1 file changed

Lines changed: 14 additions & 1 deletion

File tree

kernel/rcu/tasks.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ typedef void (*postgp_func_t)(struct rcu_tasks *rtp);
2424
* struct rcu_tasks_percpu - Per-CPU component of definition for a Tasks-RCU-like mechanism.
2525
* @cblist: Callback list.
2626
* @lock: Lock protecting per-CPU callback list.
27+
* @rtp_jiffies: Jiffies counter value for statistics.
28+
* @rtp_n_lock_retries: Rough lock-contention statistic.
2729
* @rtp_work: Work queue for invoking callbacks.
2830
* @barrier_q_head: RCU callback for barrier operation.
2931
* @cpu: CPU number corresponding to this entry.
@@ -32,6 +34,8 @@ typedef void (*postgp_func_t)(struct rcu_tasks *rtp);
3234
struct rcu_tasks_percpu {
3335
struct rcu_segcblist cblist;
3436
raw_spinlock_t __private lock;
37+
unsigned long rtp_jiffies;
38+
unsigned long rtp_n_lock_retries;
3539
struct work_struct rtp_work;
3640
struct rcu_head barrier_q_head;
3741
int cpu;
@@ -231,6 +235,7 @@ static void call_rcu_tasks_generic(struct rcu_head *rhp, rcu_callback_t func,
231235
struct rcu_tasks *rtp)
232236
{
233237
unsigned long flags;
238+
unsigned long j;
234239
bool needwake;
235240
struct rcu_tasks_percpu *rtpcp;
236241

@@ -239,7 +244,15 @@ static void call_rcu_tasks_generic(struct rcu_head *rhp, rcu_callback_t func,
239244
local_irq_save(flags);
240245
rtpcp = per_cpu_ptr(rtp->rtpcpu,
241246
smp_processor_id() >> READ_ONCE(rtp->percpu_enqueue_shift));
242-
raw_spin_lock_rcu_node(rtpcp); // irqs already disabled.
247+
if (!raw_spin_trylock_rcu_node(rtpcp)) { // irqs already disabled.
248+
raw_spin_lock_rcu_node(rtpcp); // irqs already disabled.
249+
j = jiffies;
250+
if (rtpcp->rtp_jiffies != j) {
251+
rtpcp->rtp_jiffies = j;
252+
rtpcp->rtp_n_lock_retries = 0;
253+
}
254+
rtpcp->rtp_n_lock_retries++;
255+
}
243256
if (!rcu_segcblist_is_enabled(&rtpcp->cblist)) {
244257
raw_spin_unlock_rcu_node(rtpcp); // irqs remain disabled.
245258
cblist_init_generic(rtp);

0 commit comments

Comments
 (0)