aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>2010-02-26 19:38:58 -0500
committerIngo Molnar <mingo@elte.hu>2010-02-27 03:53:53 -0500
commit71da81324c83ef65bb196c7f874ac1c6996d8287 (patch)
treeb470c5769ad88d2e2af8fe25cc84e7df85fb3d7c /kernel
parent0b1c87278a8c7e394022ec184a0b44a3886b6fde (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')
-rw-r--r--kernel/rcutree_plugin.h10
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
988static DEFINE_PER_CPU(int, rcu_dyntick_drain); 988static DEFINE_PER_CPU(int, rcu_dyntick_drain);
989static 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)
1050static void rcu_needs_cpu_flush(void) 1055static 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) */