There is an article at: http://lwn.net/Articles/378262/ that describes the Linux kernels circular buffer implementation. I have some questions:
Here is the "producer":
spin_lock(&producer_lock);
unsigned long head = buffer->head;
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_wmb(); /* commit the item before incrementing the head */
    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);
Questions:
Here is the "consumer":
spin_lock(&consumer_lock);
unsigned long head = ACCESS_ONCE(buffer->head);
unsigned long tail = buffer->tail;
if (CIRC_CNT(head, tail, buffer->size) >= 1) {
    /* read index before reading contents at that index */
    smp_read_barrier_depends();
    /* extract one item from the buffer */
    struct item *item = buffer[tail];
    consume_item(item);
    smp_mb(); /* finish reading descriptor before incrementing tail */
    buffer->tail = (tail + 1) & (buffer->size - 1);
}
spin_unlock(&consumer_lock);
Questions specific to "consumer":
For the producer:
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 about ACCESS_ONCE on LWN that expands on this further)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 that buffer->tail is read before using it as an array index in buffer[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.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With