xref: /dpdk/drivers/event/sw/event_ring.h (revision 29911b323e7a4200b95e2049df08779c0673fbfc)
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