EM-ODP 4.4.0
Event Machine on ODP
Loading...
Searching...
No Matches
em_queue_types.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2015-2026, Nokia Solutions and Networks
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * * Neither the name of the copyright holder nor the names of its
15 * contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 /**
32 * @file
33 * EM internal queue types & definitions
34 *
35 */
36
37#ifndef EM_QUEUE_TYPES_H_
38#define EM_QUEUE_TYPES_H_
39
40#include <stdbool.h>
41#include <stdint.h>
42
43#include <odp_api.h>
44
45#include <event_machine.h>
47
48#include "misc/list.h"
49#include "misc/objpool.h"
50
51#ifdef __cplusplus
52extern "C" {
53#endif
54
55/*
56 * Forward declaration — queue_elem_t holds an eo_elem_t* (pointer only).
57 * Using a forward declaration instead of #include "em_eo_types.h" keeps
58 * the *_types.h layer free of inter-includes, preventing circular
59 * dependencies if a reverse pointer is ever added.
60 */
61struct eo_elem_t;
62typedef struct eo_elem_t eo_elem_t;
63
64/*
65 * EM internal queue ids - local part of the queue only, i.e missing the
66 * device-id.
67 * Note that the EM queue handle range is determined by 'EM_QUEUE_RANGE_OFFSET'
68 */
69#define MAX_INTERNAL_QUEUES (EM_MAX_CORES + EM_MAX_EXTTHRS + 1/*shared internal queue*/)
70
71COMPILE_TIME_ASSERT(MAX_INTERNAL_QUEUES - 1 >= EM_MAX_CORES, TOO_FEW_INTERNAL_QUEUES_ERROR);
72
73/* Priority for the EM-internal queues */
74#define INTERNAL_QUEUE_PRIORITY (EM_QUEUE_PRIO_HIGHEST)
75
76#define QUEUE_ELEM_VALID ((uint16_t)0xCAFE)
77
78#define INVALID_QUEUE_ID ((uint16_t)0xFFFF)
79
80/* Verify that the byte order is defined for 'internal_queue_t' */
81#if \
82(__BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__) && \
83(__BYTE_ORDER__ != __ORDER_BIG_ENDIAN__)
84#error __BYTE_ORDER__ not defined!
85#endif
86
87/**
88 * Internal representation of the EM queue handle
89 * The EM queue handle contains a 16-bit queue-id and a 16-bit device-id.
90 */
91typedef union {
92 em_queue_t queue;
93 struct {
94#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
95 uint16_t queue_id;
96 uint16_t device_id;
97#ifdef EM_64_BIT
98 uint32_t unused;
99#endif
100#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
101#ifdef EM_64_BIT
102 uint32_t unused;
103#endif
104 uint16_t device_id;
105 uint16_t queue_id;
106#endif
107 };
109
110/* Verify size of struct, i.e. accept no padding */
111COMPILE_TIME_ASSERT(sizeof(internal_queue_t) == sizeof(em_queue_t),
112 INTERNAL_QUEUE_T_SIZE_ERROR);
113
114/**
115 * Queue state
116 */
117typedef enum queue_state {
118 /** Invalid queue state, queue not created/allocated */
120
121 /*
122 * Scheduled queue (ATOMIC, PARALLEL, ORDERED) states:
123 * (keep state values consecutive: ...n-1,n,n+1...)
124 */
125 /** Queue initialization, allocated and being set up */
127 /** Queue added/bound to an EO, but EO-start not yet complete */
129 /** Queue ready, related EO started */
131
132 /*
133 * Non-scheduled queue (UNSCHED, OUTPUT) state use the UNSCHEDULED-state.
134 */
135 /* Use separate value for unscheduled queues to catch illegal usage */
136 EM_QUEUE_STATE_UNSCHEDULED = 255
138/**
139 * Queue state, packed into uint8_t.
140 *
141 * The 'enum queue_state' or queue_state_e will always fit into an uint8_t.
142 * Save space in the queue_elem_t by using this instead.
143 */
144typedef uint8_t queue_state_t;
145
146/**
147 * Atomic-group queue specific part of the queue element
148 */
149typedef struct q_elem_atomic_group_ {
150 /** The atomic group handle (if any) of this queue */
151 em_atomic_group_t atomic_group;
152 /** List node for linking queue elems belonging to an atomic group */
155
156/**
157 * Output queue specific part of the queue element
158 */
159typedef struct q_elem_output_ {
160 /** Output Queue config, incl. output_fn(..., output_fn_args) */
162 /** Copied output_fn_args content of length 'args_len' stored in event */
164 /** Output queue index used for output queue tracking, not same as queue index */
165 uint32_t idx;
166 /** Lock for output queues during an ordered-context */
167 odp_ticketlock_t lock;
169
170/**
171 * Parent queue aggregator data.
172 *
173 * Stored in the parent (scheduled or unscheduled) queue element when the
174 * queue was created with child aggregator queues (em_queue_param_t::num_aggr).
175 */
176typedef struct q_elem_aggr_parent_ {
177 /** Number of aggregator child queues */
178 uint32_t num_aggr;
179 /** Array of aggregator child queue handles (as uint32_t's) */
182
183/**
184 * Child aggregator queue data.
185 *
186 * Stored in aggregator (EM_QUEUE_TYPE_AGGR) queue elements.
187 * Aggregator queues are never added to an EO or queue group, so this
188 * data shares space (union) with q_elem_atomic_group_t and q_elem_output_t.
189 */
190typedef struct q_elem_aggr_ {
191 /** Back-reference to the parent queue handle */
192 em_queue_t parent_queue;
193
194 /** Event vector pool (from em_queue_aggr_conf_t) */
195 em_pool_t pool;
196
197 /** Maximum time to wait to fill a vector (from em_queue_aggr_conf_t) */
198 uint64_t max_tmo_ns;
199
200 /** Maximum number of events in vector (from em_queue_aggr_conf_t) */
201 uint32_t max_size;
202
203 /** Aggregation and vector event type (from em_queue_aggr_conf_t) */
206
207/**
208 * Internal EM queue flags.
209 *
210 * Contains per-queue boolean flags packed into a single byte, which describe
211 * aspects of the queue's nature and use. Intended for internal bookkeeping
212 * within EM.
213 */
214typedef union queue_elem_flags_ {
215 /** Access all flags as an 8-bit unsigned integer */
216 uint8_t all;
217 struct {
218 /** true(1):receive_multi_func(), false(0):receive_func() */
219 uint8_t use_multi_rcv : 1;
220 /** Set if queue is scheduled, i.e. atomic, parallel or ordered */
221 uint8_t scheduled : 1;
222 /** Does this queue belong to an EM Atomic Group (true/false)? */
223 uint8_t in_atomic_group : 1;
224 /** Is this an ODP pktin event queue (true/false)? */
225 uint8_t is_pktin : 1;
226 /** Does this queue have aggregator child queues (true/false)? */
227 uint8_t has_aggr : 1;
228 /** Reserved bits */
229 uint8_t rsvd : 3;
230 };
232
233/**
234 * EM queue element
235 */
236typedef struct queue_elem_t {
237 /**
238 * Check that contents is an EM queue elem.
239 *
240 * EM will verify that the ODP queue context actually points to an
241 * EM queue elem and not to something else:
242 * queue_elem_t *q_elem = odp_queue_context(odp_queue);
243 * if (!q_elem || q_elem->valid_check != QUEUE_ELEM_VALID)
244 * EM_ERROR(...);
245 * Keep first.
246 */
247 uint16_t valid_check;
248
249 /** Queue flags */
251
252 /** Queue state */
253 queue_state_t state; /* queue_state_e */
254
255 /** Queue priority */
256 uint8_t priority; /* em_queue_prio_t */
257
258 /** Atomic, parallel, ordered, unscheduled, local, output, aggregator */
259 uint8_t type; /* em_queue_type_t */
260
261 /** Max number of events passed to the EO's multi-event receive function */
262 uint16_t max_events; /* only used if flags.use_multi_rcv == true */
263
264 /** EM EO that this queue belongs to */
265 uint16_t eo; /* em_eo_t */
266
267 /** Queue handle */
268 uint32_t queue; /* em_queue_t */
269
270 /** Associated ODP queue handle */
271 odp_queue_t odp_queue;
272
273 /** User defined queue context (can be NULL) */
274 void *context;
275
276 union {
277 /** Copy of the event receive function for better performance */
279 /** Copy of the multi-event receive function for better performance */
281 };
282
283 /** Copy of the user defined eo context (or NULL) for performance */
284 void *eo_ctx;
285
286 /**
287 * Atomic group specific data.
288 * Only used if the queue belongs to an atomic group. Cannot be placed
289 * in the union below (with the other q_elem_*_t's) since a queue might
290 * both belong to an atomic group and have aggregator child queues (i.e.
291 * .agrp and .aggr_parent might be simultaneously in use).
292 */
294
295 /**
296 * Type-specific queue data (union).
297 *
298 * Only one variant is active, determined by the queue type:
299 * - aggr_parent: scheduled or unscheduled queue with child aggregator queues,
300 * only used when aggregators have been configured and set up.
301 * - aggr: EM_QUEUE_TYPE_AGGR (aggregator child queue)
302 * - output: EM_QUEUE_TYPE_OUTPUT
303 */
304 union {
305 q_elem_aggr_parent_t aggr_parent;
306 q_elem_aggr_t aggr;
307 q_elem_output_t output;
308 };
309
310 /** Associated eo element */
312
313 /** Queue group handle of this queue */
314 em_queue_group_t queue_group;
315
316 /** List node for linking queue elems belonging to an EO */
318 /** List node for linking queue elems belonging to a queue group */
320
321 /** Queue pool elem for linking free queues for queue_alloc() */
323
324 /**
325 * End of queue element data,
326 * for offsetof(queue_elem_t, end_data)
327 */
328 uint8_t end_data[0];
329
330 /*
331 * ! EMPTY SPACE !
332 */
333
334 /** Guarantee that size is a multiple of cache line size */
337
338COMPILE_TIME_ASSERT(sizeof(queue_elem_t) % ENV_CACHE_LINE_SIZE == 0,
339 QUEUE_ELEM_T__SIZE_ERROR);
340/* Catch unintentional size increase */
341COMPILE_TIME_ASSERT(sizeof(queue_elem_t) <= 3 * ENV_CACHE_LINE_SIZE,
342 QUEUE_ELEM_T__SIZE_TOO_LARGE);
343
344/**
345 * EM queue element table
346 */
347typedef struct queue_tbl_t {
348 /** ODP queue capabilities common for all queues */
349 odp_queue_capability_t odp_queue_capability;
350 /** ODP schedule capabilities related to queues */
351 odp_schedule_capability_t odp_schedule_capability;
352 /** Current number of allocated output queues */
353 odp_atomic_u32_t output_queue_count ENV_CACHE_LINE_ALIGNED;
354 /** Free output queue indexes */
356 /** Lock for output queue (de-)allocations */
357 odp_ticketlock_t output_queue_lock;
358
359 /** First static queue ID */
361 /** Last static queue ID */
363
364 /** First internal queue ID */
366 /** Last internal queue ID */
368 /** Shared internal queue ID */
370
371 /** First dynamic queue ID */
373 /** Last dynamic queue ID */
375
376 /** First aggregator queue ID */
378 /** Last aggregator queue ID */
380
381 /** Maximum number of EM queues */
383
384 /**
385 * Dynamically allocated memory starts here. The elements
386 * are in a single continuous memory block. The amount of memory
387 * reserved depends on the max number of EM queues given in
388 * EM config file.
389 */
390 /** Queue element table, format: queue_elem[em_queue_max_num()] */
392 /** Queue name table, format: name[em_queue_max_num()][EM_QUEUE_NAME_LEN] */
395
396/**
397 * Pool of free queues
398 */
399typedef struct queue_pool_t {
400 objpool_t objpool;
402
403/**
404 * Local queues, i.e. core-local storage for events to local queues
405 */
406typedef struct local_queues_t {
407 int empty;
408 struct {
409 int empty_prio;
410 odp_stash_t stash;
411 } prio[EM_QUEUE_PRIO_NUM];
413
414/**
415 * Track output-queues used during a dispatch round (burst)
416 */
417typedef struct output_queue_track_t {
418 unsigned int idx_cnt;
419 uint16_t idx[EM_MAX_OUTPUT_QUEUES];
422
423#ifdef __cplusplus
424}
425#endif
426
427#endif /* EM_QUEUE_TYPES_H_ */
struct q_elem_atomic_group_ q_elem_atomic_group_t
struct q_elem_aggr_ q_elem_aggr_t
uint8_t queue_state_t
struct q_elem_output_ q_elem_output_t
struct queue_elem_t ENV_CACHE_LINE_ALIGNED
queue_state
@ EM_QUEUE_STATE_READY
@ EM_QUEUE_STATE_INIT
@ EM_QUEUE_STATE_INVALID
@ EM_QUEUE_STATE_BIND
union queue_elem_flags_ queue_elem_flags_t
enum queue_state queue_state_e
struct q_elem_aggr_parent_ q_elem_aggr_parent_t
#define EM_QUEUE_MAX_AGGR
#define EM_QUEUE_PRIO_NUM
#define EM_QUEUE_NAME_LEN
#define EM_MAX_OUTPUT_QUEUES
#define EM_MAX_CORES
uint32_t em_event_type_t
void(* em_receive_func_t)(void *eo_ctx, em_event_t event, em_event_type_t type, em_queue_t queue, void *q_ctx)
void(* em_receive_multi_func_t)(void *eo_ctx, em_event_t events[], int num, em_queue_t queue, void *q_ctx)
uint64_t max_tmo_ns
uint32_t max_size
em_queue_t parent_queue
em_event_type_t event_type
uint32_t aggr_queues[EM_QUEUE_MAX_AGGR]
em_atomic_group_t atomic_group
odp_ticketlock_t lock
em_output_queue_conf_t output_conf
em_event_t output_fn_args_event
odp_queue_t odp_queue
uint8_t end_data[0]
uint16_t max_events
queue_state_t state
uint16_t valid_check
q_elem_atomic_group_t agrp
void *end[0] ENV_CACHE_LINE_ALIGNED
list_node_t eo_queue_node
objpool_elem_t queue_pool_elem
em_receive_multi_func_t receive_multi_func
em_queue_group_t queue_group
queue_elem_flags_t flags
em_receive_func_t receive_func
eo_elem_t * eo_elem
list_node_t qgrp_node
uint16_t last_internal_queue_id
uint16_t shared_internal_queue_id
odp_schedule_capability_t odp_schedule_capability
odp_atomic_u32_t output_queue_count ENV_CACHE_LINE_ALIGNED
odp_queue_capability_t odp_queue_capability
uint16_t first_aggr_queue_id
uint16_t first_internal_queue_id
char(* name)[EM_QUEUE_NAME_LEN]
uint16_t max_queue_num
bool output_queue_idx_free[EM_MAX_OUTPUT_QUEUES]
uint16_t last_static_queue_id
uint16_t first_dyn_queue_id
queue_elem_t *queue_elem ENV_CACHE_LINE_ALIGNED
odp_ticketlock_t output_queue_lock
uint16_t last_aggr_queue_id
uint16_t first_static_queue_id
uint16_t last_dyn_queue_id