1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2016-2017 Intel Corporation 3 */ 4 5 /* 6 * Generic ring structure for passing events from one core to another. 7 * 8 * Used by the software scheduler for the producer and consumer rings for 9 * each port, i.e. for passing events from worker cores to scheduler and 10 * vice-versa. Designed for single-producer, single-consumer use with two 11 * cores working on each ring. 12 */ 13 14 #ifndef _EVENT_RING_ 15 #define _EVENT_RING_ 16 17 #include <stdint.h> 18 19 #include <rte_common.h> 20 #include <rte_memory.h> 21 #include <rte_malloc.h> 22 23 /* Custom single threaded ring implementation used for ROB */ 24 struct rob_ring { 25 uint32_t ring_size; 26 uint32_t mask; 27 uint32_t size; 28 uint32_t write_idx; 29 uint32_t read_idx; 30 alignas(RTE_CACHE_LINE_SIZE) void *ring[]; 31 }; 32 33 static inline struct rob_ring * 34 rob_ring_create(unsigned int size, unsigned int socket_id) 35 { 36 struct rob_ring *retval; 37 const uint32_t ring_size = rte_align32pow2(size + 1); 38 size_t memsize = sizeof(*retval) + 39 (ring_size * sizeof(retval->ring[0])); 40 41 retval = rte_zmalloc_socket(NULL, memsize, 0, socket_id); 42 if (retval == NULL) 43 goto end; 44 retval->ring_size = ring_size; 45 retval->mask = ring_size - 1; 46 retval->size = size; 47 end: 48 return retval; 49 } 50 51 static inline void 52 rob_ring_free(struct rob_ring *r) 53 { 54 rte_free(r); 55 } 56 57 static __rte_always_inline unsigned int 58 rob_ring_count(const struct rob_ring *r) 59 { 60 return r->write_idx - r->read_idx; 61 } 62 63 static __rte_always_inline unsigned int 64 rob_ring_free_count(const struct rob_ring *r) 65 { 66 return r->size - rob_ring_count(r); 67 } 68 69 static __rte_always_inline unsigned int 70 rob_ring_enqueue(struct rob_ring *r, void *re) 71 { 72 const uint32_t size = r->size; 73 const uint32_t mask = r->mask; 74 const uint32_t read = r->read_idx; 75 uint32_t write = r->write_idx; 76 const uint32_t space = read + size - write; 77 if (space < 1) 78 return 0; 79 r->ring[write & mask] = re; 80 r->write_idx++; 81 return 1; 82 } 83 84 static __rte_always_inline unsigned int 85 rob_ring_dequeue(struct rob_ring *r, void **re) 86 { 87 const uint32_t mask = r->mask; 88 uint32_t read = r->read_idx; 89 const uint32_t write = r->write_idx; 90 const uint32_t items = write - read; 91 if (items < 1) 92 return 0; 93 *re = r->ring[read & mask]; 94 r->read_idx++; 95 return 1; 96 } 97 98 #endif 99