<div dir="ltr">Hi all,<div><br></div><div>I wonder if it is safe to use a spin lock on RCU writers?</div><div>Here's the sample code:</div><div><br></div><div>#include <stdbool.h></div><div>#include <stdatomic.h></div><div><br></div><div>static atomic_bool lock;</div><div><br></div><div>void writer(...) {</div><div>  while (atomic_fetch_or(&lock, true)) {}  // spin lock</div><div>  // Update rcu guarded pointers (code omitted)</div><div>  synchronize_rcu(); // potential dead lock?</div><div>  atomic_store(&lock, false);</div><div>}</div><div><br></div><div>My concern is, in a classical RCU model, the code snippet above may introduce a dead lock.</div><div>Assume we use the pseudo RCU implementation given in the linux kernel manual:</div><div><pre style="word-wrap:break-word"><font color="#000000"><span style="white-space:pre-wrap">    void rcu_read_lock(void) { }

        void rcu_read_unlock(void) { }

        void synchronize_rcu(void)
        {
                int cpu;

                for_each_possible_cpu(cpu)
                        run_on(cpu);
        }<br></span></font></pre>When we try to run `for_each_possible_cpu(cpu)`, wouldn't it stuck on the writer's spin lock?</div><div><br></div><div>Here's my dead lock scenario.</div><div>We have two writer thread T1 T2, they executed in following order:</div><div>1. T1 enters writer(...), acquires the spin lock and set it to true</div><div>2. T2 enters writer(...), tries to acquire the spin lock but failed. It spins on the while loop.</div><div>3. T1 finishes updating rcu guarded pointer.</div><div>4. T1 calls synchronize_rcu(), which should put T1 on each CPU</div><div>5. T1 couldn't run on the CPU T2 occupies, because it is in a spin lock.</div><div>Therefore we enters a dead lock.</div><div><br></div><div>Is this a possible scenario, or it is already addressed in practice?</div><div>Maybe the way I write the spin lock is incorrect? Do I have to write it in this way?</div><div><br></div><div>while (atomic_fetch_or(&lock, true)) {</div><div>  rcu_thread_offline();</div><div>  // other candidates:</div><div>  // sched_yield();</div><div>  // rcu_quiescent_state();</div><div>}</div><div><br></div><div>Please help to advice,</div><div>Thanks!</div><div><br></div><div>Felix</div></div>