On Wed, Dec 18, 2024 at 08:21:14AM -0500, Elad Lahav wrote: > On Tue, Dec 17, 2024 at 9:05 PM Daniel Xu <dxu@xxxxxxxxx> wrote: > > My understanding is that read_seqbegin() and read_seqretry() > > can execute at any time. That means the read side access of > > the sequence number can occur doing an increment. > > > > To prevent the reader from reading a partially written value, > > we need the WRITE_ONCE() to ensure the relaxed atomic > > write. > > Hi Daniel, > > This seems very odd to me. Assuming that the lock field is of an > atomic type, no reader will ever see a partial write. > By "atomic" I don't mean subject to atomic read-modify-write > operations, but simply that the hardware always completes a write to > the value before it is made visible to any observers. This should be > true for all aligned integral types in all modern architectures. Real compilers really do tear non-volatile stores. For example, when storing certain constants (0x10002 comes to mind) into 32-bit variables on systems with store-immediate instructions having short immediate fields, some compilers generate a pair of 16-bit store-immediate instructions instead of forming the 32-bit constant in a register and then storing the register. And for a single-threaded program without interrupt handlers, this is an eminently reasonable optimization. > Also, I don't believe WRITE_ONCE() imposes any atomicity where none > exists. I'm not a Linux kernel developer, but from what I can tell all > it does is wrap a pointer with volatile, to ensure that the compiler > does not optimize-away the write. In this case I don't see how the > compiler can ignore seq->lock++ between a spin lock and a barrier. Agreed, if you do a volatile store of a 64Kbyte structure, the compiler does not have much alternative to tearing that store. But in modern compilers, if the corresponding atomic type is always lock-free, then a volatile operation on the underlying (non-atomic) type should never tear. Thanx, Paul