diff options
-rw-r--r-- | kernel/rcutree.c | 8 | ||||
-rw-r--r-- | kernel/rcutree.h | 5 |
2 files changed, 13 insertions, 0 deletions
diff --git a/kernel/rcutree.c b/kernel/rcutree.c index d9202857d3ad..55e8f6ef8195 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c | |||
@@ -660,6 +660,8 @@ rcu_start_gp(struct rcu_state *rsp, unsigned long flags) | |||
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) || rsp->fqs_active) { | 662 | if (!cpu_needs_another_gp(rsp, rdp) || rsp->fqs_active) { |
663 | if (cpu_needs_another_gp(rsp, rdp)) | ||
664 | rsp->fqs_need_gp = 1; | ||
663 | if (rnp->completed == rsp->completed) { | 665 | if (rnp->completed == rsp->completed) { |
664 | spin_unlock_irqrestore(&rnp->lock, flags); | 666 | spin_unlock_irqrestore(&rnp->lock, flags); |
665 | return; | 667 | return; |
@@ -1239,6 +1241,12 @@ static void force_quiescent_state(struct rcu_state *rsp, int relaxed) | |||
1239 | break; | 1241 | break; |
1240 | } | 1242 | } |
1241 | rsp->fqs_active = 0; | 1243 | rsp->fqs_active = 0; |
1244 | if (rsp->fqs_need_gp) { | ||
1245 | spin_unlock(&rsp->fqslock); /* irqs remain disabled */ | ||
1246 | rsp->fqs_need_gp = 0; | ||
1247 | rcu_start_gp(rsp, flags); /* releases rnp->lock */ | ||
1248 | return; | ||
1249 | } | ||
1242 | spin_unlock(&rnp->lock); /* irqs remain disabled */ | 1250 | spin_unlock(&rnp->lock); /* irqs remain disabled */ |
1243 | unlock_fqs_ret: | 1251 | unlock_fqs_ret: |
1244 | spin_unlock_irqrestore(&rsp->fqslock, flags); | 1252 | spin_unlock_irqrestore(&rsp->fqslock, flags); |
diff --git a/kernel/rcutree.h b/kernel/rcutree.h index edb6fae0fa94..bd5d78ad1c48 100644 --- a/kernel/rcutree.h +++ b/kernel/rcutree.h | |||
@@ -278,6 +278,11 @@ struct rcu_state { | |||
278 | /* Force QS state. */ | 278 | /* Force QS state. */ |
279 | u8 fqs_active; /* force_quiescent_state() */ | 279 | u8 fqs_active; /* force_quiescent_state() */ |
280 | /* is running. */ | 280 | /* is running. */ |
281 | u8 fqs_need_gp; /* A CPU was prevented from */ | ||
282 | /* starting a new grace */ | ||
283 | /* period because */ | ||
284 | /* force_quiescent_state() */ | ||
285 | /* was running. */ | ||
281 | long gpnum; /* Current gp number. */ | 286 | long gpnum; /* Current gp number. */ |
282 | long completed; /* # of last completed gp. */ | 287 | long completed; /* # of last completed gp. */ |
283 | 288 | ||