[dpdk-dev,v3,15/16] ring: add sched_yield to avoid spin forever

Message ID 1422491072-5114-16-git-send-email-cunming.liang@intel.com (mailing list archive)
State Superseded, archived
Headers

Commit Message

Cunming Liang Jan. 29, 2015, 12:24 a.m. UTC
It does a gentle yield after spin for a while.
It reduces the wasting by spin when the preemption happens.

Signed-off-by: Cunming Liang <cunming.liang@intel.com>
---
 lib/librte_ring/rte_ring.h | 25 +++++++++++++++++++------
 1 file changed, 19 insertions(+), 6 deletions(-)
  

Patch

diff --git a/lib/librte_ring/rte_ring.h b/lib/librte_ring/rte_ring.h
index 39bacdd..c16da6e 100644
--- a/lib/librte_ring/rte_ring.h
+++ b/lib/librte_ring/rte_ring.h
@@ -126,6 +126,7 @@  struct rte_ring_debug_stats {
 
 #define RTE_RING_NAMESIZE 32 /**< The maximum length of a ring name. */
 #define RTE_RING_MZ_PREFIX "RG_"
+#define RTE_RING_PAUSE_REP 0x100  /**< yield after num of times pause. */
 
 /**
  * An RTE ring structure.
@@ -410,7 +411,7 @@  __rte_ring_mp_do_enqueue(struct rte_ring *r, void * const *obj_table,
 	uint32_t cons_tail, free_entries;
 	const unsigned max = n;
 	int success;
-	unsigned i;
+	unsigned i, rep;
 	uint32_t mask = r->prod.mask;
 	int ret;
 
@@ -468,8 +469,14 @@  __rte_ring_mp_do_enqueue(struct rte_ring *r, void * const *obj_table,
 	 * If there are other enqueues in progress that preceded us,
 	 * we need to wait for them to complete
 	 */
-	while (unlikely(r->prod.tail != prod_head))
-		rte_pause();
+	do {
+		for (rep = RTE_RING_PAUSE_REP;
+		     rep != 0 && r->prod.tail != prod_head; rep--)
+			rte_pause();
+
+		if (rep == 0)
+			sched_yield();
+	}while(rep == 0);
 
 	r->prod.tail = prod_next;
 	return ret;
@@ -589,7 +596,7 @@  __rte_ring_mc_do_dequeue(struct rte_ring *r, void **obj_table,
 	uint32_t cons_next, entries;
 	const unsigned max = n;
 	int success;
-	unsigned i;
+	unsigned i, rep;
 	uint32_t mask = r->prod.mask;
 
 	/* move cons.head atomically */
@@ -634,8 +641,14 @@  __rte_ring_mc_do_dequeue(struct rte_ring *r, void **obj_table,
 	 * If there are other dequeues in progress that preceded us,
 	 * we need to wait for them to complete
 	 */
-	while (unlikely(r->cons.tail != cons_head))
-		rte_pause();
+	do {
+		for (rep = RTE_RING_PAUSE_REP;
+		     rep != 0 && r->cons.tail != cons_head; rep--)
+			rte_pause();
+
+		if (rep == 0)
+			sched_yield();
+	}while(rep == 0);
 
 	__RING_STAT_ADD(r, deq_success, n);
 	r->cons.tail = cons_next;