xref: /linux/kernel/rcu/tree_stall.h (revision 10462d6f58fb6dbde7563e9343505d98d5bfba3d)
1*10462d6fSPaul E. McKenney // SPDX-License-Identifier: GPL-2.0+
2*10462d6fSPaul E. McKenney /*
3*10462d6fSPaul E. McKenney  * RCU CPU stall warnings for normal RCU grace periods
4*10462d6fSPaul E. McKenney  *
5*10462d6fSPaul E. McKenney  * Copyright IBM Corporation, 2019
6*10462d6fSPaul E. McKenney  *
7*10462d6fSPaul E. McKenney  * Author: Paul E. McKenney <paulmck@linux.ibm.com>
8*10462d6fSPaul E. McKenney  */
9*10462d6fSPaul E. McKenney 
10*10462d6fSPaul E. McKenney 
11*10462d6fSPaul E. McKenney #ifdef CONFIG_PROVE_RCU
12*10462d6fSPaul E. McKenney #define RCU_STALL_DELAY_DELTA	       (5 * HZ)
13*10462d6fSPaul E. McKenney #else
14*10462d6fSPaul E. McKenney #define RCU_STALL_DELAY_DELTA	       0
15*10462d6fSPaul E. McKenney #endif
16*10462d6fSPaul E. McKenney 
17*10462d6fSPaul E. McKenney int rcu_jiffies_till_stall_check(void)
18*10462d6fSPaul E. McKenney {
19*10462d6fSPaul E. McKenney 	int till_stall_check = READ_ONCE(rcu_cpu_stall_timeout);
20*10462d6fSPaul E. McKenney 
21*10462d6fSPaul E. McKenney 	/*
22*10462d6fSPaul E. McKenney 	 * Limit check must be consistent with the Kconfig limits
23*10462d6fSPaul E. McKenney 	 * for CONFIG_RCU_CPU_STALL_TIMEOUT.
24*10462d6fSPaul E. McKenney 	 */
25*10462d6fSPaul E. McKenney 	if (till_stall_check < 3) {
26*10462d6fSPaul E. McKenney 		WRITE_ONCE(rcu_cpu_stall_timeout, 3);
27*10462d6fSPaul E. McKenney 		till_stall_check = 3;
28*10462d6fSPaul E. McKenney 	} else if (till_stall_check > 300) {
29*10462d6fSPaul E. McKenney 		WRITE_ONCE(rcu_cpu_stall_timeout, 300);
30*10462d6fSPaul E. McKenney 		till_stall_check = 300;
31*10462d6fSPaul E. McKenney 	}
32*10462d6fSPaul E. McKenney 	return till_stall_check * HZ + RCU_STALL_DELAY_DELTA;
33*10462d6fSPaul E. McKenney }
34*10462d6fSPaul E. McKenney EXPORT_SYMBOL_GPL(rcu_jiffies_till_stall_check);
35*10462d6fSPaul E. McKenney 
36*10462d6fSPaul E. McKenney void rcu_sysrq_start(void)
37*10462d6fSPaul E. McKenney {
38*10462d6fSPaul E. McKenney 	if (!rcu_cpu_stall_suppress)
39*10462d6fSPaul E. McKenney 		rcu_cpu_stall_suppress = 2;
40*10462d6fSPaul E. McKenney }
41*10462d6fSPaul E. McKenney 
42*10462d6fSPaul E. McKenney void rcu_sysrq_end(void)
43*10462d6fSPaul E. McKenney {
44*10462d6fSPaul E. McKenney 	if (rcu_cpu_stall_suppress == 2)
45*10462d6fSPaul E. McKenney 		rcu_cpu_stall_suppress = 0;
46*10462d6fSPaul E. McKenney }
47*10462d6fSPaul E. McKenney 
48*10462d6fSPaul E. McKenney static int rcu_panic(struct notifier_block *this, unsigned long ev, void *ptr)
49*10462d6fSPaul E. McKenney {
50*10462d6fSPaul E. McKenney 	rcu_cpu_stall_suppress = 1;
51*10462d6fSPaul E. McKenney 	return NOTIFY_DONE;
52*10462d6fSPaul E. McKenney }
53*10462d6fSPaul E. McKenney 
54*10462d6fSPaul E. McKenney static struct notifier_block rcu_panic_block = {
55*10462d6fSPaul E. McKenney 	.notifier_call = rcu_panic,
56*10462d6fSPaul E. McKenney };
57*10462d6fSPaul E. McKenney 
58*10462d6fSPaul E. McKenney static int __init check_cpu_stall_init(void)
59*10462d6fSPaul E. McKenney {
60*10462d6fSPaul E. McKenney 	atomic_notifier_chain_register(&panic_notifier_list, &rcu_panic_block);
61*10462d6fSPaul E. McKenney 	return 0;
62*10462d6fSPaul E. McKenney }
63*10462d6fSPaul E. McKenney early_initcall(check_cpu_stall_init);
64