diff options
-rw-r--r-- | kernel/rcutree.c | 40 |
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); |