ring: fix deadlock in zero object multi enqueue or dequeue
Issuing a zero objects dequeue with a single consumer has no effect.
Doing so with multiple consumers, can get more than one thread to succeed
the compare-and-set operation and observe starvation or even deadlock in
the while loop that checks for preceding dequeues. The problematic piece
of code when n = 0:
cons_next = cons_head + n;
success = rte_atomic32_cmpset(&r->cons.head, cons_head, cons_next);
The same is possible on the enqueue path.
Fixes: af75078fec
("first public release")
Signed-off-by: Lazaros Koromilas <l@nofutznetworks.com>
Acked-by: Olivier Matz <olivier.matz@6wind.com>
This commit is contained in:
parent
768f0e4587
commit
d097964616
@ -431,6 +431,11 @@ __rte_ring_mp_do_enqueue(struct rte_ring *r, void * const *obj_table,
|
||||
uint32_t mask = r->prod.mask;
|
||||
int ret;
|
||||
|
||||
/* Avoid the unnecessary cmpset operation below, which is also
|
||||
* potentially harmful when n equals 0. */
|
||||
if (n == 0)
|
||||
return 0;
|
||||
|
||||
/* move prod.head atomically */
|
||||
do {
|
||||
/* Reset n to the initial burst count */
|
||||
@ -618,6 +623,11 @@ __rte_ring_mc_do_dequeue(struct rte_ring *r, void **obj_table,
|
||||
unsigned i, rep = 0;
|
||||
uint32_t mask = r->prod.mask;
|
||||
|
||||
/* Avoid the unnecessary cmpset operation below, which is also
|
||||
* potentially harmful when n equals 0. */
|
||||
if (n == 0)
|
||||
return 0;
|
||||
|
||||
/* move cons.head atomically */
|
||||
do {
|
||||
/* Restore n as it may change every loop */
|
||||
|
Loading…
Reference in New Issue
Block a user