aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/rcutree.c40
1 files changed, 17 insertions, 23 deletions
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index f91a20c652b5..145f27fe3a1f 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -1141,37 +1141,31 @@ static void rcu_gp_cleanup(struct rcu_state *rsp)
1141 * they can do to advance the grace period. It is therefore 1141 * they can do to advance the grace period. It is therefore
1142 * safe for us to drop the lock in order to mark the grace 1142 * safe for us to drop the lock in order to mark the grace
1143 * period as completed in all of the rcu_node structures. 1143 * period as completed in all of the rcu_node structures.
1144 *
1145 * But if this CPU needs another grace period, it will take
1146 * care of this while initializing the next grace period.
1147 * We use RCU_WAIT_TAIL instead of the usual RCU_DONE_TAIL
1148 * because the callbacks have not yet been advanced: Those
1149 * callbacks are waiting on the grace period that just now
1150 * completed.
1151 */ 1144 */
1152 rdp = this_cpu_ptr(rsp->rda); 1145 raw_spin_unlock_irq(&rnp->lock);
1153 if (*rdp->nxttail[RCU_WAIT_TAIL] == NULL) {
1154 raw_spin_unlock_irq(&rnp->lock);
1155 1146
1156 /* 1147 /*
1157 * Propagate new ->completed value to rcu_node 1148 * Propagate new ->completed value to rcu_node structures so
1158 * structures so that other CPUs don't have to 1149 * that other CPUs don't have to wait until the start of the next
1159 * wait until the start of the next grace period 1150 * grace period to process their callbacks. This also avoids
1160 * to process their callbacks. 1151 * some nasty RCU grace-period initialization races by forcing
1161 */ 1152 * the end of the current grace period to be completely recorded in
1162 rcu_for_each_node_breadth_first(rsp, rnp) { 1153 * all of the rcu_node structures before the beginning of the next
1163 raw_spin_lock_irq(&rnp->lock); 1154 * grace period is recorded in any of the rcu_node structures.
1164 rnp->completed = rsp->gpnum; 1155 */
1165 raw_spin_unlock_irq(&rnp->lock); 1156 rcu_for_each_node_breadth_first(rsp, rnp) {
1166 cond_resched();
1167 }
1168 rnp = rcu_get_root(rsp);
1169 raw_spin_lock_irq(&rnp->lock); 1157 raw_spin_lock_irq(&rnp->lock);
1158 rnp->completed = rsp->gpnum;
1159 raw_spin_unlock_irq(&rnp->lock);
1160 cond_resched();
1170 } 1161 }
1162 rnp = rcu_get_root(rsp);
1163 raw_spin_lock_irq(&rnp->lock);
1171 1164
1172 rsp->completed = rsp->gpnum; /* Declare grace period done. */ 1165 rsp->completed = rsp->gpnum; /* Declare grace period done. */
1173 trace_rcu_grace_period(rsp->name, rsp->completed, "end"); 1166 trace_rcu_grace_period(rsp->name, rsp->completed, "end");
1174 rsp->fqs_state = RCU_GP_IDLE; 1167 rsp->fqs_state = RCU_GP_IDLE;
1168 rdp = this_cpu_ptr(rsp->rda);
1175 if (cpu_needs_another_gp(rsp, rdp)) 1169 if (cpu_needs_another_gp(rsp, rdp))
1176 rsp->gp_flags = 1; 1170 rsp->gp_flags = 1;
1177 raw_spin_unlock_irq(&rnp->lock); 1171 raw_spin_unlock_irq(&rnp->lock);