diff options
author | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2010-02-26 19:38:58 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-02-27 03:53:53 -0500 |
commit | 71da81324c83ef65bb196c7f874ac1c6996d8287 (patch) | |
tree | b470c5769ad88d2e2af8fe25cc84e7df85fb3d7c /kernel/rcutree_plugin.h | |
parent | 0b1c87278a8c7e394022ec184a0b44a3886b6fde (diff) |
rcu: Fix accelerated GPs for last non-dynticked CPU
This patch disables irqs across the call to rcu_needs_cpu(). It
also enforces a hold-off period so that the idle loop doesn't
softirq itself to death when there are lots of RCU callbacks in
flight on the last non-dynticked CPU.
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: laijs@cn.fujitsu.com
Cc: dipankar@in.ibm.com
Cc: mathieu.desnoyers@polymtl.ca
Cc: josh@joshtriplett.org
Cc: dvhltc@us.ibm.com
Cc: niv@us.ibm.com
Cc: peterz@infradead.org
Cc: rostedt@goodmis.org
Cc: Valdis.Kletnieks@vt.edu
Cc: dhowells@redhat.com
LKML-Reference: <1267231138-27856-3-git-send-email-paulmck@linux.vnet.ibm.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/rcutree_plugin.h')
-rw-r--r-- | kernel/rcutree_plugin.h | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index ed241fc478f0..464ad2cdee00 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h | |||
@@ -986,6 +986,7 @@ static void rcu_needs_cpu_flush(void) | |||
986 | 986 | ||
987 | #define RCU_NEEDS_CPU_FLUSHES 5 | 987 | #define RCU_NEEDS_CPU_FLUSHES 5 |
988 | static DEFINE_PER_CPU(int, rcu_dyntick_drain); | 988 | static DEFINE_PER_CPU(int, rcu_dyntick_drain); |
989 | static DEFINE_PER_CPU(unsigned long, rcu_dyntick_holdoff); | ||
989 | 990 | ||
990 | /* | 991 | /* |
991 | * Check to see if any future RCU-related work will need to be done | 992 | * Check to see if any future RCU-related work will need to be done |
@@ -1013,6 +1014,7 @@ int rcu_needs_cpu(int cpu) | |||
1013 | for_each_cpu_not(thatcpu, nohz_cpu_mask) | 1014 | for_each_cpu_not(thatcpu, nohz_cpu_mask) |
1014 | if (thatcpu != cpu) { | 1015 | if (thatcpu != cpu) { |
1015 | per_cpu(rcu_dyntick_drain, cpu) = 0; | 1016 | per_cpu(rcu_dyntick_drain, cpu) = 0; |
1017 | per_cpu(rcu_dyntick_holdoff, cpu) = jiffies - 1; | ||
1016 | return rcu_needs_cpu_quick_check(cpu); | 1018 | return rcu_needs_cpu_quick_check(cpu); |
1017 | } | 1019 | } |
1018 | 1020 | ||
@@ -1022,6 +1024,7 @@ int rcu_needs_cpu(int cpu) | |||
1022 | per_cpu(rcu_dyntick_drain, cpu) = RCU_NEEDS_CPU_FLUSHES; | 1024 | per_cpu(rcu_dyntick_drain, cpu) = RCU_NEEDS_CPU_FLUSHES; |
1023 | } else if (--per_cpu(rcu_dyntick_drain, cpu) <= 0) { | 1025 | } else if (--per_cpu(rcu_dyntick_drain, cpu) <= 0) { |
1024 | /* We have hit the limit, so time to give up. */ | 1026 | /* We have hit the limit, so time to give up. */ |
1027 | per_cpu(rcu_dyntick_holdoff, cpu) = jiffies; | ||
1025 | return rcu_needs_cpu_quick_check(cpu); | 1028 | return rcu_needs_cpu_quick_check(cpu); |
1026 | } | 1029 | } |
1027 | 1030 | ||
@@ -1038,8 +1041,10 @@ int rcu_needs_cpu(int cpu) | |||
1038 | } | 1041 | } |
1039 | 1042 | ||
1040 | /* If RCU callbacks are still pending, RCU still needs this CPU. */ | 1043 | /* If RCU callbacks are still pending, RCU still needs this CPU. */ |
1041 | if (c) | 1044 | if (c) { |
1042 | raise_softirq(RCU_SOFTIRQ); | 1045 | raise_softirq(RCU_SOFTIRQ); |
1046 | per_cpu(rcu_dyntick_holdoff, cpu) = jiffies; | ||
1047 | } | ||
1043 | return c; | 1048 | return c; |
1044 | } | 1049 | } |
1045 | 1050 | ||
@@ -1050,10 +1055,13 @@ int rcu_needs_cpu(int cpu) | |||
1050 | static void rcu_needs_cpu_flush(void) | 1055 | static void rcu_needs_cpu_flush(void) |
1051 | { | 1056 | { |
1052 | int cpu = smp_processor_id(); | 1057 | int cpu = smp_processor_id(); |
1058 | unsigned long flags; | ||
1053 | 1059 | ||
1054 | if (per_cpu(rcu_dyntick_drain, cpu) <= 0) | 1060 | if (per_cpu(rcu_dyntick_drain, cpu) <= 0) |
1055 | return; | 1061 | return; |
1062 | local_irq_save(flags); | ||
1056 | (void)rcu_needs_cpu(cpu); | 1063 | (void)rcu_needs_cpu(cpu); |
1064 | local_irq_restore(flags); | ||
1057 | } | 1065 | } |
1058 | 1066 | ||
1059 | #endif /* #else #if !defined(CONFIG_RCU_FAST_NO_HZ) */ | 1067 | #endif /* #else #if !defined(CONFIG_RCU_FAST_NO_HZ) */ |