--- 2.6/kernel/rcupdate.c 2004-08-20 19:59:22.000000000 +0200 +++ build-2.6/kernel/rcupdate.c 2004-08-20 20:46:35.952639280 +0200 @@ -237,14 +237,29 @@ * Clear it from the cpu mask and complete the grace period if it was the last * cpu. Start another grace period if someone has further entries pending */ -static void cpu_quiet(int cpu, struct rcu_ctrlblk *rcp, struct rcu_state *rsp) +static void cpu_quiet(int cpu, struct rcu_ctrlblk *rcp, struct rcu_state *rsp, + struct rcu_data *rdp, int force) { + spin_lock(&rsp->lock); + + if (unlikely(rcp->completed == rcp->cur)) + goto out_unlock; + /* + * RCU_quiescbatch/batch.cur and the cpu bitmap can come out of sync + * during cpu startup. Ignore the quiescent state if that happened. + */ + if (unlikely(rdp->quiescbatch != rcp->cur) && likely(!force)) + goto out_unlock; + cpu_clear(cpu, rsp->cpumask); if (cpus_empty(rsp->cpumask)) { /* batch completed ! */ rcp->completed = rcp->cur; rcu_start_batch(rcp, rsp, 0); } +out_unlock: + spin_unlock(&rsp->lock); + } /* @@ -279,15 +294,7 @@ return; rdp->qs_pending = 0; - spin_lock(&rsp->lock); - /* - * rdp->quiescbatch/rcp->cur and the cpu bitmap can come out of sync - * during cpu startup. Ignore the quiescent state. - */ - if (likely(rdp->quiescbatch == rcp->cur)) - cpu_quiet(rdp->cpu, rcp, rsp); - - spin_unlock(&rsp->lock); + cpu_quiet(rdp->cpu, rcp, rsp, rdp, 0); } @@ -314,10 +321,10 @@ * we can block indefinitely waiting for it, so flush * it here */ - spin_lock_bh(&rsp->lock); - if (rcp->cur != rcp->completed) - cpu_quiet(rdp->cpu, rcp, rsp); - spin_unlock_bh(&rsp->lock); + local_bh_disable(); + cpu_quiet(rdp->cpu, rcp, rsp, rdp, 1); + local_bh_enable(); + rcu_move_batch(this_rdp, rdp->curlist, rdp->curtail); rcu_move_batch(this_rdp, rdp->nxtlist, rdp->nxttail);