diff options
author | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2012-01-13 18:32:18 -0500 |
---|---|---|
committer | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2012-02-21 12:03:48 -0500 |
commit | 13cfcca0e4e2d4cee1d0183c049eb34e54ac976e (patch) | |
tree | 2aa48f0db717ae7741602022e4020f22cc3cea7f | |
parent | 27565d64a4e564e72c22d8c91a3cfcb9442383e8 (diff) |
rcu: Set RCU CPU stall times via sysfs
The default CONFIG_RCU_CPU_STALL_TIMEOUT value of 60 seconds has served
Linux users well for production use for quite some time. However, for
debugging, there will be more than three minutes between subsequent
stall-warning messages. This can be an annoyingly long wait if you
are trying to work out where the offending infinite loop is hiding.
Therefore, this commit provides a rcu_cpu_stall_timeout sysfs
parameter that may be adjusted at boot time and at runtime to speed
up debugging.
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
-rw-r--r-- | kernel/rcutree.c | 31 | ||||
-rw-r--r-- | kernel/rcutree.h | 6 |
2 files changed, 26 insertions, 11 deletions
diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 61adb351d2c7..cfdab9898e33 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c | |||
@@ -208,8 +208,11 @@ module_param(blimit, int, 0); | |||
208 | module_param(qhimark, int, 0); | 208 | module_param(qhimark, int, 0); |
209 | module_param(qlowmark, int, 0); | 209 | module_param(qlowmark, int, 0); |
210 | 210 | ||
211 | int rcu_cpu_stall_suppress __read_mostly; | 211 | int rcu_cpu_stall_suppress __read_mostly; /* 1 = suppress stall warnings. */ |
212 | int rcu_cpu_stall_timeout __read_mostly = CONFIG_RCU_CPU_STALL_TIMEOUT; | ||
213 | |||
212 | module_param(rcu_cpu_stall_suppress, int, 0644); | 214 | module_param(rcu_cpu_stall_suppress, int, 0644); |
215 | module_param(rcu_cpu_stall_timeout, int, 0644); | ||
213 | 216 | ||
214 | static void force_quiescent_state(struct rcu_state *rsp, int relaxed); | 217 | static void force_quiescent_state(struct rcu_state *rsp, int relaxed); |
215 | static int rcu_pending(int cpu); | 218 | static int rcu_pending(int cpu); |
@@ -645,10 +648,28 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp) | |||
645 | return rcu_implicit_offline_qs(rdp); | 648 | return rcu_implicit_offline_qs(rdp); |
646 | } | 649 | } |
647 | 650 | ||
651 | static int jiffies_till_stall_check(void) | ||
652 | { | ||
653 | int till_stall_check = ACCESS_ONCE(rcu_cpu_stall_timeout); | ||
654 | |||
655 | /* | ||
656 | * Limit check must be consistent with the Kconfig limits | ||
657 | * for CONFIG_RCU_CPU_STALL_TIMEOUT. | ||
658 | */ | ||
659 | if (till_stall_check < 3) { | ||
660 | ACCESS_ONCE(rcu_cpu_stall_timeout) = 3; | ||
661 | till_stall_check = 3; | ||
662 | } else if (till_stall_check > 300) { | ||
663 | ACCESS_ONCE(rcu_cpu_stall_timeout) = 300; | ||
664 | till_stall_check = 300; | ||
665 | } | ||
666 | return till_stall_check * HZ + RCU_STALL_DELAY_DELTA; | ||
667 | } | ||
668 | |||
648 | static void record_gp_stall_check_time(struct rcu_state *rsp) | 669 | static void record_gp_stall_check_time(struct rcu_state *rsp) |
649 | { | 670 | { |
650 | rsp->gp_start = jiffies; | 671 | rsp->gp_start = jiffies; |
651 | rsp->jiffies_stall = jiffies + RCU_SECONDS_TILL_STALL_CHECK; | 672 | rsp->jiffies_stall = jiffies + jiffies_till_stall_check(); |
652 | } | 673 | } |
653 | 674 | ||
654 | static void print_other_cpu_stall(struct rcu_state *rsp) | 675 | static void print_other_cpu_stall(struct rcu_state *rsp) |
@@ -667,7 +688,7 @@ static void print_other_cpu_stall(struct rcu_state *rsp) | |||
667 | raw_spin_unlock_irqrestore(&rnp->lock, flags); | 688 | raw_spin_unlock_irqrestore(&rnp->lock, flags); |
668 | return; | 689 | return; |
669 | } | 690 | } |
670 | rsp->jiffies_stall = jiffies + RCU_SECONDS_TILL_STALL_RECHECK; | 691 | rsp->jiffies_stall = jiffies + 3 * jiffies_till_stall_check() + 3; |
671 | 692 | ||
672 | /* | 693 | /* |
673 | * Now rat on any tasks that got kicked up to the root rcu_node | 694 | * Now rat on any tasks that got kicked up to the root rcu_node |
@@ -726,8 +747,8 @@ static void print_cpu_stall(struct rcu_state *rsp) | |||
726 | 747 | ||
727 | raw_spin_lock_irqsave(&rnp->lock, flags); | 748 | raw_spin_lock_irqsave(&rnp->lock, flags); |
728 | if (ULONG_CMP_GE(jiffies, rsp->jiffies_stall)) | 749 | if (ULONG_CMP_GE(jiffies, rsp->jiffies_stall)) |
729 | rsp->jiffies_stall = | 750 | rsp->jiffies_stall = jiffies + |
730 | jiffies + RCU_SECONDS_TILL_STALL_RECHECK; | 751 | 3 * jiffies_till_stall_check() + 3; |
731 | raw_spin_unlock_irqrestore(&rnp->lock, flags); | 752 | raw_spin_unlock_irqrestore(&rnp->lock, flags); |
732 | 753 | ||
733 | set_need_resched(); /* kick ourselves to get things going. */ | 754 | set_need_resched(); /* kick ourselves to get things going. */ |
diff --git a/kernel/rcutree.h b/kernel/rcutree.h index 58c9fc3bc820..0328a537846a 100644 --- a/kernel/rcutree.h +++ b/kernel/rcutree.h | |||
@@ -314,12 +314,6 @@ struct rcu_data { | |||
314 | #else | 314 | #else |
315 | #define RCU_STALL_DELAY_DELTA 0 | 315 | #define RCU_STALL_DELAY_DELTA 0 |
316 | #endif | 316 | #endif |
317 | |||
318 | #define RCU_SECONDS_TILL_STALL_CHECK (CONFIG_RCU_CPU_STALL_TIMEOUT * HZ + \ | ||
319 | RCU_STALL_DELAY_DELTA) | ||
320 | /* for rsp->jiffies_stall */ | ||
321 | #define RCU_SECONDS_TILL_STALL_RECHECK (3 * RCU_SECONDS_TILL_STALL_CHECK + 30) | ||
322 | /* for rsp->jiffies_stall */ | ||
323 | #define RCU_STALL_RAT_DELAY 2 /* Allow other CPUs time */ | 317 | #define RCU_STALL_RAT_DELAY 2 /* Allow other CPUs time */ |
324 | /* to take at least one */ | 318 | /* to take at least one */ |
325 | /* scheduling clock irq */ | 319 | /* scheduling clock irq */ |