cpointer-arithmetic

Can someone explain to me this piece of code? (pointer arithmetics with masks)


I'm trying to understand the inner working for the linux kernel io_uring interface, and I found some code I have problem understanding:

/*
 * Assign 'buf' with the addr/len/buffer ID supplied
 */
IOURINGINLINE void io_uring_buf_ring_add(struct io_uring_buf_ring *br,
                     void *addr, unsigned int len,
                     unsigned short bid, int mask,
                     int buf_offset)
    LIBURING_NOEXCEPT
{
    struct io_uring_buf *buf = &br->bufs[(br->tail + buf_offset) & mask];

    buf->addr = (unsigned long) (uintptr_t) addr;
    buf->len = len;
    buf->bid = bid;
}

I invite to read the rest of the code or the manual for better understanding the context, but to sum what's happening:

What I really can't understand is:

struct io_uring_buf *buf = &br->bufs[(br->tail + buf_offset) & mask];

Note:

Here's the code of io_uring_buf_ring_mask, still I can't understand its meaning. Might be worth mentioning that from what I understood ring_entries is not the current number of buffers in the buffer group, but the maximum number of buffers I picked when calling io_uring_setup_buf_ring, code here. Btw in the manual io_uring_setup_buf_ring is a function, but in the code I can't see the function body, what am I misunderstanding?


Solution

  • Why are why using the & operator to pick a slot in the buffer pointers array?

    It is the modulo division operator, gives you remainder from division. For example say we have ring buffer with maximum size of 16 elements and current tail points to the 10th element index and we want to add an element at the 8th element offset from the current tail. That will be 2nd element in the buffer. tail + offset = 10 + 8 = 18 is out of range, so we need to 18 % 16 = 2.

    Using mask is just an optimized version of modulo operator. It implies a constraint that size of ring buffer is a power of 2. % 16 is the same as & 0b1111 or similar. See https://en.wikipedia.org/wiki/Modulo#Performance_issues .

    What is the meaning of the mask variable?

    Mask variable represents all bits that can be set in a variable that represents any possible position index in the ring buffer. Or it is equal to the last ring buffer index. Or it is the maximum size of the ring buffer minus one, which is what io_uring_buf_ring_mask function returns.

    io_uring_setup_buf_ring is a function, but in the code I can't see the function body, what am I misunderstanding?

    The function source code is in setup.c https://github.com/axboe/liburing/blob/669a89b880d08913652ec86239be02c026a20083/src/setup.c#L676 .