ring: return free space when enqueuing
[dpdk.git] / lib / librte_ring / rte_ring.h
index 2777b41..439698b 100644 (file)
@@ -114,11 +114,6 @@ enum rte_ring_queue_behavior {
 #define RTE_RING_NAMESIZE (RTE_MEMZONE_NAMESIZE - \
                           sizeof(RTE_RING_MZ_PREFIX) + 1)
 
-#ifndef RTE_RING_PAUSE_REP_COUNT
-#define RTE_RING_PAUSE_REP_COUNT 0 /**< Yield after pause num of times, no yield
-                                    *   if RTE_RING_PAUSE_REP not defined. */
-#endif
-
 struct rte_memzone; /* forward declaration, so as not to require memzone.h */
 
 #if RTE_CACHE_LINE_SIZE < 128
@@ -158,7 +153,6 @@ struct rte_ring {
                        /**< Memzone, if any, containing the rte_ring */
        uint32_t size;           /**< Size of ring. */
        uint32_t mask;           /**< Mask (size-1) of ring. */
-       uint32_t watermark;      /**< Max items before EDQUOT in producer. */
 
        /** Ring producer status. */
        struct rte_ring_headtail prod __rte_aligned(PROD_ALIGN);
@@ -173,7 +167,6 @@ struct rte_ring {
 
 #define RING_F_SP_ENQ 0x0001 /**< The default enqueue is "single-producer". */
 #define RING_F_SC_DEQ 0x0002 /**< The default dequeue is "single-consumer". */
-#define RTE_RING_QUOT_EXCEED (1 << 31)  /**< Quota exceed for burst ops */
 #define RTE_RING_SZ_MASK  (unsigned)(0x0fffffff) /**< Ring size mask */
 
 /**
@@ -278,26 +271,6 @@ struct rte_ring *rte_ring_create(const char *name, unsigned count,
  */
 void rte_ring_free(struct rte_ring *r);
 
-/**
- * Change the high water mark.
- *
- * If *count* is 0, water marking is disabled. Otherwise, it is set to the
- * *count* value. The *count* value must be greater than 0 and less
- * than the ring size.
- *
- * This function can be called at any time (not necessarily at
- * initialization).
- *
- * @param r
- *   A pointer to the ring structure.
- * @param count
- *   The new water mark value.
- * @return
- *   - 0: Success; water mark changed.
- *   - -EINVAL: Invalid water mark value.
- */
-int rte_ring_set_water_mark(struct rte_ring *r, unsigned count);
-
 /**
  * Dump the status of the ring to a file.
  *
@@ -376,31 +349,20 @@ void rte_ring_dump(FILE *f, const struct rte_ring *r);
  *   RTE_RING_QUEUE_FIXED:    Enqueue a fixed number of items from a ring
  *   RTE_RING_QUEUE_VARIABLE: Enqueue as many items a possible from ring
  * @return
- *   Depend on the behavior value
- *   if behavior = RTE_RING_QUEUE_FIXED
- *   - 0: Success; objects enqueue.
- *   - -EDQUOT: Quota exceeded. The objects have been enqueued, but the
- *     high water mark is exceeded.
- *   - -ENOBUFS: Not enough room in the ring to enqueue, no object is enqueued.
- *   if behavior = RTE_RING_QUEUE_VARIABLE
- *   - n: Actual number of objects enqueued.
+ *   Actual number of objects enqueued.
+ *   If behavior == RTE_RING_QUEUE_FIXED, this will be 0 or n only.
  */
-static inline int __attribute__((always_inline))
+static inline unsigned int __attribute__((always_inline))
 __rte_ring_mp_do_enqueue(struct rte_ring *r, void * const *obj_table,
-                        unsigned n, enum rte_ring_queue_behavior behavior)
+                        unsigned int n, enum rte_ring_queue_behavior behavior,
+                        unsigned int *free_space)
 {
        uint32_t prod_head, prod_next;
        uint32_t cons_tail, free_entries;
-       const unsigned max = n;
+       const unsigned int max = n;
        int success;
-       unsigned i, rep = 0;
+       unsigned int i;
        uint32_t mask = r->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 {
@@ -416,16 +378,12 @@ __rte_ring_mp_do_enqueue(struct rte_ring *r, void * const *obj_table,
                free_entries = (mask + cons_tail - prod_head);
 
                /* check that we have enough room in ring */
-               if (unlikely(n > free_entries)) {
-                       if (behavior == RTE_RING_QUEUE_FIXED)
-                               return -ENOBUFS;
-                       else {
-                               /* No free entry available */
-                               if (unlikely(free_entries == 0))
-                                       return 0;
-                               n = free_entries;
-                       }
-               }
+               if (unlikely(n > free_entries))
+                       n = (behavior == RTE_RING_QUEUE_FIXED) ?
+                                       0 : free_entries;
+
+               if (n == 0)
+                       goto end;
 
                prod_next = prod_head + n;
                success = rte_atomic32_cmpset(&r->prod.head, prod_head,
@@ -436,31 +394,18 @@ __rte_ring_mp_do_enqueue(struct rte_ring *r, void * const *obj_table,
        ENQUEUE_PTRS();
        rte_smp_wmb();
 
-       /* if we exceed the watermark */
-       if (unlikely(((mask + 1) - free_entries + n) > r->watermark))
-               ret = (behavior == RTE_RING_QUEUE_FIXED) ? -EDQUOT :
-                               (int)(n | RTE_RING_QUOT_EXCEED);
-       else
-               ret = (behavior == RTE_RING_QUEUE_FIXED) ? 0 : n;
-
        /*
         * 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)) {
+       while (unlikely(r->prod.tail != prod_head))
                rte_pause();
 
-               /* Set RTE_RING_PAUSE_REP_COUNT to avoid spin too long waiting
-                * for other thread finish. It gives pre-empted thread a chance
-                * to proceed and finish with ring dequeue operation. */
-               if (RTE_RING_PAUSE_REP_COUNT &&
-                   ++rep == RTE_RING_PAUSE_REP_COUNT) {
-                       rep = 0;
-                       sched_yield();
-               }
-       }
        r->prod.tail = prod_next;
-       return ret;
+end:
+       if (free_space != NULL)
+               *free_space = free_entries - n;
+       return n;
 }
 
 /**
@@ -476,24 +421,18 @@ __rte_ring_mp_do_enqueue(struct rte_ring *r, void * const *obj_table,
  *   RTE_RING_QUEUE_FIXED:    Enqueue a fixed number of items from a ring
  *   RTE_RING_QUEUE_VARIABLE: Enqueue as many items a possible from ring
  * @return
- *   Depend on the behavior value
- *   if behavior = RTE_RING_QUEUE_FIXED
- *   - 0: Success; objects enqueue.
- *   - -EDQUOT: Quota exceeded. The objects have been enqueued, but the
- *     high water mark is exceeded.
- *   - -ENOBUFS: Not enough room in the ring to enqueue, no object is enqueued.
- *   if behavior = RTE_RING_QUEUE_VARIABLE
- *   - n: Actual number of objects enqueued.
+ *   Actual number of objects enqueued.
+ *   If behavior == RTE_RING_QUEUE_FIXED, this will be 0 or n only.
  */
-static inline int __attribute__((always_inline))
+static inline unsigned int __attribute__((always_inline))
 __rte_ring_sp_do_enqueue(struct rte_ring *r, void * const *obj_table,
-                        unsigned n, enum rte_ring_queue_behavior behavior)
+                        unsigned int n, enum rte_ring_queue_behavior behavior,
+                        unsigned int *free_space)
 {
        uint32_t prod_head, cons_tail;
        uint32_t prod_next, free_entries;
-       unsigned i;
+       unsigned int i;
        uint32_t mask = r->mask;
-       int ret;
 
        prod_head = r->prod.head;
        cons_tail = r->cons.tail;
@@ -504,16 +443,12 @@ __rte_ring_sp_do_enqueue(struct rte_ring *r, void * const *obj_table,
        free_entries = mask + cons_tail - prod_head;
 
        /* check that we have enough room in ring */
-       if (unlikely(n > free_entries)) {
-               if (behavior == RTE_RING_QUEUE_FIXED)
-                       return -ENOBUFS;
-               else {
-                       /* No free entry available */
-                       if (unlikely(free_entries == 0))
-                               return 0;
-                       n = free_entries;
-               }
-       }
+       if (unlikely(n > free_entries))
+               n = (behavior == RTE_RING_QUEUE_FIXED) ? 0 : free_entries;
+
+       if (n == 0)
+               goto end;
+
 
        prod_next = prod_head + n;
        r->prod.head = prod_next;
@@ -522,15 +457,11 @@ __rte_ring_sp_do_enqueue(struct rte_ring *r, void * const *obj_table,
        ENQUEUE_PTRS();
        rte_smp_wmb();
 
-       /* if we exceed the watermark */
-       if (unlikely(((mask + 1) - free_entries + n) > r->watermark))
-               ret = (behavior == RTE_RING_QUEUE_FIXED) ? -EDQUOT :
-                       (int)(n | RTE_RING_QUOT_EXCEED);
-       else
-               ret = (behavior == RTE_RING_QUEUE_FIXED) ? 0 : n;
-
        r->prod.tail = prod_next;
-       return ret;
+end:
+       if (free_space != NULL)
+               *free_space = free_entries - n;
+       return n;
 }
 
 /**
@@ -551,16 +482,11 @@ __rte_ring_sp_do_enqueue(struct rte_ring *r, void * const *obj_table,
  *   RTE_RING_QUEUE_FIXED:    Dequeue a fixed number of items from a ring
  *   RTE_RING_QUEUE_VARIABLE: Dequeue as many items a possible from ring
  * @return
- *   Depend on the behavior value
- *   if behavior = RTE_RING_QUEUE_FIXED
- *   - 0: Success; objects dequeued.
- *   - -ENOENT: Not enough entries in the ring to dequeue; no object is
- *     dequeued.
- *   if behavior = RTE_RING_QUEUE_VARIABLE
- *   - n: Actual number of objects dequeued.
+ *   - Actual number of objects dequeued.
+ *     If behavior == RTE_RING_QUEUE_FIXED, this will be 0 or n only.
  */
 
-static inline int __attribute__((always_inline))
+static inline unsigned int __attribute__((always_inline))
 __rte_ring_mc_do_dequeue(struct rte_ring *r, void **obj_table,
                 unsigned n, enum rte_ring_queue_behavior behavior)
 {
@@ -568,7 +494,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, rep = 0;
+       unsigned int i;
        uint32_t mask = r->mask;
 
        /* Avoid the unnecessary cmpset operation below, which is also
@@ -592,7 +518,7 @@ __rte_ring_mc_do_dequeue(struct rte_ring *r, void **obj_table,
                /* Set the actual entries for dequeue */
                if (n > entries) {
                        if (behavior == RTE_RING_QUEUE_FIXED)
-                               return -ENOENT;
+                               return 0;
                        else {
                                if (unlikely(entries == 0))
                                        return 0;
@@ -613,21 +539,12 @@ __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)) {
+       while (unlikely(r->cons.tail != cons_head))
                rte_pause();
 
-               /* Set RTE_RING_PAUSE_REP_COUNT to avoid spin too long waiting
-                * for other thread finish. It gives pre-empted thread a chance
-                * to proceed and finish with ring dequeue operation. */
-               if (RTE_RING_PAUSE_REP_COUNT &&
-                   ++rep == RTE_RING_PAUSE_REP_COUNT) {
-                       rep = 0;
-                       sched_yield();
-               }
-       }
        r->cons.tail = cons_next;
 
-       return behavior == RTE_RING_QUEUE_FIXED ? 0 : n;
+       return n;
 }
 
 /**
@@ -645,21 +562,16 @@ __rte_ring_mc_do_dequeue(struct rte_ring *r, void **obj_table,
  *   RTE_RING_QUEUE_FIXED:    Dequeue a fixed number of items from a ring
  *   RTE_RING_QUEUE_VARIABLE: Dequeue as many items a possible from ring
  * @return
- *   Depend on the behavior value
- *   if behavior = RTE_RING_QUEUE_FIXED
- *   - 0: Success; objects dequeued.
- *   - -ENOENT: Not enough entries in the ring to dequeue; no object is
- *     dequeued.
- *   if behavior = RTE_RING_QUEUE_VARIABLE
- *   - n: Actual number of objects dequeued.
+ *   - Actual number of objects dequeued.
+ *     If behavior == RTE_RING_QUEUE_FIXED, this will be 0 or n only.
  */
-static inline int __attribute__((always_inline))
+static inline unsigned int __attribute__((always_inline))
 __rte_ring_sc_do_dequeue(struct rte_ring *r, void **obj_table,
                 unsigned n, enum rte_ring_queue_behavior behavior)
 {
        uint32_t cons_head, prod_tail;
        uint32_t cons_next, entries;
-       unsigned i;
+       unsigned int i;
        uint32_t mask = r->mask;
 
        cons_head = r->cons.head;
@@ -672,7 +584,7 @@ __rte_ring_sc_do_dequeue(struct rte_ring *r, void **obj_table,
 
        if (n > entries) {
                if (behavior == RTE_RING_QUEUE_FIXED)
-                       return -ENOENT;
+                       return 0;
                else {
                        if (unlikely(entries == 0))
                                return 0;
@@ -688,7 +600,7 @@ __rte_ring_sc_do_dequeue(struct rte_ring *r, void **obj_table,
        rte_smp_rmb();
 
        r->cons.tail = cons_next;
-       return behavior == RTE_RING_QUEUE_FIXED ? 0 : n;
+       return n;
 }
 
 /**
@@ -703,17 +615,18 @@ __rte_ring_sc_do_dequeue(struct rte_ring *r, void **obj_table,
  *   A pointer to a table of void * pointers (objects).
  * @param n
  *   The number of objects to add in the ring from the obj_table.
+ * @param free_space
+ *   if non-NULL, returns the amount of space in the ring after the
+ *   enqueue operation has finished.
  * @return
- *   - 0: Success; objects enqueue.
- *   - -EDQUOT: Quota exceeded. The objects have been enqueued, but the
- *     high water mark is exceeded.
- *   - -ENOBUFS: Not enough room in the ring to enqueue, no object is enqueued.
+ *   The number of objects enqueued, either 0 or n
  */
-static inline int __attribute__((always_inline))
+static inline unsigned int __attribute__((always_inline))
 rte_ring_mp_enqueue_bulk(struct rte_ring *r, void * const *obj_table,
-                        unsigned n)
+                        unsigned int n, unsigned int *free_space)
 {
-       return __rte_ring_mp_do_enqueue(r, obj_table, n, RTE_RING_QUEUE_FIXED);
+       return __rte_ring_mp_do_enqueue(r, obj_table, n, RTE_RING_QUEUE_FIXED,
+                       free_space);
 }
 
 /**
@@ -725,17 +638,18 @@ rte_ring_mp_enqueue_bulk(struct rte_ring *r, void * const *obj_table,
  *   A pointer to a table of void * pointers (objects).
  * @param n
  *   The number of objects to add in the ring from the obj_table.
+ * @param free_space
+ *   if non-NULL, returns the amount of space in the ring after the
+ *   enqueue operation has finished.
  * @return
- *   - 0: Success; objects enqueued.
- *   - -EDQUOT: Quota exceeded. The objects have been enqueued, but the
- *     high water mark is exceeded.
- *   - -ENOBUFS: Not enough room in the ring to enqueue; no object is enqueued.
+ *   The number of objects enqueued, either 0 or n
  */
-static inline int __attribute__((always_inline))
+static inline unsigned int __attribute__((always_inline))
 rte_ring_sp_enqueue_bulk(struct rte_ring *r, void * const *obj_table,
-                        unsigned n)
+                        unsigned int n, unsigned int *free_space)
 {
-       return __rte_ring_sp_do_enqueue(r, obj_table, n, RTE_RING_QUEUE_FIXED);
+       return __rte_ring_sp_do_enqueue(r, obj_table, n, RTE_RING_QUEUE_FIXED,
+                       free_space);
 }
 
 /**
@@ -751,20 +665,20 @@ rte_ring_sp_enqueue_bulk(struct rte_ring *r, void * const *obj_table,
  *   A pointer to a table of void * pointers (objects).
  * @param n
  *   The number of objects to add in the ring from the obj_table.
+ * @param free_space
+ *   if non-NULL, returns the amount of space in the ring after the
+ *   enqueue operation has finished.
  * @return
- *   - 0: Success; objects enqueued.
- *   - -EDQUOT: Quota exceeded. The objects have been enqueued, but the
- *     high water mark is exceeded.
- *   - -ENOBUFS: Not enough room in the ring to enqueue; no object is enqueued.
+ *   The number of objects enqueued, either 0 or n
  */
-static inline int __attribute__((always_inline))
+static inline unsigned int __attribute__((always_inline))
 rte_ring_enqueue_bulk(struct rte_ring *r, void * const *obj_table,
-                     unsigned n)
+                     unsigned int n, unsigned int *free_space)
 {
        if (r->prod.single)
-               return rte_ring_sp_enqueue_bulk(r, obj_table, n);
+               return rte_ring_sp_enqueue_bulk(r, obj_table, n, free_space);
        else
-               return rte_ring_mp_enqueue_bulk(r, obj_table, n);
+               return rte_ring_mp_enqueue_bulk(r, obj_table, n, free_space);
 }
 
 /**
@@ -779,14 +693,12 @@ rte_ring_enqueue_bulk(struct rte_ring *r, void * const *obj_table,
  *   A pointer to the object to be added.
  * @return
  *   - 0: Success; objects enqueued.
- *   - -EDQUOT: Quota exceeded. The objects have been enqueued, but the
- *     high water mark is exceeded.
  *   - -ENOBUFS: Not enough room in the ring to enqueue; no object is enqueued.
  */
 static inline int __attribute__((always_inline))
 rte_ring_mp_enqueue(struct rte_ring *r, void *obj)
 {
-       return rte_ring_mp_enqueue_bulk(r, &obj, 1);
+       return rte_ring_mp_enqueue_bulk(r, &obj, 1, NULL) ? 0 : -ENOBUFS;
 }
 
 /**
@@ -798,14 +710,12 @@ rte_ring_mp_enqueue(struct rte_ring *r, void *obj)
  *   A pointer to the object to be added.
  * @return
  *   - 0: Success; objects enqueued.
- *   - -EDQUOT: Quota exceeded. The objects have been enqueued, but the
- *     high water mark is exceeded.
  *   - -ENOBUFS: Not enough room in the ring to enqueue; no object is enqueued.
  */
 static inline int __attribute__((always_inline))
 rte_ring_sp_enqueue(struct rte_ring *r, void *obj)
 {
-       return rte_ring_sp_enqueue_bulk(r, &obj, 1);
+       return rte_ring_sp_enqueue_bulk(r, &obj, 1, NULL) ? 0 : -ENOBUFS;
 }
 
 /**
@@ -821,17 +731,12 @@ rte_ring_sp_enqueue(struct rte_ring *r, void *obj)
  *   A pointer to the object to be added.
  * @return
  *   - 0: Success; objects enqueued.
- *   - -EDQUOT: Quota exceeded. The objects have been enqueued, but the
- *     high water mark is exceeded.
  *   - -ENOBUFS: Not enough room in the ring to enqueue; no object is enqueued.
  */
 static inline int __attribute__((always_inline))
 rte_ring_enqueue(struct rte_ring *r, void *obj)
 {
-       if (r->prod.single)
-               return rte_ring_sp_enqueue(r, obj);
-       else
-               return rte_ring_mp_enqueue(r, obj);
+       return rte_ring_enqueue_bulk(r, &obj, 1, NULL) ? 0 : -ENOBUFS;
 }
 
 /**
@@ -847,11 +752,9 @@ rte_ring_enqueue(struct rte_ring *r, void *obj)
  * @param n
  *   The number of objects to dequeue from the ring to the obj_table.
  * @return
- *   - 0: Success; objects dequeued.
- *   - -ENOENT: Not enough entries in the ring to dequeue; no object is
- *     dequeued.
+ *   The number of objects dequeued, either 0 or n
  */
-static inline int __attribute__((always_inline))
+static inline unsigned int __attribute__((always_inline))
 rte_ring_mc_dequeue_bulk(struct rte_ring *r, void **obj_table, unsigned n)
 {
        return __rte_ring_mc_do_dequeue(r, obj_table, n, RTE_RING_QUEUE_FIXED);
@@ -868,11 +771,9 @@ rte_ring_mc_dequeue_bulk(struct rte_ring *r, void **obj_table, unsigned n)
  *   The number of objects to dequeue from the ring to the obj_table,
  *   must be strictly positive.
  * @return
- *   - 0: Success; objects dequeued.
- *   - -ENOENT: Not enough entries in the ring to dequeue; no object is
- *     dequeued.
+ *   The number of objects dequeued, either 0 or n
  */
-static inline int __attribute__((always_inline))
+static inline unsigned int __attribute__((always_inline))
 rte_ring_sc_dequeue_bulk(struct rte_ring *r, void **obj_table, unsigned n)
 {
        return __rte_ring_sc_do_dequeue(r, obj_table, n, RTE_RING_QUEUE_FIXED);
@@ -892,11 +793,9 @@ rte_ring_sc_dequeue_bulk(struct rte_ring *r, void **obj_table, unsigned n)
  * @param n
  *   The number of objects to dequeue from the ring to the obj_table.
  * @return
- *   - 0: Success; objects dequeued.
- *   - -ENOENT: Not enough entries in the ring to dequeue, no object is
- *     dequeued.
+ *   The number of objects dequeued, either 0 or n
  */
-static inline int __attribute__((always_inline))
+static inline unsigned int __attribute__((always_inline))
 rte_ring_dequeue_bulk(struct rte_ring *r, void **obj_table, unsigned n)
 {
        if (r->cons.single)
@@ -923,7 +822,7 @@ rte_ring_dequeue_bulk(struct rte_ring *r, void **obj_table, unsigned n)
 static inline int __attribute__((always_inline))
 rte_ring_mc_dequeue(struct rte_ring *r, void **obj_p)
 {
-       return rte_ring_mc_dequeue_bulk(r, obj_p, 1);
+       return rte_ring_mc_dequeue_bulk(r, obj_p, 1)  ? 0 : -ENOBUFS;
 }
 
 /**
@@ -941,7 +840,7 @@ rte_ring_mc_dequeue(struct rte_ring *r, void **obj_p)
 static inline int __attribute__((always_inline))
 rte_ring_sc_dequeue(struct rte_ring *r, void **obj_p)
 {
-       return rte_ring_sc_dequeue_bulk(r, obj_p, 1);
+       return rte_ring_sc_dequeue_bulk(r, obj_p, 1) ? 0 : -ENOBUFS;
 }
 
 /**
@@ -963,10 +862,7 @@ rte_ring_sc_dequeue(struct rte_ring *r, void **obj_p)
 static inline int __attribute__((always_inline))
 rte_ring_dequeue(struct rte_ring *r, void **obj_p)
 {
-       if (r->cons.single)
-               return rte_ring_sc_dequeue(r, obj_p);
-       else
-               return rte_ring_mc_dequeue(r, obj_p);
+       return rte_ring_dequeue_bulk(r, obj_p, 1) ? 0 : -ENOBUFS;
 }
 
 /**
@@ -1081,14 +977,18 @@ struct rte_ring *rte_ring_lookup(const char *name);
  *   A pointer to a table of void * pointers (objects).
  * @param n
  *   The number of objects to add in the ring from the obj_table.
+ * @param free_space
+ *   if non-NULL, returns the amount of space in the ring after the
+ *   enqueue operation has finished.
  * @return
  *   - n: Actual number of objects enqueued.
  */
 static inline unsigned __attribute__((always_inline))
 rte_ring_mp_enqueue_burst(struct rte_ring *r, void * const *obj_table,
-                        unsigned n)
+                        unsigned int n, unsigned int *free_space)
 {
-       return __rte_ring_mp_do_enqueue(r, obj_table, n, RTE_RING_QUEUE_VARIABLE);
+       return __rte_ring_mp_do_enqueue(r, obj_table, n,
+                       RTE_RING_QUEUE_VARIABLE, free_space);
 }
 
 /**
@@ -1100,14 +1000,18 @@ rte_ring_mp_enqueue_burst(struct rte_ring *r, void * const *obj_table,
  *   A pointer to a table of void * pointers (objects).
  * @param n
  *   The number of objects to add in the ring from the obj_table.
+ * @param free_space
+ *   if non-NULL, returns the amount of space in the ring after the
+ *   enqueue operation has finished.
  * @return
  *   - n: Actual number of objects enqueued.
  */
 static inline unsigned __attribute__((always_inline))
 rte_ring_sp_enqueue_burst(struct rte_ring *r, void * const *obj_table,
-                        unsigned n)
+                        unsigned int n, unsigned int *free_space)
 {
-       return __rte_ring_sp_do_enqueue(r, obj_table, n, RTE_RING_QUEUE_VARIABLE);
+       return __rte_ring_sp_do_enqueue(r, obj_table, n,
+                       RTE_RING_QUEUE_VARIABLE, free_space);
 }
 
 /**
@@ -1123,17 +1027,20 @@ rte_ring_sp_enqueue_burst(struct rte_ring *r, void * const *obj_table,
  *   A pointer to a table of void * pointers (objects).
  * @param n
  *   The number of objects to add in the ring from the obj_table.
+ * @param free_space
+ *   if non-NULL, returns the amount of space in the ring after the
+ *   enqueue operation has finished.
  * @return
  *   - n: Actual number of objects enqueued.
  */
 static inline unsigned __attribute__((always_inline))
 rte_ring_enqueue_burst(struct rte_ring *r, void * const *obj_table,
-                     unsigned n)
+                     unsigned int n, unsigned int *free_space)
 {
        if (r->prod.single)
-               return rte_ring_sp_enqueue_burst(r, obj_table, n);
+               return rte_ring_sp_enqueue_burst(r, obj_table, n, free_space);
        else
-               return rte_ring_mp_enqueue_burst(r, obj_table, n);
+               return rte_ring_mp_enqueue_burst(r, obj_table, n, free_space);
 }
 
 /**