xref: /dpdk/lib/ring/rte_ring_elem.h (revision 719834a6849e1daf4a70ff7742bbcc3ae7e25607)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright (c) 2019 Arm Limited
4  * Copyright (c) 2010-2017 Intel Corporation
5  * Copyright (c) 2007-2009 Kip Macy kmacy@freebsd.org
6  * All rights reserved.
7  * Derived from FreeBSD's bufring.h
8  * Used as BSD-3 Licensed with permission from Kip Macy.
9  */
10 
11 #ifndef _RTE_RING_ELEM_H_
12 #define _RTE_RING_ELEM_H_
13 
14 /**
15  * @file
16  * RTE Ring with user defined element size
17  */
18 
19 #include <rte_ring_core.h>
20 #include <rte_ring_elem_pvt.h>
21 
22 /**
23  * Calculate the memory size needed for a ring with given element size
24  *
25  * This function returns the number of bytes needed for a ring, given
26  * the number of elements in it and the size of the element. This value
27  * is the sum of the size of the structure rte_ring and the size of the
28  * memory needed for storing the elements. The value is aligned to a cache
29  * line size.
30  *
31  * @param esize
32  *   The size of ring element, in bytes. It must be a multiple of 4.
33  * @param count
34  *   The number of elements in the ring (must be a power of 2).
35  * @return
36  *   - The memory size needed for the ring on success.
37  *   - -EINVAL - esize is not a multiple of 4 or count provided is not a
38  *		 power of 2.
39  */
40 ssize_t rte_ring_get_memsize_elem(unsigned int esize, unsigned int count);
41 
42 /**
43  * Create a new ring named *name* that stores elements with given size.
44  *
45  * This function uses ``memzone_reserve()`` to allocate memory. Then it
46  * calls rte_ring_init() to initialize an empty ring.
47  *
48  * The new ring size is set to *count*, which must be a power of
49  * two. Water marking is disabled by default. The real usable ring size
50  * is *count-1* instead of *count* to differentiate a full ring from an
51  * empty ring.
52  *
53  * The ring is added in RTE_TAILQ_RING list.
54  *
55  * @param name
56  *   The name of the ring.
57  * @param esize
58  *   The size of ring element, in bytes. It must be a multiple of 4.
59  * @param count
60  *   The number of elements in the ring (must be a power of 2).
61  * @param socket_id
62  *   The *socket_id* argument is the socket identifier in case of
63  *   NUMA. The value can be *SOCKET_ID_ANY* if there is no NUMA
64  *   constraint for the reserved zone.
65  * @param flags
66  *   An OR of the following:
67  *   - One of mutually exclusive flags that define producer behavior:
68  *      - RING_F_SP_ENQ: If this flag is set, the default behavior when
69  *        using ``rte_ring_enqueue()`` or ``rte_ring_enqueue_bulk()``
70  *        is "single-producer".
71  *      - RING_F_MP_RTS_ENQ: If this flag is set, the default behavior when
72  *        using ``rte_ring_enqueue()`` or ``rte_ring_enqueue_bulk()``
73  *        is "multi-producer RTS mode".
74  *      - RING_F_MP_HTS_ENQ: If this flag is set, the default behavior when
75  *        using ``rte_ring_enqueue()`` or ``rte_ring_enqueue_bulk()``
76  *        is "multi-producer HTS mode".
77  *     If none of these flags is set, then default "multi-producer"
78  *     behavior is selected.
79  *   - One of mutually exclusive flags that define consumer behavior:
80  *      - RING_F_SC_DEQ: If this flag is set, the default behavior when
81  *        using ``rte_ring_dequeue()`` or ``rte_ring_dequeue_bulk()``
82  *        is "single-consumer". Otherwise, it is "multi-consumers".
83  *      - RING_F_MC_RTS_DEQ: If this flag is set, the default behavior when
84  *        using ``rte_ring_dequeue()`` or ``rte_ring_dequeue_bulk()``
85  *        is "multi-consumer RTS mode".
86  *      - RING_F_MC_HTS_DEQ: If this flag is set, the default behavior when
87  *        using ``rte_ring_dequeue()`` or ``rte_ring_dequeue_bulk()``
88  *        is "multi-consumer HTS mode".
89  *     If none of these flags is set, then default "multi-consumer"
90  *     behavior is selected.
91  * @return
92  *   On success, the pointer to the new allocated ring. NULL on error with
93  *    rte_errno set appropriately. Possible errno values include:
94  *    - E_RTE_NO_CONFIG - function could not get pointer to rte_config structure
95  *    - EINVAL - esize is not a multiple of 4 or count provided is not a
96  *		 power of 2.
97  *    - ENOSPC - the maximum number of memzones has already been allocated
98  *    - EEXIST - a memzone with the same name already exists
99  *    - ENOMEM - no appropriate memory area found in which to create memzone
100  */
101 struct rte_ring *rte_ring_create_elem(const char *name, unsigned int esize,
102 			unsigned int count, int socket_id, unsigned int flags);
103 
104 /**
105  * Enqueue several objects on the ring (multi-producers safe).
106  *
107  * This function uses a "compare and set" instruction to move the
108  * producer index atomically.
109  *
110  * @param r
111  *   A pointer to the ring structure.
112  * @param obj_table
113  *   A pointer to a table of objects.
114  * @param esize
115  *   The size of ring element, in bytes. It must be a multiple of 4.
116  *   This must be the same value used while creating the ring. Otherwise
117  *   the results are undefined.
118  * @param n
119  *   The number of objects to add in the ring from the obj_table.
120  * @param free_space
121  *   if non-NULL, returns the amount of space in the ring after the
122  *   enqueue operation has finished.
123  * @return
124  *   The number of objects enqueued, either 0 or n
125  */
126 static __rte_always_inline unsigned int
127 rte_ring_mp_enqueue_bulk_elem(struct rte_ring *r, const void *obj_table,
128 		unsigned int esize, unsigned int n, unsigned int *free_space)
129 {
130 	return __rte_ring_do_enqueue_elem(r, obj_table, esize, n,
131 			RTE_RING_QUEUE_FIXED, RTE_RING_SYNC_MT, free_space);
132 }
133 
134 /**
135  * Enqueue several objects on a ring
136  *
137  * @warning This API is NOT multi-producers safe
138  *
139  * @param r
140  *   A pointer to the ring structure.
141  * @param obj_table
142  *   A pointer to a table of objects.
143  * @param esize
144  *   The size of ring element, in bytes. It must be a multiple of 4.
145  *   This must be the same value used while creating the ring. Otherwise
146  *   the results are undefined.
147  * @param n
148  *   The number of objects to add in the ring from the obj_table.
149  * @param free_space
150  *   if non-NULL, returns the amount of space in the ring after the
151  *   enqueue operation has finished.
152  * @return
153  *   The number of objects enqueued, either 0 or n
154  */
155 static __rte_always_inline unsigned int
156 rte_ring_sp_enqueue_bulk_elem(struct rte_ring *r, const void *obj_table,
157 		unsigned int esize, unsigned int n, unsigned int *free_space)
158 {
159 	return __rte_ring_do_enqueue_elem(r, obj_table, esize, n,
160 			RTE_RING_QUEUE_FIXED, RTE_RING_SYNC_ST, free_space);
161 }
162 
163 #include <rte_ring_hts.h>
164 #include <rte_ring_rts.h>
165 
166 /**
167  * Enqueue several objects on a ring.
168  *
169  * This function calls the multi-producer or the single-producer
170  * version depending on the default behavior that was specified at
171  * ring creation time (see flags).
172  *
173  * @param r
174  *   A pointer to the ring structure.
175  * @param obj_table
176  *   A pointer to a table of objects.
177  * @param esize
178  *   The size of ring element, in bytes. It must be a multiple of 4.
179  *   This must be the same value used while creating the ring. Otherwise
180  *   the results are undefined.
181  * @param n
182  *   The number of objects to add in the ring from the obj_table.
183  * @param free_space
184  *   if non-NULL, returns the amount of space in the ring after the
185  *   enqueue operation has finished.
186  * @return
187  *   The number of objects enqueued, either 0 or n
188  */
189 static __rte_always_inline unsigned int
190 rte_ring_enqueue_bulk_elem(struct rte_ring *r, const void *obj_table,
191 		unsigned int esize, unsigned int n, unsigned int *free_space)
192 {
193 	switch (r->prod.sync_type) {
194 	case RTE_RING_SYNC_MT:
195 		return rte_ring_mp_enqueue_bulk_elem(r, obj_table, esize, n,
196 			free_space);
197 	case RTE_RING_SYNC_ST:
198 		return rte_ring_sp_enqueue_bulk_elem(r, obj_table, esize, n,
199 			free_space);
200 	case RTE_RING_SYNC_MT_RTS:
201 		return rte_ring_mp_rts_enqueue_bulk_elem(r, obj_table, esize, n,
202 			free_space);
203 	case RTE_RING_SYNC_MT_HTS:
204 		return rte_ring_mp_hts_enqueue_bulk_elem(r, obj_table, esize, n,
205 			free_space);
206 	}
207 
208 	/* valid ring should never reach this point */
209 	RTE_ASSERT(0);
210 	if (free_space != NULL)
211 		*free_space = 0;
212 	return 0;
213 }
214 
215 /**
216  * Enqueue one object on a ring (multi-producers safe).
217  *
218  * This function uses a "compare and set" instruction to move the
219  * producer index atomically.
220  *
221  * @param r
222  *   A pointer to the ring structure.
223  * @param obj
224  *   A pointer to the object to be added.
225  * @param esize
226  *   The size of ring element, in bytes. It must be a multiple of 4.
227  *   This must be the same value used while creating the ring. Otherwise
228  *   the results are undefined.
229  * @return
230  *   - 0: Success; objects enqueued.
231  *   - -ENOBUFS: Not enough room in the ring to enqueue; no object is enqueued.
232  */
233 static __rte_always_inline int
234 rte_ring_mp_enqueue_elem(struct rte_ring *r, void *obj, unsigned int esize)
235 {
236 	return rte_ring_mp_enqueue_bulk_elem(r, obj, esize, 1, NULL) ? 0 :
237 								-ENOBUFS;
238 }
239 
240 /**
241  * Enqueue one object on a ring
242  *
243  * @warning This API is NOT multi-producers safe
244  *
245  * @param r
246  *   A pointer to the ring structure.
247  * @param obj
248  *   A pointer to the object to be added.
249  * @param esize
250  *   The size of ring element, in bytes. It must be a multiple of 4.
251  *   This must be the same value used while creating the ring. Otherwise
252  *   the results are undefined.
253  * @return
254  *   - 0: Success; objects enqueued.
255  *   - -ENOBUFS: Not enough room in the ring to enqueue; no object is enqueued.
256  */
257 static __rte_always_inline int
258 rte_ring_sp_enqueue_elem(struct rte_ring *r, void *obj, unsigned int esize)
259 {
260 	return rte_ring_sp_enqueue_bulk_elem(r, obj, esize, 1, NULL) ? 0 :
261 								-ENOBUFS;
262 }
263 
264 /**
265  * Enqueue one object on a ring.
266  *
267  * This function calls the multi-producer or the single-producer
268  * version, depending on the default behaviour that was specified at
269  * ring creation time (see flags).
270  *
271  * @param r
272  *   A pointer to the ring structure.
273  * @param obj
274  *   A pointer to the object to be added.
275  * @param esize
276  *   The size of ring element, in bytes. It must be a multiple of 4.
277  *   This must be the same value used while creating the ring. Otherwise
278  *   the results are undefined.
279  * @return
280  *   - 0: Success; objects enqueued.
281  *   - -ENOBUFS: Not enough room in the ring to enqueue; no object is enqueued.
282  */
283 static __rte_always_inline int
284 rte_ring_enqueue_elem(struct rte_ring *r, void *obj, unsigned int esize)
285 {
286 	return rte_ring_enqueue_bulk_elem(r, obj, esize, 1, NULL) ? 0 :
287 								-ENOBUFS;
288 }
289 
290 /**
291  * Dequeue several objects from a ring (multi-consumers safe).
292  *
293  * This function uses a "compare and set" instruction to move the
294  * consumer index atomically.
295  *
296  * @param r
297  *   A pointer to the ring structure.
298  * @param obj_table
299  *   A pointer to a table of objects that will be filled.
300  * @param esize
301  *   The size of ring element, in bytes. It must be a multiple of 4.
302  *   This must be the same value used while creating the ring. Otherwise
303  *   the results are undefined.
304  * @param n
305  *   The number of objects to dequeue from the ring to the obj_table.
306  * @param available
307  *   If non-NULL, returns the number of remaining ring entries after the
308  *   dequeue has finished.
309  * @return
310  *   The number of objects dequeued, either 0 or n
311  */
312 static __rte_always_inline unsigned int
313 rte_ring_mc_dequeue_bulk_elem(struct rte_ring *r, void *obj_table,
314 		unsigned int esize, unsigned int n, unsigned int *available)
315 {
316 	return __rte_ring_do_dequeue_elem(r, obj_table, esize, n,
317 			RTE_RING_QUEUE_FIXED, RTE_RING_SYNC_MT, available);
318 }
319 
320 /**
321  * Dequeue several objects from a ring (NOT multi-consumers safe).
322  *
323  * @param r
324  *   A pointer to the ring structure.
325  * @param obj_table
326  *   A pointer to a table of objects that will be filled.
327  * @param esize
328  *   The size of ring element, in bytes. It must be a multiple of 4.
329  *   This must be the same value used while creating the ring. Otherwise
330  *   the results are undefined.
331  * @param n
332  *   The number of objects to dequeue from the ring to the obj_table,
333  *   must be strictly positive.
334  * @param available
335  *   If non-NULL, returns the number of remaining ring entries after the
336  *   dequeue has finished.
337  * @return
338  *   The number of objects dequeued, either 0 or n
339  */
340 static __rte_always_inline unsigned int
341 rte_ring_sc_dequeue_bulk_elem(struct rte_ring *r, void *obj_table,
342 		unsigned int esize, unsigned int n, unsigned int *available)
343 {
344 	return __rte_ring_do_dequeue_elem(r, obj_table, esize, n,
345 			RTE_RING_QUEUE_FIXED, RTE_RING_SYNC_ST, available);
346 }
347 
348 /**
349  * Dequeue several objects from a ring.
350  *
351  * This function calls the multi-consumers or the single-consumer
352  * version, depending on the default behaviour that was specified at
353  * ring creation time (see flags).
354  *
355  * @param r
356  *   A pointer to the ring structure.
357  * @param obj_table
358  *   A pointer to a table of objects that will be filled.
359  * @param esize
360  *   The size of ring element, in bytes. It must be a multiple of 4.
361  *   This must be the same value used while creating the ring. Otherwise
362  *   the results are undefined.
363  * @param n
364  *   The number of objects to dequeue from the ring to the obj_table.
365  * @param available
366  *   If non-NULL, returns the number of remaining ring entries after the
367  *   dequeue has finished.
368  * @return
369  *   The number of objects dequeued, either 0 or n
370  */
371 static __rte_always_inline unsigned int
372 rte_ring_dequeue_bulk_elem(struct rte_ring *r, void *obj_table,
373 		unsigned int esize, unsigned int n, unsigned int *available)
374 {
375 	switch (r->cons.sync_type) {
376 	case RTE_RING_SYNC_MT:
377 		return rte_ring_mc_dequeue_bulk_elem(r, obj_table, esize, n,
378 			available);
379 	case RTE_RING_SYNC_ST:
380 		return rte_ring_sc_dequeue_bulk_elem(r, obj_table, esize, n,
381 			available);
382 	case RTE_RING_SYNC_MT_RTS:
383 		return rte_ring_mc_rts_dequeue_bulk_elem(r, obj_table, esize,
384 			n, available);
385 	case RTE_RING_SYNC_MT_HTS:
386 		return rte_ring_mc_hts_dequeue_bulk_elem(r, obj_table, esize,
387 			n, available);
388 	}
389 
390 	/* valid ring should never reach this point */
391 	RTE_ASSERT(0);
392 	if (available != NULL)
393 		*available = 0;
394 	return 0;
395 }
396 
397 /**
398  * Dequeue one object from a ring (multi-consumers safe).
399  *
400  * This function uses a "compare and set" instruction to move the
401  * consumer index atomically.
402  *
403  * @param r
404  *   A pointer to the ring structure.
405  * @param obj_p
406  *   A pointer to the object that will be filled.
407  * @param esize
408  *   The size of ring element, in bytes. It must be a multiple of 4.
409  *   This must be the same value used while creating the ring. Otherwise
410  *   the results are undefined.
411  * @return
412  *   - 0: Success; objects dequeued.
413  *   - -ENOENT: Not enough entries in the ring to dequeue; no object is
414  *     dequeued.
415  */
416 static __rte_always_inline int
417 rte_ring_mc_dequeue_elem(struct rte_ring *r, void *obj_p,
418 				unsigned int esize)
419 {
420 	return rte_ring_mc_dequeue_bulk_elem(r, obj_p, esize, 1, NULL)  ? 0 :
421 								-ENOENT;
422 }
423 
424 /**
425  * Dequeue one object from a ring (NOT multi-consumers safe).
426  *
427  * @param r
428  *   A pointer to the ring structure.
429  * @param obj_p
430  *   A pointer to the object that will be filled.
431  * @param esize
432  *   The size of ring element, in bytes. It must be a multiple of 4.
433  *   This must be the same value used while creating the ring. Otherwise
434  *   the results are undefined.
435  * @return
436  *   - 0: Success; objects dequeued.
437  *   - -ENOENT: Not enough entries in the ring to dequeue, no object is
438  *     dequeued.
439  */
440 static __rte_always_inline int
441 rte_ring_sc_dequeue_elem(struct rte_ring *r, void *obj_p,
442 				unsigned int esize)
443 {
444 	return rte_ring_sc_dequeue_bulk_elem(r, obj_p, esize, 1, NULL) ? 0 :
445 								-ENOENT;
446 }
447 
448 /**
449  * Dequeue one object from a ring.
450  *
451  * This function calls the multi-consumers or the single-consumer
452  * version depending on the default behaviour that was specified at
453  * ring creation time (see flags).
454  *
455  * @param r
456  *   A pointer to the ring structure.
457  * @param obj_p
458  *   A pointer to the object that will be filled.
459  * @param esize
460  *   The size of ring element, in bytes. It must be a multiple of 4.
461  *   This must be the same value used while creating the ring. Otherwise
462  *   the results are undefined.
463  * @return
464  *   - 0: Success, objects dequeued.
465  *   - -ENOENT: Not enough entries in the ring to dequeue, no object is
466  *     dequeued.
467  */
468 static __rte_always_inline int
469 rte_ring_dequeue_elem(struct rte_ring *r, void *obj_p, unsigned int esize)
470 {
471 	return rte_ring_dequeue_bulk_elem(r, obj_p, esize, 1, NULL) ? 0 :
472 								-ENOENT;
473 }
474 
475 /**
476  * Enqueue several objects on the ring (multi-producers safe).
477  *
478  * This function uses a "compare and set" instruction to move the
479  * producer index atomically.
480  *
481  * @param r
482  *   A pointer to the ring structure.
483  * @param obj_table
484  *   A pointer to a table of objects.
485  * @param esize
486  *   The size of ring element, in bytes. It must be a multiple of 4.
487  *   This must be the same value used while creating the ring. Otherwise
488  *   the results are undefined.
489  * @param n
490  *   The number of objects to add in the ring from the obj_table.
491  * @param free_space
492  *   if non-NULL, returns the amount of space in the ring after the
493  *   enqueue operation has finished.
494  * @return
495  *   - n: Actual number of objects enqueued.
496  */
497 static __rte_always_inline unsigned int
498 rte_ring_mp_enqueue_burst_elem(struct rte_ring *r, const void *obj_table,
499 		unsigned int esize, unsigned int n, unsigned int *free_space)
500 {
501 	return __rte_ring_do_enqueue_elem(r, obj_table, esize, n,
502 			RTE_RING_QUEUE_VARIABLE, RTE_RING_SYNC_MT, free_space);
503 }
504 
505 /**
506  * Enqueue several objects on a ring
507  *
508  * @warning This API is NOT multi-producers safe
509  *
510  * @param r
511  *   A pointer to the ring structure.
512  * @param obj_table
513  *   A pointer to a table of objects.
514  * @param esize
515  *   The size of ring element, in bytes. It must be a multiple of 4.
516  *   This must be the same value used while creating the ring. Otherwise
517  *   the results are undefined.
518  * @param n
519  *   The number of objects to add in the ring from the obj_table.
520  * @param free_space
521  *   if non-NULL, returns the amount of space in the ring after the
522  *   enqueue operation has finished.
523  * @return
524  *   - n: Actual number of objects enqueued.
525  */
526 static __rte_always_inline unsigned int
527 rte_ring_sp_enqueue_burst_elem(struct rte_ring *r, const void *obj_table,
528 		unsigned int esize, unsigned int n, unsigned int *free_space)
529 {
530 	return __rte_ring_do_enqueue_elem(r, obj_table, esize, n,
531 			RTE_RING_QUEUE_VARIABLE, RTE_RING_SYNC_ST, free_space);
532 }
533 
534 /**
535  * Enqueue several objects on a ring.
536  *
537  * This function calls the multi-producer or the single-producer
538  * version depending on the default behavior that was specified at
539  * ring creation time (see flags).
540  *
541  * @param r
542  *   A pointer to the ring structure.
543  * @param obj_table
544  *   A pointer to a table of objects.
545  * @param esize
546  *   The size of ring element, in bytes. It must be a multiple of 4.
547  *   This must be the same value used while creating the ring. Otherwise
548  *   the results are undefined.
549  * @param n
550  *   The number of objects to add in the ring from the obj_table.
551  * @param free_space
552  *   if non-NULL, returns the amount of space in the ring after the
553  *   enqueue operation has finished.
554  * @return
555  *   - n: Actual number of objects enqueued.
556  */
557 static __rte_always_inline unsigned int
558 rte_ring_enqueue_burst_elem(struct rte_ring *r, const void *obj_table,
559 		unsigned int esize, unsigned int n, unsigned int *free_space)
560 {
561 	switch (r->prod.sync_type) {
562 	case RTE_RING_SYNC_MT:
563 		return rte_ring_mp_enqueue_burst_elem(r, obj_table, esize, n,
564 			free_space);
565 	case RTE_RING_SYNC_ST:
566 		return rte_ring_sp_enqueue_burst_elem(r, obj_table, esize, n,
567 			free_space);
568 	case RTE_RING_SYNC_MT_RTS:
569 		return rte_ring_mp_rts_enqueue_burst_elem(r, obj_table, esize,
570 			n, free_space);
571 	case RTE_RING_SYNC_MT_HTS:
572 		return rte_ring_mp_hts_enqueue_burst_elem(r, obj_table, esize,
573 			n, free_space);
574 	}
575 
576 	/* valid ring should never reach this point */
577 	RTE_ASSERT(0);
578 	if (free_space != NULL)
579 		*free_space = 0;
580 	return 0;
581 }
582 
583 /**
584  * Dequeue several objects from a ring (multi-consumers safe). When the request
585  * objects are more than the available objects, only dequeue the actual number
586  * of objects
587  *
588  * This function uses a "compare and set" instruction to move the
589  * consumer index atomically.
590  *
591  * @param r
592  *   A pointer to the ring structure.
593  * @param obj_table
594  *   A pointer to a table of objects that will be filled.
595  * @param esize
596  *   The size of ring element, in bytes. It must be a multiple of 4.
597  *   This must be the same value used while creating the ring. Otherwise
598  *   the results are undefined.
599  * @param n
600  *   The number of objects to dequeue from the ring to the obj_table.
601  * @param available
602  *   If non-NULL, returns the number of remaining ring entries after the
603  *   dequeue has finished.
604  * @return
605  *   - n: Actual number of objects dequeued, 0 if ring is empty
606  */
607 static __rte_always_inline unsigned int
608 rte_ring_mc_dequeue_burst_elem(struct rte_ring *r, void *obj_table,
609 		unsigned int esize, unsigned int n, unsigned int *available)
610 {
611 	return __rte_ring_do_dequeue_elem(r, obj_table, esize, n,
612 			RTE_RING_QUEUE_VARIABLE, RTE_RING_SYNC_MT, available);
613 }
614 
615 /**
616  * Dequeue several objects from a ring (NOT multi-consumers safe).When the
617  * request objects are more than the available objects, only dequeue the
618  * actual number of objects
619  *
620  * @param r
621  *   A pointer to the ring structure.
622  * @param obj_table
623  *   A pointer to a table of objects that will be filled.
624  * @param esize
625  *   The size of ring element, in bytes. It must be a multiple of 4.
626  *   This must be the same value used while creating the ring. Otherwise
627  *   the results are undefined.
628  * @param n
629  *   The number of objects to dequeue from the ring to the obj_table.
630  * @param available
631  *   If non-NULL, returns the number of remaining ring entries after the
632  *   dequeue has finished.
633  * @return
634  *   - n: Actual number of objects dequeued, 0 if ring is empty
635  */
636 static __rte_always_inline unsigned int
637 rte_ring_sc_dequeue_burst_elem(struct rte_ring *r, void *obj_table,
638 		unsigned int esize, unsigned int n, unsigned int *available)
639 {
640 	return __rte_ring_do_dequeue_elem(r, obj_table, esize, n,
641 			RTE_RING_QUEUE_VARIABLE, RTE_RING_SYNC_ST, available);
642 }
643 
644 /**
645  * Dequeue multiple objects from a ring up to a maximum number.
646  *
647  * This function calls the multi-consumers or the single-consumer
648  * version, depending on the default behaviour that was specified at
649  * ring creation time (see flags).
650  *
651  * @param r
652  *   A pointer to the ring structure.
653  * @param obj_table
654  *   A pointer to a table of objects that will be filled.
655  * @param esize
656  *   The size of ring element, in bytes. It must be a multiple of 4.
657  *   This must be the same value used while creating the ring. Otherwise
658  *   the results are undefined.
659  * @param n
660  *   The number of objects to dequeue from the ring to the obj_table.
661  * @param available
662  *   If non-NULL, returns the number of remaining ring entries after the
663  *   dequeue has finished.
664  * @return
665  *   - Number of objects dequeued
666  */
667 static __rte_always_inline unsigned int
668 rte_ring_dequeue_burst_elem(struct rte_ring *r, void *obj_table,
669 		unsigned int esize, unsigned int n, unsigned int *available)
670 {
671 	switch (r->cons.sync_type) {
672 	case RTE_RING_SYNC_MT:
673 		return rte_ring_mc_dequeue_burst_elem(r, obj_table, esize, n,
674 			available);
675 	case RTE_RING_SYNC_ST:
676 		return rte_ring_sc_dequeue_burst_elem(r, obj_table, esize, n,
677 			available);
678 	case RTE_RING_SYNC_MT_RTS:
679 		return rte_ring_mc_rts_dequeue_burst_elem(r, obj_table, esize,
680 			n, available);
681 	case RTE_RING_SYNC_MT_HTS:
682 		return rte_ring_mc_hts_dequeue_burst_elem(r, obj_table, esize,
683 			n, available);
684 	}
685 
686 	/* valid ring should never reach this point */
687 	RTE_ASSERT(0);
688 	if (available != NULL)
689 		*available = 0;
690 	return 0;
691 }
692 
693 #include <rte_ring_peek.h>
694 #include <rte_ring_peek_zc.h>
695 
696 #include <rte_ring.h>
697 
698 #endif /* _RTE_RING_ELEM_H_ */
699