xref: /dpdk/lib/eventdev/rte_event_ring.h (revision 719834a6849e1daf4a70ff7742bbcc3ae7e25607)
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 #include <stdint.h>
18 
19 #include <rte_common.h>
20 #include <rte_ring.h>
21 #include <rte_ring_elem.h>
22 #include "rte_eventdev.h"
23 
24 #ifdef __cplusplus
25 extern "C" {
26 #endif
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
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
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 /**
72  * Enqueue several objects on a ring.
73  *
74  * This function calls the multi-producer or the single-producer
75  * version depending on the default behavior that was specified at
76  * ring creation time (see flags).
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  *   The number of events in the array to enqueue
84  * @param free_space
85  *   if non-NULL, returns the amount of space in the ring after the
86  *   enqueue operation has completed
87  * @return
88  *   the number of objects enqueued, either 0 or n
89  */
90 static __rte_always_inline unsigned int
91 rte_event_ring_enqueue_bulk(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_bulk_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 objects dequeued, either 0 or n
125  */
126 static __rte_always_inline unsigned int
127 rte_event_ring_dequeue_bulk(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_bulk_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  * Enqueue a set of events onto a ring
146  *
147  * Note: this API enqueues by copying the events themselves onto the ring,
148  * rather than just placing a pointer to each event onto the ring. This
149  * means that statically-allocated events can safely be enqueued by this
150  * API.
151  *
152  * @param r
153  *   pointer to the event ring
154  * @param events
155  *   pointer to an array of struct rte_event objects
156  * @param n
157  *   number of events in the array to enqueue
158  * @param free_space
159  *   if non-null, is updated to indicate the amount of free space in the
160  *   ring once the enqueue has completed.
161  * @return
162  *   the number of elements, n', enqueued to the ring, 0 <= n' <= n
163  */
164 static __rte_always_inline unsigned int
165 rte_event_ring_enqueue_burst(struct rte_event_ring *r,
166 		const struct rte_event *events,
167 		unsigned int n, uint16_t *free_space)
168 {
169 	unsigned int num;
170 	uint32_t space;
171 
172 	num = rte_ring_enqueue_burst_elem(&r->r, events,
173 				sizeof(struct rte_event), n,
174 				&space);
175 
176 	if (free_space != NULL)
177 		*free_space = space;
178 
179 	return num;
180 }
181 
182 /**
183  * Dequeue a set of events from a ring
184  *
185  * Note: this API does not work with pointers to events, rather it copies
186  * the events themselves to the destination ``events`` buffer.
187  *
188  * @param r
189  *   pointer to the event ring
190  * @param events
191  *   pointer to an array to hold the struct rte_event objects
192  * @param n
193  *   number of events that can be held in the ``events`` array
194  * @param available
195  *   if non-null, is updated to indicate the number of events remaining in
196  *   the ring once the dequeue has completed
197  * @return
198  *   the number of elements, n', dequeued from the ring, 0 <= n' <= n
199  */
200 static __rte_always_inline unsigned int
201 rte_event_ring_dequeue_burst(struct rte_event_ring *r,
202 		struct rte_event *events,
203 		unsigned int n, uint16_t *available)
204 {
205 	unsigned int num;
206 	uint32_t remaining;
207 
208 	num = rte_ring_dequeue_burst_elem(&r->r, events,
209 				sizeof(struct rte_event), n,
210 				&remaining);
211 
212 	if (available != NULL)
213 		*available = remaining;
214 
215 	return num;
216 }
217 
218 /*
219  * Initializes an already-allocated ring structure
220  *
221  * @param r
222  *   pointer to the ring memory to be initialized
223  * @param name
224  *   name to be given to the ring
225  * @param count
226  *   the number of elements to be stored in the ring. If the flag
227  *   ``RING_F_EXACT_SZ`` is not set, this must be a power of 2, and the actual
228  *   usable space in the ring will be ``count - 1`` entries. If the flag
229  *   ``RING_F_EXACT_SZ`` is set, the this can be any value up to the ring size
230  *   limit - 1, and the usable space will be exactly that requested.
231  * @param flags
232  *   An OR of the following:
233  *    - RING_F_SP_ENQ: If this flag is set, the default behavior when
234  *      using ``rte_ring_enqueue()`` or ``rte_ring_enqueue_bulk()``
235  *      is "single-producer". Otherwise, it is "multi-producers".
236  *    - RING_F_SC_DEQ: If this flag is set, the default behavior when
237  *      using ``rte_ring_dequeue()`` or ``rte_ring_dequeue_bulk()``
238  *      is "single-consumer". Otherwise, it is "multi-consumers".
239  *    - RING_F_EXACT_SZ: If this flag is set, the ``count`` parameter is to
240  *      be taken as the exact usable size of the ring, and as such does not
241  *      need to be a power of 2. The underlying ring memory should be a
242  *      power-of-2 size greater than the count value.
243  * @return
244  *   0 on success, or a negative value on error.
245  */
246 int
247 rte_event_ring_init(struct rte_event_ring *r, const char *name,
248 	unsigned int count, unsigned int flags);
249 
250 /*
251  * Create an event ring structure
252  *
253  * This function allocates memory and initializes an event ring inside that
254  * memory.
255  *
256  * @param name
257  *   name to be given to the ring
258  * @param count
259  *   the number of elements to be stored in the ring. If the flag
260  *   ``RING_F_EXACT_SZ`` is not set, this must be a power of 2, and the actual
261  *   usable space in the ring will be ``count - 1`` entries. If the flag
262  *   ``RING_F_EXACT_SZ`` is set, the this can be any value up to the ring size
263  *   limit - 1, and the usable space will be exactly that requested.
264  * @param socket_id
265  *   The *socket_id* argument is the socket identifier in case of
266  *   NUMA. The value can be *SOCKET_ID_ANY* if there is no NUMA
267  *   constraint for the reserved zone.
268  * @param flags
269  *   An OR of the following:
270  *    - RING_F_SP_ENQ: If this flag is set, the default behavior when
271  *      using ``rte_ring_enqueue()`` or ``rte_ring_enqueue_bulk()``
272  *      is "single-producer". Otherwise, it is "multi-producers".
273  *    - RING_F_SC_DEQ: If this flag is set, the default behavior when
274  *      using ``rte_ring_dequeue()`` or ``rte_ring_dequeue_bulk()``
275  *      is "single-consumer". Otherwise, it is "multi-consumers".
276  *    - RING_F_EXACT_SZ: If this flag is set, the ``count`` parameter is to
277  *      be taken as the exact usable size of the ring, and as such does not
278  *      need to be a power of 2. The underlying ring memory should be a
279  *      power-of-2 size greater than the count value.
280  * @return
281  *   On success, the pointer to the new allocated ring. NULL on error with
282  *    rte_errno set appropriately. Possible errno values include:
283  *    - E_RTE_NO_CONFIG - function could not get pointer to rte_config structure
284  *    - E_RTE_SECONDARY - function was called from a secondary process instance
285  *    - EINVAL - count provided is not a power of 2
286  *    - ENOSPC - the maximum number of memzones has already been allocated
287  *    - EEXIST - a memzone with the same name already exists
288  *    - ENOMEM - no appropriate memory area found in which to create memzone
289  */
290 struct rte_event_ring *
291 rte_event_ring_create(const char *name, unsigned int count, int socket_id,
292 		unsigned int flags);
293 
294 /**
295  * Search for an event ring based on its name
296  *
297  * @param name
298  *   The name of the ring.
299  * @return
300  *   The pointer to the ring matching the name, or NULL if not found,
301  *   with rte_errno set appropriately. Possible rte_errno values include:
302  *    - ENOENT - required entry not available to return.
303  */
304 struct rte_event_ring *
305 rte_event_ring_lookup(const char *name);
306 
307 /**
308  * De-allocate all memory used by the ring.
309  *
310  * @param r
311  *   Pointer to ring to created with rte_event_ring_create().
312  *   If r is NULL, no operation is performed.
313  */
314 void
315 rte_event_ring_free(struct rte_event_ring *r);
316 
317 /**
318  * Return the size of the event ring.
319  *
320  * @param r
321  *   A pointer to the ring structure.
322  * @return
323  *   The size of the data store used by the ring.
324  *   NOTE: this is not the same as the usable space in the ring. To query that
325  *   use ``rte_ring_get_capacity()``.
326  */
327 static inline unsigned int
328 rte_event_ring_get_size(const struct rte_event_ring *r)
329 {
330 	return rte_ring_get_size(&r->r);
331 }
332 
333 /**
334  * Return the number of elements which can be stored in the event ring.
335  *
336  * @param r
337  *   A pointer to the ring structure.
338  * @return
339  *   The usable size of the ring.
340  */
341 static inline unsigned int
342 rte_event_ring_get_capacity(const struct rte_event_ring *r)
343 {
344 	return rte_ring_get_capacity(&r->r);
345 }
346 
347 #ifdef __cplusplus
348 }
349 #endif
350 
351 #endif
352