Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rcu: Export rcu_request_urgent_qs_task()

If a CPU is executing a long series of non-sleeping system calls,
RCU grace periods can be delayed for on the order of a couple hundred
milliseconds. This is normally not a problem, but if each system call
does a call_rcu(), those callbacks can stack up. RCU will eventually
notice this callback storm, but use of rcu_request_urgent_qs_task()
allows the code invoking call_rcu() to give RCU a heads up.

This function is not for general use, not yet, anyway.

Reported-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/bpf/20230706033447.54696-11-alexei.starovoitov@gmail.com

authored by

Paul E. McKenney and committed by
Daniel Borkmann
43a89bae 04fabf00

+3 -2
+2
include/linux/rcutiny.h
··· 138 138 return 0; 139 139 } 140 140 141 + static inline void rcu_request_urgent_qs_task(struct task_struct *t) { } 142 + 141 143 /* 142 144 * Take advantage of the fact that there is only one CPU, which 143 145 * allows us to ignore virtualization-based context switches.
+1
include/linux/rcutree.h
··· 21 21 void rcu_note_context_switch(bool preempt); 22 22 int rcu_needs_cpu(void); 23 23 void rcu_cpu_stall_reset(void); 24 + void rcu_request_urgent_qs_task(struct task_struct *t); 24 25 25 26 /* 26 27 * Note a virtualization-based context switch. This is simply a
-2
kernel/rcu/rcu.h
··· 493 493 static inline void rcu_unexpedite_gp(void) { } 494 494 static inline void rcu_async_hurry(void) { } 495 495 static inline void rcu_async_relax(void) { } 496 - static inline void rcu_request_urgent_qs_task(struct task_struct *t) { } 497 496 #else /* #ifdef CONFIG_TINY_RCU */ 498 497 bool rcu_gp_is_normal(void); /* Internal RCU use. */ 499 498 bool rcu_gp_is_expedited(void); /* Internal RCU use. */ ··· 507 508 #else /* #ifdef CONFIG_TASKS_RCU_GENERIC */ 508 509 static inline void show_rcu_tasks_gp_kthreads(void) {} 509 510 #endif /* #else #ifdef CONFIG_TASKS_RCU_GENERIC */ 510 - void rcu_request_urgent_qs_task(struct task_struct *t); 511 511 #endif /* #else #ifdef CONFIG_TINY_RCU */ 512 512 513 513 #define RCU_SCHEDULER_INACTIVE 0