I am implementing single-producer,single-consumer ptr_ring buffers. Are there really data races within this linux driver code ?


I asked this because ThreadSanitizer gives me error and my system crashes after I started the ptr_ring code implementation.

Code:
inline int push_circ_queue(struct ptr_ring * buffer, unsigned int val1, unsigned int val2)
{ 
    int push_status;

    if (!ptr_ring_full_any(buffer)) // if (not full)
    {
        // assigns the two values in each item
        item_push[buffer->producer].val1 = val1;
        item_push[buffer->producer].val2 = val2;

        DEBUG_MSG(KERN_INFO "buffer->producer = %u , item_push[buffer->producer].val1 = %u , item_push[buffer->producer].val2 = %u\n", buffer->producer, item_push[buffer->producer].val1, item_push[buffer->producer].val2);

        /* insert one item into the buffer */
        push_status = ptr_ring_produce_any(buffer, &item_push[buffer->producer]);

        DEBUG_MSG(KERN_INFO "push_status = %u\n", push_status);

        return 0;
    }

    else return 1; // full, not enough buffer space
}

inline int pop_circ_queue(struct ptr_ring * buffer, unsigned int * val1, unsigned int * val2)
{
    unsigned int head;
    unsigned int tail;

    /* Read index before reading contents at that index. */
    head = buffer->consumer_head;
    tail = buffer->consumer_tail;

    if (!ptr_ring_empty_any(buffer)) // if (not empty)
    {
        DEBUG_MSG(KERN_INFO "Before pop, head = %u , tail = %u\n", head, tail);

        /* extract one item from the buffer */
        item_pop[tail] = *((struct item *)ptr_ring_consume_any(buffer));

        // reassigns the two values in each item
        *val1 = item_pop[tail].val1;
        *val2 = item_pop[tail].val2;

        DEBUG_MSG(KERN_INFO "val1 = %u , val2 = %u\n", *val1, *val2);       

        DEBUG_MSG(KERN_INFO "After pop, head = %u , tail = %u\n", buffer->consumer_head, buffer->consumer_tail);

        return 0;
    }

    else return 1; // empty, nothing to pop from the ring
}