1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2016-2017 Intel Corporation
3 * Copyright(c) 2019 Arm Limited
4 */
5
6 /**
7 * @file
8 * RTE Event Ring
9 *
10 * This provides a ring implementation for passing rte_event structures
11 * from one core to another.
12 */
13
14 #ifndef _RTE_EVENT_RING_
15 #define _RTE_EVENT_RING_
16
17 #ifdef __cplusplus
18 extern "C" {
19 #endif
20
21 #include <stdint.h>
22
23 #include <rte_common.h>
24 #include <rte_ring.h>
25 #include <rte_ring_elem.h>
26 #include "rte_eventdev.h"
27
28 #define RTE_TAILQ_EVENT_RING_NAME "RTE_EVENT_RING"
29
30 /**
31 * Generic ring structure for passing rte_event objects from core to core.
32 *
33 * Based on the primitives given in the rte_ring library. Designed to be
34 * used inside software eventdev implementations and by applications
35 * directly as needed.
36 */
37 struct rte_event_ring {
38 struct rte_ring r;
39 };
40
41 /**
42 * Returns the number of events in the ring
43 *
44 * @param r
45 * pointer to the event ring
46 * @return
47 * the number of events in the ring
48 */
49 static __rte_always_inline unsigned int
rte_event_ring_count(const struct rte_event_ring * r)50 rte_event_ring_count(const struct rte_event_ring *r)
51 {
52 return rte_ring_count(&r->r);
53 }
54
55 /**
56 * Returns the amount of free space in the ring
57 *
58 * @param r
59 * pointer to the event ring
60 * @return
61 * the number of free slots in the ring, i.e. the number of events that
62 * can be successfully enqueued before dequeue must be called
63 */
64 static __rte_always_inline unsigned int
rte_event_ring_free_count(const struct rte_event_ring * r)65 rte_event_ring_free_count(const struct rte_event_ring *r)
66 {
67 return rte_ring_free_count(&r->r);
68 }
69
70 /**
71 * Enqueue a set of events onto a ring
72 *
73 * Note: this API enqueues by copying the events themselves onto the ring,
74 * rather than just placing a pointer to each event onto the ring. This
75 * means that statically-allocated events can safely be enqueued by this
76 * API.
77 *
78 * @param r
79 * pointer to the event ring
80 * @param events
81 * pointer to an array of struct rte_event objects
82 * @param n
83 * number of events in the array to enqueue
84 * @param free_space
85 * if non-null, is updated to indicate the amount of free space in the
86 * ring once the enqueue has completed.
87 * @return
88 * the number of elements, n', enqueued to the ring, 0 <= n' <= n
89 */
90 static __rte_always_inline unsigned int
rte_event_ring_enqueue_burst(struct rte_event_ring * r,const struct rte_event * events,unsigned int n,uint16_t * free_space)91 rte_event_ring_enqueue_burst(struct rte_event_ring *r,
92 const struct rte_event *events,
93 unsigned int n, uint16_t *free_space)
94 {
95 unsigned int num;
96 uint32_t space;
97
98 num = rte_ring_enqueue_burst_elem(&r->r, events,
99 sizeof(struct rte_event), n,
100 &space);
101
102 if (free_space != NULL)
103 *free_space = space;
104
105 return num;
106 }
107
108 /**
109 * Dequeue a set of events from a ring
110 *
111 * Note: this API does not work with pointers to events, rather it copies
112 * the events themselves to the destination ``events`` buffer.
113 *
114 * @param r
115 * pointer to the event ring
116 * @param events
117 * pointer to an array to hold the struct rte_event objects
118 * @param n
119 * number of events that can be held in the ``events`` array
120 * @param available
121 * if non-null, is updated to indicate the number of events remaining in
122 * the ring once the dequeue has completed
123 * @return
124 * the number of elements, n', dequeued from the ring, 0 <= n' <= n
125 */
126 static __rte_always_inline unsigned int
rte_event_ring_dequeue_burst(struct rte_event_ring * r,struct rte_event * events,unsigned int n,uint16_t * available)127 rte_event_ring_dequeue_burst(struct rte_event_ring *r,
128 struct rte_event *events,
129 unsigned int n, uint16_t *available)
130 {
131 unsigned int num;
132 uint32_t remaining;
133
134 num = rte_ring_dequeue_burst_elem(&r->r, events,
135 sizeof(struct rte_event), n,
136 &remaining);
137
138 if (available != NULL)
139 *available = remaining;
140
141 return num;
142 }
143
144 /*
145 * Initializes an already-allocated ring structure
146 *
147 * @param r
148 * pointer to the ring memory to be initialized
149 * @param name
150 * name to be given to the ring
151 * @param count
152 * the number of elements to be stored in the ring. If the flag
153 * ``RING_F_EXACT_SZ`` is not set, this must be a power of 2, and the actual
154 * usable space in the ring will be ``count - 1`` entries. If the flag
155 * ``RING_F_EXACT_SZ`` is set, the this can be any value up to the ring size
156 * limit - 1, and the usable space will be exactly that requested.
157 * @param flags
158 * An OR of the following:
159 * - RING_F_SP_ENQ: If this flag is set, the default behavior when
160 * using ``rte_ring_enqueue()`` or ``rte_ring_enqueue_bulk()``
161 * is "single-producer". Otherwise, it is "multi-producers".
162 * - RING_F_SC_DEQ: If this flag is set, the default behavior when
163 * using ``rte_ring_dequeue()`` or ``rte_ring_dequeue_bulk()``
164 * is "single-consumer". Otherwise, it is "multi-consumers".
165 * - RING_F_EXACT_SZ: If this flag is set, the ``count`` parameter is to
166 * be taken as the exact usable size of the ring, and as such does not
167 * need to be a power of 2. The underlying ring memory should be a
168 * power-of-2 size greater than the count value.
169 * @return
170 * 0 on success, or a negative value on error.
171 */
172 int
173 rte_event_ring_init(struct rte_event_ring *r, const char *name,
174 unsigned int count, unsigned int flags);
175
176 /*
177 * Create an event ring structure
178 *
179 * This function allocates memory and initializes an event ring inside that
180 * memory.
181 *
182 * @param name
183 * name to be given to the ring
184 * @param count
185 * the number of elements to be stored in the ring. If the flag
186 * ``RING_F_EXACT_SZ`` is not set, this must be a power of 2, and the actual
187 * usable space in the ring will be ``count - 1`` entries. If the flag
188 * ``RING_F_EXACT_SZ`` is set, the this can be any value up to the ring size
189 * limit - 1, and the usable space will be exactly that requested.
190 * @param socket_id
191 * The *socket_id* argument is the socket identifier in case of
192 * NUMA. The value can be *SOCKET_ID_ANY* if there is no NUMA
193 * constraint for the reserved zone.
194 * @param flags
195 * An OR of the following:
196 * - RING_F_SP_ENQ: If this flag is set, the default behavior when
197 * using ``rte_ring_enqueue()`` or ``rte_ring_enqueue_bulk()``
198 * is "single-producer". Otherwise, it is "multi-producers".
199 * - RING_F_SC_DEQ: If this flag is set, the default behavior when
200 * using ``rte_ring_dequeue()`` or ``rte_ring_dequeue_bulk()``
201 * is "single-consumer". Otherwise, it is "multi-consumers".
202 * - RING_F_EXACT_SZ: If this flag is set, the ``count`` parameter is to
203 * be taken as the exact usable size of the ring, and as such does not
204 * need to be a power of 2. The underlying ring memory should be a
205 * power-of-2 size greater than the count value.
206 * @return
207 * On success, the pointer to the new allocated ring. NULL on error with
208 * rte_errno set appropriately. Possible errno values include:
209 * - E_RTE_NO_CONFIG - function could not get pointer to rte_config structure
210 * - E_RTE_SECONDARY - function was called from a secondary process instance
211 * - EINVAL - count provided is not a power of 2
212 * - ENOSPC - the maximum number of memzones has already been allocated
213 * - EEXIST - a memzone with the same name already exists
214 * - ENOMEM - no appropriate memory area found in which to create memzone
215 */
216 struct rte_event_ring *
217 rte_event_ring_create(const char *name, unsigned int count, int socket_id,
218 unsigned int flags);
219
220 /**
221 * Search for an event ring based on its name
222 *
223 * @param name
224 * The name of the ring.
225 * @return
226 * The pointer to the ring matching the name, or NULL if not found,
227 * with rte_errno set appropriately. Possible rte_errno values include:
228 * - ENOENT - required entry not available to return.
229 */
230 struct rte_event_ring *
231 rte_event_ring_lookup(const char *name);
232
233 /**
234 * De-allocate all memory used by the ring.
235 *
236 * @param r
237 * Ring to free
238 */
239 void
240 rte_event_ring_free(struct rte_event_ring *r);
241
242 /**
243 * Return the size of the event ring.
244 *
245 * @param r
246 * A pointer to the ring structure.
247 * @return
248 * The size of the data store used by the ring.
249 * NOTE: this is not the same as the usable space in the ring. To query that
250 * use ``rte_ring_get_capacity()``.
251 */
252 static inline unsigned int
rte_event_ring_get_size(const struct rte_event_ring * r)253 rte_event_ring_get_size(const struct rte_event_ring *r)
254 {
255 return rte_ring_get_size(&r->r);
256 }
257
258 /**
259 * Return the number of elements which can be stored in the event ring.
260 *
261 * @param r
262 * A pointer to the ring structure.
263 * @return
264 * The usable size of the ring.
265 */
266 static inline unsigned int
rte_event_ring_get_capacity(const struct rte_event_ring * r)267 rte_event_ring_get_capacity(const struct rte_event_ring *r)
268 {
269 return rte_ring_get_capacity(&r->r);
270 }
271
272 #ifdef __cplusplus
273 }
274 #endif
275
276 #endif
277