From d0979646166e740917baaabc4b78ded3482226b7 Mon Sep 17 00:00:00 2001 From: Lazaros Koromilas Date: Thu, 17 Mar 2016 17:49:43 +0200 Subject: [PATCH] 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: af75078fece3 ("first public release") Signed-off-by: Lazaros Koromilas Acked-by: Olivier Matz --- lib/librte_ring/rte_ring.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/librte_ring/rte_ring.h b/lib/librte_ring/rte_ring.h index 943c97cf4a..eb45e41449 100644 --- a/lib/librte_ring/rte_ring.h +++ b/lib/librte_ring/rte_ring.h @@ -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 */ -- 2.20.1