On 2023-06-23 18:51:24 [+0900], Tetsuo Handa wrote: > My understanding is that zonelist_iter_begin() accesses only zonelist_update_seq.seqcount . > From where is the zonelist_update_seq.lock accessed when zonelist_iter_begin() is called? zonelist_iter_begin() -> read_seqbegin() -> read_seqcount_begin() -> raw_read_seqcount_begin() -> __read_seqcount_begin() Now. The inner part looks like while ((__seq = seqprop_sequence(s)) & 1) cpu_relax(); but with RT enabled (in-tree, not out-of-tree, in-tree) seqprop_sequence() goes from: | __seqprop_##lockname##_sequence(const seqcount_##lockname##_t *s) \ | { \ | unsigned seq = READ_ONCE(s->seqcount.sequence); \ | \ | if (!IS_ENABLED(CONFIG_PREEMPT_RT)) \ | return seq; \ | \ | if (preemptible && unlikely(seq & 1)) { \ | __SEQ_LOCK(lock_acquire); \ | __SEQ_LOCK(lockbase##_unlock(s->lock)); \ | \ | /* \ | * Re-read the sequence counter since the (possibly \ | * preempted) writer made progress. \ | */ \ | seq = READ_ONCE(s->seqcount.sequence); \ | } \ | \ | return seq; \ to | unsigned __seqprop_spinlock_sequence(const seqcount_spinlock_t *s) | { | unsigned seq = READ_ONCE(s->seqcount.sequence); | | if (unlikely(seq & 1)) { | spin_lock(s->lock); | spin_unlock(s->lock); | seq = READ_ONCE(s->seqcount.sequence); | } | return seq; | } tada \o/ Sebastian