Understanding Linux Kernel Circular Buffer
For the producer:
- The
spin_lock()
here is to prevent two producers from trying to modify the queue at the same time. ACCESS_ONCE
does prevent reordering, it also prevents the compiler from reloading the value later. (There's an article aboutACCESS_ONCE
on LWN that expands on this further)- Correct.
- Also correct.
- The (implied) write barrier here is needed before waking the consumer as otherwise the consumer might not see the updated
head
value.
Consumer:
smp_read_barrier_depends()
is a data dependency barrier, which is a weaker form of a read barrier (see 2). The effect in this case is to ensure thatbuffer->tail
is read before using it as an array index inbuffer[tail]
.smp_mb()
here is a full memory barrier, ensuring all reads and writes are committed by this point.
Additional references:
(Note: I'm not entirely sure about my answers for 5 in the producer and 1 for the consumer, but I believe they're a fair approximation of the facts. I highly recommend reading the documentation page about memory barriers, as it's more comprehensive than anything I could write here.)