diff options
-rw-r--r-- | kernel/rcutree.c | 31 | ||||
-rw-r--r-- | kernel/rcutree.h | 2 |
2 files changed, 19 insertions, 14 deletions
diff --git a/kernel/rcutree.c b/kernel/rcutree.c index d42ad30c4d70..41688ff60e07 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c | |||
@@ -659,7 +659,7 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags) | |||
659 | struct rcu_data *rdp = rsp->rda[smp_processor_id()]; | 659 | struct rcu_data *rdp = rsp->rda[smp_processor_id()]; |
660 | struct rcu_node *rnp = rcu_get_root(rsp); | 660 | struct rcu_node *rnp = rcu_get_root(rsp); |
661 | 661 | ||
662 | if (!cpu_needs_another_gp(rsp, rdp)) { | 662 | if (!cpu_needs_another_gp(rsp, rdp) || rsp->fqs_active) { |
663 | if (rnp->completed == rsp->completed) { | 663 | if (rnp->completed == rsp->completed) { |
664 | spin_unlock_irqrestore(&rnp->lock, flags); | 664 | spin_unlock_irqrestore(&rnp->lock, flags); |
665 | return; | 665 | return; |
@@ -1195,6 +1195,7 @@ static void force_quiescent_state(struct rcu_state *rsp, int relaxed) | |||
1195 | struct rcu_node *rnp = rcu_get_root(rsp); | 1195 | struct rcu_node *rnp = rcu_get_root(rsp); |
1196 | u8 signaled; | 1196 | u8 signaled; |
1197 | u8 forcenow; | 1197 | u8 forcenow; |
1198 | u8 gpdone; | ||
1198 | 1199 | ||
1199 | if (!rcu_gp_in_progress(rsp)) | 1200 | if (!rcu_gp_in_progress(rsp)) |
1200 | return; /* No grace period in progress, nothing to force. */ | 1201 | return; /* No grace period in progress, nothing to force. */ |
@@ -1206,15 +1207,16 @@ static void force_quiescent_state(struct rcu_state *rsp, int relaxed) | |||
1206 | (long)(rsp->jiffies_force_qs - jiffies) >= 0) | 1207 | (long)(rsp->jiffies_force_qs - jiffies) >= 0) |
1207 | goto unlock_fqs_ret; /* no emergency and done recently. */ | 1208 | goto unlock_fqs_ret; /* no emergency and done recently. */ |
1208 | rsp->n_force_qs++; | 1209 | rsp->n_force_qs++; |
1209 | spin_lock(&rnp->lock); | 1210 | spin_lock(&rnp->lock); /* irqs already disabled */ |
1210 | lastcomp = rsp->gpnum - 1; | 1211 | lastcomp = rsp->gpnum - 1; |
1211 | signaled = rsp->signaled; | 1212 | signaled = rsp->signaled; |
1212 | rsp->jiffies_force_qs = jiffies + RCU_JIFFIES_TILL_FORCE_QS; | 1213 | rsp->jiffies_force_qs = jiffies + RCU_JIFFIES_TILL_FORCE_QS; |
1213 | if(!rcu_gp_in_progress(rsp)) { | 1214 | if(!rcu_gp_in_progress(rsp)) { |
1214 | rsp->n_force_qs_ngp++; | 1215 | rsp->n_force_qs_ngp++; |
1215 | spin_unlock(&rnp->lock); | 1216 | spin_unlock(&rnp->lock); /* irqs remain disabled */ |
1216 | goto unlock_fqs_ret; /* no GP in progress, time updated. */ | 1217 | goto unlock_fqs_ret; /* no GP in progress, time updated. */ |
1217 | } | 1218 | } |
1219 | rsp->fqs_active = 1; | ||
1218 | switch (signaled) { | 1220 | switch (signaled) { |
1219 | case RCU_GP_IDLE: | 1221 | case RCU_GP_IDLE: |
1220 | case RCU_GP_INIT: | 1222 | case RCU_GP_INIT: |
@@ -1223,15 +1225,16 @@ static void force_quiescent_state(struct rcu_state *rsp, int relaxed) | |||
1223 | 1225 | ||
1224 | case RCU_SAVE_DYNTICK: | 1226 | case RCU_SAVE_DYNTICK: |
1225 | 1227 | ||
1226 | spin_unlock(&rnp->lock); | 1228 | spin_unlock(&rnp->lock); /* irqs remain disabled */ |
1227 | if (RCU_SIGNAL_INIT != RCU_SAVE_DYNTICK) | 1229 | if (RCU_SIGNAL_INIT != RCU_SAVE_DYNTICK) |
1228 | break; /* So gcc recognizes the dead code. */ | 1230 | break; /* So gcc recognizes the dead code. */ |
1229 | 1231 | ||
1230 | /* Record dyntick-idle state. */ | 1232 | /* Record dyntick-idle state. */ |
1231 | if (rcu_process_dyntick(rsp, lastcomp, | 1233 | gpdone = rcu_process_dyntick(rsp, lastcomp, |
1232 | dyntick_save_progress_counter)) | 1234 | dyntick_save_progress_counter); |
1233 | goto unlock_fqs_ret; | 1235 | spin_lock(&rnp->lock); /* irqs already disabled */ |
1234 | spin_lock(&rnp->lock); | 1236 | if (gpdone) |
1237 | break; | ||
1235 | /* fall into next case. */ | 1238 | /* fall into next case. */ |
1236 | 1239 | ||
1237 | case RCU_SAVE_COMPLETED: | 1240 | case RCU_SAVE_COMPLETED: |
@@ -1252,17 +1255,17 @@ static void force_quiescent_state(struct rcu_state *rsp, int relaxed) | |||
1252 | case RCU_FORCE_QS: | 1255 | case RCU_FORCE_QS: |
1253 | 1256 | ||
1254 | /* Check dyntick-idle state, send IPI to laggarts. */ | 1257 | /* Check dyntick-idle state, send IPI to laggarts. */ |
1255 | spin_unlock(&rnp->lock); | 1258 | spin_unlock(&rnp->lock); /* irqs remain disabled */ |
1256 | if (rcu_process_dyntick(rsp, rsp->completed_fqs, | 1259 | gpdone = rcu_process_dyntick(rsp, rsp->completed_fqs, |
1257 | rcu_implicit_dynticks_qs)) | 1260 | rcu_implicit_dynticks_qs); |
1258 | goto unlock_fqs_ret; | ||
1259 | 1261 | ||
1260 | /* Leave state in case more forcing is required. */ | 1262 | /* Leave state in case more forcing is required. */ |
1261 | 1263 | ||
1262 | spin_lock(&rnp->lock); | 1264 | spin_lock(&rnp->lock); /* irqs already disabled */ |
1263 | break; | 1265 | break; |
1264 | } | 1266 | } |
1265 | spin_unlock(&rnp->lock); | 1267 | rsp->fqs_active = 0; |
1268 | spin_unlock(&rnp->lock); /* irqs remain disabled */ | ||
1266 | unlock_fqs_ret: | 1269 | unlock_fqs_ret: |
1267 | spin_unlock_irqrestore(&rsp->fqslock, flags); | 1270 | spin_unlock_irqrestore(&rsp->fqslock, flags); |
1268 | } | 1271 | } |
diff --git a/kernel/rcutree.h b/kernel/rcutree.h index d2a0046f63b2..dc386a7c634f 100644 --- a/kernel/rcutree.h +++ b/kernel/rcutree.h | |||
@@ -277,6 +277,8 @@ struct rcu_state { | |||
277 | 277 | ||
278 | u8 signaled ____cacheline_internodealigned_in_smp; | 278 | u8 signaled ____cacheline_internodealigned_in_smp; |
279 | /* Force QS state. */ | 279 | /* Force QS state. */ |
280 | u8 fqs_active; /* force_quiescent_state() */ | ||
281 | /* is running. */ | ||
280 | long gpnum; /* Current gp number. */ | 282 | long gpnum; /* Current gp number. */ |
281 | long completed; /* # of last completed gp. */ | 283 | long completed; /* # of last completed gp. */ |
282 | 284 | ||