Both __store_ring() and __load_ring() have a same bug.
function __store_ring:
|
__store_ring(struct rte_ring *r, uint_fast32_t head, void * const* obj, unsigned n) |
|
{ |
|
unsigned i; |
|
unsigned loops = n & 0x3; |
|
unsigned idx = head & r->mask; |
|
|
|
|
|
// If we know we won't wrap around, we unroll 4 times |
|
if (likely((idx + n) <= r->mask)) { |
|
for (i = 0; i < loops; i += 4, idx += 4) { |
|
r->ring[idx+0] = obj[i+0]; |
|
r->ring[idx+1] = obj[i+1]; |
|
r->ring[idx+2] = obj[i+2]; |
|
r->ring[idx+3] = obj[i+3]; |
|
} |
|
|
|
// mop up remainder |
|
switch (n & 0x3) { |
|
case 3: |
|
r->ring[idx+0] = obj[i+0]; |
|
r->ring[idx+1] = obj[i+1]; |
|
r->ring[idx+2] = obj[i+2]; |
|
break; |
|
|
|
case 2: |
|
r->ring[idx+0] = obj[i+0]; |
|
r->ring[idx+1] = obj[i+1]; |
|
break; |
|
|
|
case 1: |
|
r->ring[idx+0] = obj[i+0]; |
|
break; |
|
} |
|
} else { |
|
const uint32_t mask = r->mask; |
|
|
|
for (i = 0; i < n; i++, idx++) { |
|
r->ring[idx & mask] = obj[i]; |
|
} |
|
} |
|
} |
-
Bug: When n=1, function __store_ring(ring, head, elements, n) actually writes 4 elements into the ring.
-
Reason: loop should = n>>2 not n&0x03
Buggy code is at line 240:
|
unsigned loops = n & 0x3; |
-
Solution:
The correct logic should be:
unsigned loop = n & ((unsigned) ~0x3U);
see also https://github.com/DPDK/dpdk/blob/07f08a96f5255a0375dce2683db4fb489bbaa8a0/lib/librte_ring/rte_ring.h#L240-L250
Both
__store_ring()and__load_ring()have a same bug.function
__store_ring:portable-lib/inc/fast/ringbuf.h
Lines 237 to 277 in 10c3286
Bug: When
n=1, function__store_ring(ring, head, elements, n)actually writes 4 elements into the ring.Reason:
loopshould =n>>2notn&0x03Buggy code is at line 240:
portable-lib/inc/fast/ringbuf.h
Line 240 in 10c3286
Solution:
The correct logic should be:
see also https://github.com/DPDK/dpdk/blob/07f08a96f5255a0375dce2683db4fb489bbaa8a0/lib/librte_ring/rte_ring.h#L240-L250