Branch data Line data Source code
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 : 12 : 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 : 12 : size_t memsize = sizeof(*retval) + 39 : : (ring_size * sizeof(retval->ring[0])); 40 : : 41 : 12 : retval = rte_zmalloc_socket(NULL, memsize, 0, socket_id); 42 [ - + ]: 12 : if (retval == NULL) 43 : 0 : goto end; 44 : 12 : retval->ring_size = ring_size; 45 : 12 : retval->mask = ring_size - 1; 46 : 12 : retval->size = size; 47 : 12 : end: 48 : 12 : return retval; 49 : : } 50 : : 51 : : static inline void 52 : : rob_ring_free(struct rob_ring *r) 53 : : { 54 : 19 : rte_free(r); 55 : 19 : } 56 : : 57 : : static __rte_always_inline unsigned int 58 : : rob_ring_count(const struct rob_ring *r) 59 : : { 60 : 4 : 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 [ - + ]: 4210709 : 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 : 12276 : const uint32_t size = r->size; 73 : 12282 : const uint32_t mask = r->mask; 74 : 12276 : const uint32_t read = r->read_idx; 75 : 12282 : uint32_t write = r->write_idx; 76 : 12282 : const uint32_t space = read + size - write; 77 [ + + ]: 12282 : if (space < 1) 78 : : return 0; 79 : 12282 : r->ring[write & mask] = re; 80 : 12282 : r->write_idx++; 81 : 6 : return 1; 82 : : } 83 : : 84 : : static __rte_always_inline unsigned int 85 : : rob_ring_dequeue(struct rob_ring *r, void **re) 86 : : { 87 : 6 : const uint32_t mask = r->mask; 88 : 6 : uint32_t read = r->read_idx; 89 : 6 : const uint32_t write = r->write_idx; 90 : : const uint32_t items = write - read; 91 [ + - ]: 6 : if (items < 1) 92 : : return 0; 93 : 6 : *re = r->ring[read & mask]; 94 : 6 : r->read_idx++; 95 : 6 : return 1; 96 : : } 97 : : 98 : : #endif