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