Re: [PATCH v2] introduce atomic_pointer to fix a race condition in cancelable mcs spinlocks

Eric Dumazet
2014-06-02T22:44:52Z

On Mon, 2014-06-02 at 15:08 -0700, Paul E. McKenney wrote:

> diff --git a/kernel/rcu/srcu.c b/kernel/rcu/srcu.c
> index c639556f3fa0..c0120279dead 100644
> --- a/kernel/rcu/srcu.c
> +++ b/kernel/rcu/srcu.c
> @@ -295,12 +295,15 @@ EXPORT_SYMBOL_GPL(cleanup_srcu_struct);
> int __srcu_read_lock(struct srcu_struct *sp)
> {
> int idx;
> + unsigned long *lp;
>
> idx = ACCESS_ONCE(sp->completed) & 0x1;
> preempt_disable();
> - ACCESS_ONCE(this_cpu_ptr(sp->per_cpu_ref)->c[idx]) += 1;
> + lp = this_cpu_ptr(&sp->per_cpu_ref->c[idx]);
> + ACCESS_ONCE(*lp) = *lp + 1;
> smp_mb(); /* B */ /* Avoid leaking the critical section. */
> - ACCESS_ONCE(this_cpu_ptr(sp->per_cpu_ref)->seq[idx]) += 1;
> + lp = this_cpu_ptr(&sp->per_cpu_ref->seq[idx]);
> + ACCESS_ONCE(*lp) = *lp + 1;
> preempt_enable();
> return idx;
>

This probably could use the following

diff --git a/kernel/rcu/srcu.c b/kernel/rcu/srcu.c
index c639556f3fa0..3a97eb6f9076 100644
--- a/kernel/rcu/srcu.c
+++ b/kernel/rcu/srcu.c
@@ -298,9 +298,9 @@ int __srcu_read_lock(struct srcu_struct *sp)

idx = ACCESS_ONCE(sp->completed) & 0x1;
preempt_disable();
- ACCESS_ONCE(this_cpu_ptr(sp->per_cpu_ref)->c[idx]) += 1;
+ this_cpu_inc(sp->per_cpu_ref->c[idx]);
smp_mb(); /* B */ /* Avoid leaking the critical section. */
- ACCESS_ONCE(this_cpu_ptr(sp->per_cpu_ref)->seq[idx]) += 1;
+ this_cpu_inc(sp->per_cpu_ref->seq[idx]);
preempt_enable();
return idx;
}