96 #include <sys/queue.h>
106 #define RTE_TAILQ_RING_NAME "RTE_RING"
108 enum rte_ring_queue_behavior {
109 RTE_RING_QUEUE_FIXED = 0,
110 RTE_RING_QUEUE_VARIABLE
113 #define RTE_RING_MZ_PREFIX "RG_"
115 #define RTE_RING_NAMESIZE (RTE_MEMZONE_NAMESIZE - \
116 sizeof(RTE_RING_MZ_PREFIX) + 1)
120 #if RTE_CACHE_LINE_SIZE < 128
121 #define PROD_ALIGN (RTE_CACHE_LINE_SIZE * 2)
122 #define CONS_ALIGN (RTE_CACHE_LINE_SIZE * 2)
124 #define PROD_ALIGN RTE_CACHE_LINE_SIZE
125 #define CONS_ALIGN RTE_CACHE_LINE_SIZE
129 struct rte_ring_headtail {
130 volatile uint32_t head;
131 volatile uint32_t tail;
166 #define RING_F_SP_ENQ 0x0001
167 #define RING_F_SC_DEQ 0x0002
176 #define RING_F_EXACT_SZ 0x0004
177 #define RTE_RING_SZ_MASK (unsigned)(0x0fffffff)
278 int socket_id,
unsigned flags);
300 #define ENQUEUE_PTRS(r, ring_start, prod_head, obj_table, n, obj_type) do { \
302 const uint32_t size = (r)->size; \
303 uint32_t idx = prod_head & (r)->mask; \
304 obj_type *ring = (obj_type *)ring_start; \
305 if (likely(idx + n < size)) { \
306 for (i = 0; i < (n & ((~(unsigned)0x3))); i+=4, idx+=4) { \
307 ring[idx] = obj_table[i]; \
308 ring[idx+1] = obj_table[i+1]; \
309 ring[idx+2] = obj_table[i+2]; \
310 ring[idx+3] = obj_table[i+3]; \
314 ring[idx++] = obj_table[i++]; \
316 ring[idx++] = obj_table[i++]; \
318 ring[idx++] = obj_table[i++]; \
321 for (i = 0; idx < size; i++, idx++)\
322 ring[idx] = obj_table[i]; \
323 for (idx = 0; i < n; i++, idx++) \
324 ring[idx] = obj_table[i]; \
331 #define DEQUEUE_PTRS(r, ring_start, cons_head, obj_table, n, obj_type) do { \
333 uint32_t idx = cons_head & (r)->mask; \
334 const uint32_t size = (r)->size; \
335 obj_type *ring = (obj_type *)ring_start; \
336 if (likely(idx + n < size)) { \
337 for (i = 0; i < (n & (~(unsigned)0x3)); i+=4, idx+=4) {\
338 obj_table[i] = ring[idx]; \
339 obj_table[i+1] = ring[idx+1]; \
340 obj_table[i+2] = ring[idx+2]; \
341 obj_table[i+3] = ring[idx+3]; \
345 obj_table[i++] = ring[idx++]; \
347 obj_table[i++] = ring[idx++]; \
349 obj_table[i++] = ring[idx++]; \
352 for (i = 0; idx < size; i++, idx++) \
353 obj_table[i] = ring[idx]; \
354 for (idx = 0; i < n; i++, idx++) \
355 obj_table[i] = ring[idx]; \
360 update_tail(
struct rte_ring_headtail *ht, uint32_t old_val, uint32_t new_val,
368 while (
unlikely(ht->tail != old_val))
398 __rte_ring_move_prod_head(
struct rte_ring *r,
int is_sp,
399 unsigned int n,
enum rte_ring_queue_behavior behavior,
400 uint32_t *old_head, uint32_t *new_head,
401 uint32_t *free_entries)
404 unsigned int max = n;
411 *old_head = r->prod.head;
412 const uint32_t cons_tail = r->cons.tail;
419 *free_entries = (capacity + cons_tail - *old_head);
423 n = (behavior == RTE_RING_QUEUE_FIXED) ?
429 *new_head = *old_head + n;
431 r->prod.head = *new_head, success = 1;
434 *old_head, *new_head);
460 __rte_ring_do_enqueue(
struct rte_ring *r,
void *
const *obj_table,
461 unsigned int n,
enum rte_ring_queue_behavior behavior,
462 int is_sp,
unsigned int *free_space)
464 uint32_t prod_head, prod_next;
465 uint32_t free_entries;
467 n = __rte_ring_move_prod_head(r, is_sp, n, behavior,
468 &prod_head, &prod_next, &free_entries);
472 ENQUEUE_PTRS(r, &r[1], prod_head, obj_table, n,
void *);
475 update_tail(&r->prod, prod_head, prod_next, is_sp);
477 if (free_space != NULL)
478 *free_space = free_entries - n;
506 __rte_ring_move_cons_head(
struct rte_ring *r,
int is_sc,
507 unsigned int n,
enum rte_ring_queue_behavior behavior,
508 uint32_t *old_head, uint32_t *new_head,
511 unsigned int max = n;
519 *old_head = r->cons.head;
520 const uint32_t prod_tail = r->prod.tail;
525 *entries = (prod_tail - *old_head);
529 n = (behavior == RTE_RING_QUEUE_FIXED) ? 0 : *entries;
534 *new_head = *old_head + n;
536 r->cons.head = *new_head, success = 1;
565 __rte_ring_do_dequeue(
struct rte_ring *r,
void **obj_table,
566 unsigned int n,
enum rte_ring_queue_behavior behavior,
567 int is_sc,
unsigned int *available)
569 uint32_t cons_head, cons_next;
572 n = __rte_ring_move_cons_head(r, is_sc, n, behavior,
573 &cons_head, &cons_next, &entries);
577 DEQUEUE_PTRS(r, &r[1], cons_head, obj_table, n,
void *);
580 update_tail(&r->cons, cons_head, cons_next, is_sc);
583 if (available != NULL)
584 *available = entries - n;
608 unsigned int n,
unsigned int *free_space)
610 return __rte_ring_do_enqueue(r, obj_table, n, RTE_RING_QUEUE_FIXED,
611 __IS_MP, free_space);
631 unsigned int n,
unsigned int *free_space)
633 return __rte_ring_do_enqueue(r, obj_table, n, RTE_RING_QUEUE_FIXED,
634 __IS_SP, free_space);
658 unsigned int n,
unsigned int *free_space)
660 return __rte_ring_do_enqueue(r, obj_table, n, RTE_RING_QUEUE_FIXED,
661 r->prod.single, free_space);
742 unsigned int n,
unsigned int *available)
744 return __rte_ring_do_dequeue(r, obj_table, n, RTE_RING_QUEUE_FIXED,
766 unsigned int n,
unsigned int *available)
768 return __rte_ring_do_dequeue(r, obj_table, n, RTE_RING_QUEUE_FIXED,
793 unsigned int *available)
795 return __rte_ring_do_dequeue(r, obj_table, n, RTE_RING_QUEUE_FIXED,
796 r->cons.single, available);
868 static inline unsigned
871 uint32_t prod_tail = r->prod.tail;
872 uint32_t cons_tail = r->cons.tail;
873 uint32_t count = (prod_tail - cons_tail) & r->
mask;
885 static inline unsigned
931 static inline unsigned int
945 static inline unsigned int
991 unsigned int n,
unsigned int *free_space)
993 return __rte_ring_do_enqueue(r, obj_table, n,
994 RTE_RING_QUEUE_VARIABLE, __IS_MP, free_space);
1014 unsigned int n,
unsigned int *free_space)
1016 return __rte_ring_do_enqueue(r, obj_table, n,
1017 RTE_RING_QUEUE_VARIABLE, __IS_SP, free_space);
1041 unsigned int n,
unsigned int *free_space)
1043 return __rte_ring_do_enqueue(r, obj_table, n, RTE_RING_QUEUE_VARIABLE,
1044 r->prod.single, free_space);
1069 unsigned int n,
unsigned int *available)
1071 return __rte_ring_do_dequeue(r, obj_table, n,
1072 RTE_RING_QUEUE_VARIABLE, __IS_MC, available);
1094 unsigned int n,
unsigned int *available)
1096 return __rte_ring_do_dequeue(r, obj_table, n,
1097 RTE_RING_QUEUE_VARIABLE, __IS_SC, available);
1121 unsigned int n,
unsigned int *available)
1123 return __rte_ring_do_dequeue(r, obj_table, n,
1124 RTE_RING_QUEUE_VARIABLE,
1125 r->cons.single, available);