diff options
author | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2012-06-19 20:18:20 -0400 |
---|---|---|
committer | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2012-09-23 10:41:52 -0400 |
commit | 755609a9087fa983f567dc5452b2fa7b089b591f (patch) | |
tree | 8a0687cae001206535a22223efb73884daedde30 /kernel/rcutree.c | |
parent | 79bce6724366b3827c5c673fb07d7063082873cf (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.c | 26 |
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 | */ |
1033 | static int rcu_gp_kthread(void *arg) | 1033 | static 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 | /* |