I have a question regarding using the circular buffer macros in the linux kernel.
I'm trying to use the circular buffer macros from include/linux/circ_buf.h.
The ACCESS_ONCE() macro is used to ensure that the compiler will read from memory the value, and not try to optimize the access.
In the documentation of circular buffer the following code is given as an example for the producer:
spin_lock(&producer_lock);
unsigned long head = buffer->head;
/* The spin_unlock() and next spin_lock() provide needed ordering. */
unsigned long tail = ACCESS_ONCE(buffer->tail);
if (CIRC_SPACE(head, tail, buffer->size) >= 1) {
/* insert one item into the buffer */
struct item *item = buffer[head];
produce_item(item);
smp_store_release(buffer->head,
(head + 1) & (buffer->size - 1));
/* wake_up() will make sure that the head is committed before
* waking anyone up */
wake_up(consumer);
}
spin_unlock(&producer_lock);
I have 3 questions:
What I'm not sure is, if I need to use ACCESS_ONCE when reading the value of buffer->tail, since in my function I need to read buffer->tail only once. I read the value at the start of the function and then use that value throughout the function. I assume that this example code was written with the idea that it runs in a loop and the new tail value must be read from memory in every iteration.
I thought if you have a single producer and a single consumer you don't need to use spinlocks. Why are spin locks used here?
Also there is this comment here:
/* wake_up() will make sure that the head is committed before * waking anyone up */
If I don't use wake_up in my code, do I need to use a memory barrier? Isn't smp_store_release() already issuing a memory barrier?