aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/rcutree.c
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>2012-06-19 20:18:20 -0400
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2012-09-23 10:41:52 -0400
commit755609a9087fa983f567dc5452b2fa7b089b591f (patch)
tree8a0687cae001206535a22223efb73884daedde30 /kernel/rcutree.c
parent79bce6724366b3827c5c673fb07d7063082873cf (diff)
rcu: Allow RCU grace-period initialization to be preempted
RCU grace-period initialization is currently carried out with interrupts disabled, which can result in 200-microsecond latency spikes on systems on which RCU has been configured for 4096 CPUs. This patch therefore makes the RCU grace-period initialization be preemptible, which should eliminate those latency spikes. Similar spikes from grace-period cleanup and the forcing of quiescent states will be dealt with similarly by later patches. Reported-by: Mike Galbraith <mgalbraith@suse.de> Reported-by: Dimitri Sivanich <sivanich@sgi.com> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Reviewed-by: Josh Triplett <josh@joshtriplett.org>
Diffstat (limited to 'kernel/rcutree.c')
-rw-r--r--kernel/rcutree.c26
1 files changed, 11 insertions, 15 deletions
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index e7a534498aa0..781e5f0b7b17 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -1030,7 +1030,7 @@ rcu_start_gp_per_cpu(struct rcu_state *rsp, struct rcu_node *rnp, struct rcu_dat
1030/* 1030/*
1031 * Body of kthread that handles grace periods. 1031 * Body of kthread that handles grace periods.
1032 */ 1032 */
1033static int rcu_gp_kthread(void *arg) 1033static int __noreturn rcu_gp_kthread(void *arg)
1034{ 1034{
1035 struct rcu_data *rdp; 1035 struct rcu_data *rdp;
1036 struct rcu_node *rnp; 1036 struct rcu_node *rnp;
@@ -1056,6 +1056,7 @@ static int rcu_gp_kthread(void *arg)
1056 * don't start another one. 1056 * don't start another one.
1057 */ 1057 */
1058 raw_spin_unlock_irq(&rnp->lock); 1058 raw_spin_unlock_irq(&rnp->lock);
1059 cond_resched();
1059 continue; 1060 continue;
1060 } 1061 }
1061 1062
@@ -1066,6 +1067,7 @@ static int rcu_gp_kthread(void *arg)
1066 */ 1067 */
1067 rsp->fqs_need_gp = 1; 1068 rsp->fqs_need_gp = 1;
1068 raw_spin_unlock_irq(&rnp->lock); 1069 raw_spin_unlock_irq(&rnp->lock);
1070 cond_resched();
1069 continue; 1071 continue;
1070 } 1072 }
1071 1073
@@ -1076,10 +1078,10 @@ static int rcu_gp_kthread(void *arg)
1076 rsp->fqs_state = RCU_GP_INIT; /* Stop force_quiescent_state. */ 1078 rsp->fqs_state = RCU_GP_INIT; /* Stop force_quiescent_state. */
1077 rsp->jiffies_force_qs = jiffies + RCU_JIFFIES_TILL_FORCE_QS; 1079 rsp->jiffies_force_qs = jiffies + RCU_JIFFIES_TILL_FORCE_QS;
1078 record_gp_stall_check_time(rsp); 1080 record_gp_stall_check_time(rsp);
1079 raw_spin_unlock(&rnp->lock); /* leave irqs disabled. */ 1081 raw_spin_unlock_irq(&rnp->lock);
1080 1082
1081 /* Exclude any concurrent CPU-hotplug operations. */ 1083 /* Exclude any concurrent CPU-hotplug operations. */
1082 raw_spin_lock(&rsp->onofflock); /* irqs already disabled. */ 1084 get_online_cpus();
1083 1085
1084 /* 1086 /*
1085 * Set the quiescent-state-needed bits in all the rcu_node 1087 * Set the quiescent-state-needed bits in all the rcu_node
@@ -1091,15 +1093,9 @@ static int rcu_gp_kthread(void *arg)
1091 * indicate that no grace period is in progress, at least 1093 * indicate that no grace period is in progress, at least
1092 * until the corresponding leaf node has been initialized. 1094 * until the corresponding leaf node has been initialized.
1093 * In addition, we have excluded CPU-hotplug operations. 1095 * In addition, we have excluded CPU-hotplug operations.
1094 *
1095 * Note that the grace period cannot complete until
1096 * we finish the initialization process, as there will
1097 * be at least one qsmask bit set in the root node until
1098 * that time, namely the one corresponding to this CPU,
1099 * due to the fact that we have irqs disabled.
1100 */ 1096 */
1101 rcu_for_each_node_breadth_first(rsp, rnp) { 1097 rcu_for_each_node_breadth_first(rsp, rnp) {
1102 raw_spin_lock(&rnp->lock); /* irqs already disabled. */ 1098 raw_spin_lock_irq(&rnp->lock);
1103 rcu_preempt_check_blocked_tasks(rnp); 1099 rcu_preempt_check_blocked_tasks(rnp);
1104 rnp->qsmask = rnp->qsmaskinit; 1100 rnp->qsmask = rnp->qsmaskinit;
1105 rnp->gpnum = rsp->gpnum; 1101 rnp->gpnum = rsp->gpnum;
@@ -1110,17 +1106,17 @@ static int rcu_gp_kthread(void *arg)
1110 trace_rcu_grace_period_init(rsp->name, rnp->gpnum, 1106 trace_rcu_grace_period_init(rsp->name, rnp->gpnum,
1111 rnp->level, rnp->grplo, 1107 rnp->level, rnp->grplo,
1112 rnp->grphi, rnp->qsmask); 1108 rnp->grphi, rnp->qsmask);
1113 raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */ 1109 raw_spin_unlock_irq(&rnp->lock);
1110 cond_resched();
1114 } 1111 }
1115 1112
1116 rnp = rcu_get_root(rsp); 1113 rnp = rcu_get_root(rsp);
1117 raw_spin_lock(&rnp->lock); /* irqs already disabled. */ 1114 raw_spin_lock_irq(&rnp->lock);
1118 /* force_quiescent_state() now OK. */ 1115 /* force_quiescent_state() now OK. */
1119 rsp->fqs_state = RCU_SIGNAL_INIT; 1116 rsp->fqs_state = RCU_SIGNAL_INIT;
1120 raw_spin_unlock(&rnp->lock); /* irqs remain disabled. */ 1117 raw_spin_unlock_irq(&rnp->lock);
1121 raw_spin_unlock_irq(&rsp->onofflock); 1118 put_online_cpus();
1122 } 1119 }
1123 return 0;
1124} 1120}
1125 1121
1126/* 1122/*