15566a3e3SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 25566a3e3SBruce Richardson * Copyright(c) 2016-2017 Intel Corporation 398dc055fSBruce Richardson */ 498dc055fSBruce Richardson 598dc055fSBruce Richardson /* 698dc055fSBruce Richardson * Generic ring structure for passing events from one core to another. 798dc055fSBruce Richardson * 898dc055fSBruce Richardson * Used by the software scheduler for the producer and consumer rings for 998dc055fSBruce Richardson * each port, i.e. for passing events from worker cores to scheduler and 1098dc055fSBruce Richardson * vice-versa. Designed for single-producer, single-consumer use with two 1198dc055fSBruce Richardson * cores working on each ring. 1298dc055fSBruce Richardson */ 1398dc055fSBruce Richardson 1498dc055fSBruce Richardson #ifndef _EVENT_RING_ 1598dc055fSBruce Richardson #define _EVENT_RING_ 1698dc055fSBruce Richardson 1798dc055fSBruce Richardson #include <stdint.h> 1898dc055fSBruce Richardson 1998dc055fSBruce Richardson #include <rte_common.h> 2098dc055fSBruce Richardson #include <rte_memory.h> 2198dc055fSBruce Richardson #include <rte_malloc.h> 2298dc055fSBruce Richardson 2370207f35SRadu Nicolau /* Custom single threaded ring implementation used for ROB */ 2470207f35SRadu Nicolau struct rob_ring { 2570207f35SRadu Nicolau uint32_t ring_size; 2670207f35SRadu Nicolau uint32_t mask; 2770207f35SRadu Nicolau uint32_t size; 2870207f35SRadu Nicolau uint32_t write_idx; 2970207f35SRadu Nicolau uint32_t read_idx; 30*29911b32SStephen Hemminger alignas(RTE_CACHE_LINE_SIZE) void *ring[]; 3198dc055fSBruce Richardson }; 3298dc055fSBruce Richardson 3370207f35SRadu Nicolau static inline struct rob_ring * 3470207f35SRadu Nicolau rob_ring_create(unsigned int size, unsigned int socket_id) 3598dc055fSBruce Richardson { 3670207f35SRadu Nicolau struct rob_ring *retval; 3798dc055fSBruce Richardson const uint32_t ring_size = rte_align32pow2(size + 1); 3898dc055fSBruce Richardson size_t memsize = sizeof(*retval) + 3998dc055fSBruce Richardson (ring_size * sizeof(retval->ring[0])); 4098dc055fSBruce Richardson 4198dc055fSBruce Richardson retval = rte_zmalloc_socket(NULL, memsize, 0, socket_id); 4298dc055fSBruce Richardson if (retval == NULL) 4398dc055fSBruce Richardson goto end; 4498dc055fSBruce Richardson retval->ring_size = ring_size; 4598dc055fSBruce Richardson retval->mask = ring_size - 1; 4698dc055fSBruce Richardson retval->size = size; 4798dc055fSBruce Richardson end: 4898dc055fSBruce Richardson return retval; 4998dc055fSBruce Richardson } 5098dc055fSBruce Richardson 5198dc055fSBruce Richardson static inline void 5270207f35SRadu Nicolau rob_ring_free(struct rob_ring *r) 5398dc055fSBruce Richardson { 5498dc055fSBruce Richardson rte_free(r); 5598dc055fSBruce Richardson } 5698dc055fSBruce Richardson 57c0583d98SJerin Jacob static __rte_always_inline unsigned int 5870207f35SRadu Nicolau rob_ring_count(const struct rob_ring *r) 5998dc055fSBruce Richardson { 6098dc055fSBruce Richardson return r->write_idx - r->read_idx; 6198dc055fSBruce Richardson } 6298dc055fSBruce Richardson 63c0583d98SJerin Jacob static __rte_always_inline unsigned int 6470207f35SRadu Nicolau rob_ring_free_count(const struct rob_ring *r) 6598dc055fSBruce Richardson { 6670207f35SRadu Nicolau return r->size - rob_ring_count(r); 6798dc055fSBruce Richardson } 6898dc055fSBruce Richardson 69c0583d98SJerin Jacob static __rte_always_inline unsigned int 7070207f35SRadu Nicolau rob_ring_enqueue(struct rob_ring *r, void *re) 7198dc055fSBruce Richardson { 7298dc055fSBruce Richardson const uint32_t size = r->size; 7398dc055fSBruce Richardson const uint32_t mask = r->mask; 7498dc055fSBruce Richardson const uint32_t read = r->read_idx; 7598dc055fSBruce Richardson uint32_t write = r->write_idx; 7698dc055fSBruce Richardson const uint32_t space = read + size - write; 7770207f35SRadu Nicolau if (space < 1) 7870207f35SRadu Nicolau return 0; 7970207f35SRadu Nicolau r->ring[write & mask] = re; 8070207f35SRadu Nicolau r->write_idx++; 8170207f35SRadu Nicolau return 1; 8298dc055fSBruce Richardson } 8398dc055fSBruce Richardson 84c0583d98SJerin Jacob static __rte_always_inline unsigned int 8570207f35SRadu Nicolau rob_ring_dequeue(struct rob_ring *r, void **re) 8698dc055fSBruce Richardson { 8798dc055fSBruce Richardson const uint32_t mask = r->mask; 8898dc055fSBruce Richardson uint32_t read = r->read_idx; 8998dc055fSBruce Richardson const uint32_t write = r->write_idx; 9098dc055fSBruce Richardson const uint32_t items = write - read; 9170207f35SRadu Nicolau if (items < 1) 9270207f35SRadu Nicolau return 0; 9370207f35SRadu Nicolau *re = r->ring[read & mask]; 9470207f35SRadu Nicolau r->read_idx++; 9570207f35SRadu Nicolau return 1; 9698dc055fSBruce Richardson } 9798dc055fSBruce Richardson 9898dc055fSBruce Richardson #endif 99