aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorPaul E. McKenney <paul.mckenney@linaro.org>2011-11-22 20:07:11 -0500
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2011-12-11 13:32:00 -0500
commit3084f2f80cc8a1fd66233722d88beac0fe85e26f (patch)
treebce77805235278599eda0572d5d36b11419681d7 /kernel
parent433cdddcd9ac5558068edd7f8d4707a70f7710f5 (diff)
rcu: Go dyntick-idle more quickly if CPU has serviced current grace period
The earlier version would attempt to push callbacks through five times before going into dyntick-idle mode if callbacks remained, but the CPU had done all that it needed to do for the current RCU grace periods. This is wasteful: In most cases, once the CPU has done all that it needs to for the current RCU grace periods, it will make no further progress on the callbacks no matter how many times it loops through the RCU core processing and the idle-entry code. This commit therefore goes to dyntick-idle mode whenever the current CPU has done all it can for the current grace period. Signed-off-by: Paul E. McKenney <paul.mckenney@linaro.org> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/rcutree_plugin.h24
1 files changed, 18 insertions, 6 deletions
diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h
index 6467f5669ab7..45790bfb6e8c 100644
--- a/kernel/rcutree_plugin.h
+++ b/kernel/rcutree_plugin.h
@@ -2028,12 +2028,29 @@ static void rcu_prepare_for_idle(int cpu)
2028{ 2028{
2029 int c = 0; 2029 int c = 0;
2030 2030
2031 /* If no callbacks or in the holdoff period, enter dyntick-idle. */ 2031 /*
2032 * If there are no callbacks on this CPU or if RCU has no further
2033 * need for this CPU at the moment, enter dyntick-idle mode.
2034 * Also reset state so as to not prejudice later attempts.
2035 */
2032 if (!rcu_cpu_has_callbacks(cpu)) { 2036 if (!rcu_cpu_has_callbacks(cpu)) {
2033 per_cpu(rcu_dyntick_holdoff, cpu) = jiffies - 1; 2037 per_cpu(rcu_dyntick_holdoff, cpu) = jiffies - 1;
2038 per_cpu(rcu_dyntick_drain, cpu) = 0;
2034 trace_rcu_prep_idle("No callbacks"); 2039 trace_rcu_prep_idle("No callbacks");
2035 return; 2040 return;
2036 } 2041 }
2042 if (!rcu_pending(cpu)) {
2043 trace_rcu_prep_idle("Dyntick with callbacks");
2044 per_cpu(rcu_dyntick_holdoff, cpu) = jiffies - 1;
2045 per_cpu(rcu_dyntick_drain, cpu) = 0;
2046 per_cpu(rcu_awake_at_gp_end, cpu) = 1;
2047 return; /* Nothing to do immediately. */
2048 }
2049
2050 /*
2051 * If in holdoff mode, just return. We will presumably have
2052 * refrained from disabling the scheduling-clock tick.
2053 */
2037 if (per_cpu(rcu_dyntick_holdoff, cpu) == jiffies) { 2054 if (per_cpu(rcu_dyntick_holdoff, cpu) == jiffies) {
2038 trace_rcu_prep_idle("In holdoff"); 2055 trace_rcu_prep_idle("In holdoff");
2039 return; 2056 return;
@@ -2046,11 +2063,6 @@ static void rcu_prepare_for_idle(int cpu)
2046 } else if (--per_cpu(rcu_dyntick_drain, cpu) <= 0) { 2063 } else if (--per_cpu(rcu_dyntick_drain, cpu) <= 0) {
2047 /* We have hit the limit, so time to give up. */ 2064 /* We have hit the limit, so time to give up. */
2048 per_cpu(rcu_dyntick_holdoff, cpu) = jiffies; 2065 per_cpu(rcu_dyntick_holdoff, cpu) = jiffies;
2049 if (!rcu_pending(cpu)) {
2050 trace_rcu_prep_idle("Dyntick with callbacks");
2051 per_cpu(rcu_awake_at_gp_end, cpu) = 1;
2052 return; /* Nothing to do immediately. */
2053 }
2054 trace_rcu_prep_idle("Begin holdoff"); 2066 trace_rcu_prep_idle("Begin holdoff");
2055 invoke_rcu_core(); /* Force the CPU out of dyntick-idle. */ 2067 invoke_rcu_core(); /* Force the CPU out of dyntick-idle. */
2056 return; 2068 return;