EM-ODP 4.4.0
Event Machine on ODP
Loading...
Searching...
No Matches
event_machine_queue.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#ifndef EVENT_MACHINE_QUEUE_H_
32#define EVENT_MACHINE_QUEUE_H_
33
34#pragma GCC visibility push(default)
35
36/**
37 * @file
38 * @defgroup em_queue Queues
39 * Operations on queues
40 * @{
41 *
42 * Queues are the communication mechanism used by EM. Each queue is associated
43 * with one Execution Object (EO) (or HW functionality), but each EO can have
44 * multiple queues.
45 *
46 * A queue can have one of seven (7) different scheduling modes / queue types:
47 *
48 * @anchor atomic_queue
49 * -# EM_QUEUE_TYPE_ATOMIC
50 * - The atomic queue type limits event scheduling to one event at a time from
51 * the queue. The next event from the same queue can only be scheduled after
52 * the EO returns from processing the earlier event or calls
53 * em_atomic_processing_end() to signal end of atomic processing.
54 * This type is useful to avoid multicore race conditions as only one core
55 * at a time can be working on an event from an atomic queue.
56 * Additionally, the ingress-egress event order is maintained.
57 *
58 * @anchor parallel_queue
59 * -# EM_QUEUE_TYPE_PARALLEL
60 * - Parallel queues have no restriction for scheduling, which means that any
61 * amount of events (up to the number of cores in the queue group of the
62 * queue) can be processed simultaneously. This provides the best scaling,
63 * but race conditions need to be avoided and handled by the application.
64 *
65 * @anchor ordered_queue
66 * -# EM_QUEUE_TYPE_ORDERED
67 * - Ordered queues are scheduled like parallel queues — multiple events can
68 * be processed concurrently — but the system preserves egress ordering.
69 * This enables high single-flow throughput without requiring the
70 * application to synchronize for ordering between threads.
71 *
72 * Ordering context: When the scheduler dequeues an event (or burst) from
73 * an ordered queue, the receiving thread is associated with an ordering
74 * context that represents the event's sequence position in the queue.
75 * Contexts originating from the same ordered queue keep the mutual order
76 * of their corresponding events. The context is valid during the EO
77 * receive function and ends when the function returns, or earlier if
78 * em_ordered_processing_end() is called.
79 *
80 * Sending under an ordering context: Any event sent during the context
81 * inherits its sequence position, including events not received from the
82 * ordered queue (e.g. newly allocated or previously stored). The first
83 * event sent occupies the position of the received event; subsequent
84 * sends occupy the consecutive positions after it. The received event
85 * itself does not need to be forwarded; if no event is sent at all, the
86 * position is implicitly skipped.
87 *
88 * Destination queues: Events may be sent to any number of destination
89 * queues of any type. Ordering is enforced per destination queue (not
90 * between different destinations) and follows two rules:
91 * - Events sent by the same thread arrive in send-call order.
92 * - Events sent from different ordering contexts arrive in the order
93 * of those contexts.
94 * A chain of ordered (or atomic) queues preserves ordering end-to-end.
95 *
96 * Note that the guarantee covers enqueue, not processing: a non-atomic
97 * destination queue served by a multi-core EO may still process events
98 * out of order.
99 *
100 * Compared to atomic queues, which also maintain order, ordered queues
101 * achieve higher throughput by allowing multiple cores to process events
102 * in parallel.
103 *
104 * @anchor unscheduled_queue
105 * -# EM_QUEUE_TYPE_UNSCHEDULED
106 * - Unscheduled queues are not connected to the scheduler but instead the
107 * application needs to dequeue events directly using em_queue_dequeue().
108 * The API function em_send() is used to enqueue events into an unscheduled
109 * queue. All queue types look the same to the sender with the exception
110 * that em_send_group() is not supported for unscheduled queues.
111 * Unscheduled queues cannot be added to an EO.
112 *
113 * @anchor aggregator_queue
114 * -# EM_QUEUE_TYPE_AGGR
115 * - An aggregator queue is a child queue of a scheduled or unscheduled
116 * parent queue. Aggregator queues cannot be created/deleted directly
117 * but are created/deleted as part of the parent queue creation/deletion
118 * (see em_queue_param_t::num_aggr and em_queue_param_t::aggr_conf).
119 * Events sent to an aggregator queue may be bundled into vector events
120 * before being enqueued to the parent queue for delivery.
121 * Events can also be sent directly to the parent queue bypassing the
122 * aggregation.
123 * For unscheduled queues: the application must not dequeue from the
124 * aggregator queues directly, instead they should dequeue from the
125 * parent queue.
126 * For scheduled queues: the queue handle given to the EO receive
127 * function always corresponds to the parent scheduled queue, the
128 * aggregator queue handle is never passed.
129 * The application can send events to both the parent queue and the
130 * aggregator queues, depending on desired (vectorized/non-vectorized)
131 * behaviour.
132 * @note A vector event (major type EM_EVENT_TYPE_VECTOR) must never be
133 * sent to an aggregator queue - no vectors within vectors. A vector
134 * event may still be sent directly to the parent queue of the
135 * aggregators.
136 * @note Sending two events to separate aggregator queues of the same
137 * parent queue will not retain event order even if the parent
138 * queue would guarantee ordering.
139 *
140 * @anchor local_queue
141 * -# EM_QUEUE_TYPE_LOCAL
142 * - Local queues are special virtual queues bypassing the scheduler for
143 * fast core-local pipelining without load balancing or atomic processing.
144 * A local queue is connected (added) to an EO in the same way scheduled
145 * queues are. Events sent to a local queue are added to a per core (local)
146 * storage maintained by the EM dispatcher. This core local event storage is
147 * emptied by the dispatcher after the sending EO returns from the receive
148 * function. The local events are now immediately dispatched on the current
149 * core, i.e. handed to the receive function of the EO that owns the
150 * targeted local queue. Only when all local events have been handled is the
151 * scheduler allowed to schedule new events for the core.
152 * Local queues do not have an explicit ordered or atomic processing
153 * context, instead they inherit the context of the EO under which the event
154 * was sent (i.e. ordering could still be maintained with careful design).
155 * The sending EO's processing context is only released after the local
156 * queue is empty, unless the application explicitly ends the context
157 * earlier, thus effectively making local processing similar to handling
158 * the same function within the sending EO's receive.
159 * A local queue is not associated with a queue group and exists on all
160 * cores of the EM instance - the application must be able to handle
161 * events on all cores (unless sending to the local queue is controlled).
162 *
163 * The local queue concept is a performance optimization and a way to
164 * logically split processing into separate EO's but due to the side
165 * effects (may delay context release of the sending EO) and limitations
166 * should not be used without a valid reason. Local queues are mainly
167 * suitable for stateless processing that does not need EM scheduling.
168 *
169 * @anchor output_queue
170 * -# EM_QUEUE_TYPE_OUTPUT
171 * - An output queue is a system specific implementation of a SW-HW interface.
172 * It provides a queue interface for sending events out of EM to a HW
173 * device. It could e.g. be used for packet output or towards HW
174 * accelerators. The application uses em_send() to transmit an event for
175 * output. Typically the needed information to bind a queue to an interface
176 * is provided via the optional conf-argument given during queue creation
177 * (the content of 'conf' is system specific).
178 *
179 * Currently EM does not define the exact queue behavior except that queues
180 * work like FIFOs. This means, e.g. that the maximum length of a queue is
181 * system specific (the conf parameter of queue create can be used to provide
182 * options)
183 *
184 * Special queues towards asynchronous HW functions, e.g. a crypto accelerator,
185 * should look like any regular queue from the sender's point of view, i.e.
186 * em_send() and related functions work.
187 */
188
191
192#ifdef __cplusplus
193extern "C" {
194#endif
195
196/**
197 * @typedef em_queue_type_t
198 * Queue type.
199 *
200 * Affects the scheduling principle
201 *
202 * @see em_queue_type_e, em_queue_create()
203 */
204typedef uint32_t em_queue_type_t;
205/** em_queue_type_t printf format */
206#define PRI_QTYPE PRIu32
207
208/**
209 * Queue types used by em_queue_type_t
210 */
211typedef enum em_queue_type_e {
212 /** Undefined */
214
215 /**
216 * Atomic queue.
217 * The application receives events one by one, non-concurrently to
218 * guarantee exclusive processing and ordering
219 */
221
222 /**
223 * Parallel queue.
224 * The application may receive events fully concurrently, egress event
225 * ordering (when processed in parallel) not guaranteed
226 */
228
229 /**
230 * Ordered parallel queue.
231 * The application may receive events concurrently, but the system takes
232 * care of egress order (between two queues)
233 */
235 /** backwards compatible alias */
237
238 /**
239 * A queue which is not connected to scheduling. The application needs
240 * to explicitly dequeue events
241 */
243
244 /**
245 * Aggregator queue.
246 * An aggregator queue is a child queue of a scheduled or unscheduled
247 * parent queue.
248 * Events sent to an aggregator queue are (possibly) bundled into vector
249 * events before being enqueued to the parent queue for delivery.
250 * @see @ref aggregator_queue "Aggregator queues"
251 */
253
254 /**
255 * A queue type for local virtual queue not connected to scheduling.
256 */
258 /**
259 * A system specific queue type to abstract output from EM,
260 * e.g. packet output or output towards a HW accelerator.
261 * The application uses em_send() and variants to send an event 'out'.
262 */
265
266/**
267 * @typedef em_queue_prio_t
268 * Queue priority
269 *
270 * Queue priority defines implementation specific QoS class for event
271 * scheduling. Priority is an integer in range 0 (lowest) to num priorities - 1.
272 * Note, that the exact scheduling rules are not defined by EM and all available
273 * priorities may not be relative to the adjacent one (e.g. using dynamic
274 * priority, rate limiting or other more complex scheduling discipline).
275 * There are 5 generic predefined values (em_queue_prio_e) mapped to available
276 * runtime priorities for portability.
277 *
278 * @see em_queue_create(), em_queue_num_prio(), em_queue_prio_e
279 */
280typedef uint32_t em_queue_prio_t;
281#define PRI_QPRIO PRIu32
282
283/**
284 * Portable queue priorities.
285 *
286 * These are generic portable values to use for priority with em_queue_prio_t.
287 *
288 * Alternatively application may choose to use numeric values in the valid
289 * range (from 0 to em_queue_num_prio() - 1).
290 *
291 * @see em_queue_prio_t, em_queue_num_prio()
292 */
293typedef enum em_queue_prio_e {
294 EM_QUEUE_PRIO_LOWEST = 0, /**< Lowest */
295 EM_QUEUE_PRIO_LOW = 2, /**< Low */
296 EM_QUEUE_PRIO_NORMAL = 4, /**< Normal */
297 EM_QUEUE_PRIO_HIGH = 6, /**< High */
298 EM_QUEUE_PRIO_HIGHEST = 7 /**< Highest */
300
301#define EM_QUEUE_PRIO_UNDEF 0xFF /**< Undefined */
302
303/**
304 * Queue flags
305 *
306 * An unsigned integer with defined queue flags that can be combined by
307 * bitwise 'OR' only. EM_QUEUE_FLAG_DEFAULT can be used in most cases.
308 * Unused bits must be set to zero. The actual values are system specific, but
309 * the implementation need to define at least: EM_QUEUE_FLAG_DEFAULT,
310 * EM_QUEUE_FLAG_BLOCKING, EM_QUEUE_FLAG_NONBLOCKING_LF and
311 * EM_QUEUE_FLAG_NONBLOCKING_WF even if those would not be supported.
312 */
313typedef uint32_t em_queue_flag_t;
314
315/**
316 * @def EM_QUEUE_FLAG_MASK (em_queue_flag_t mask)
317 * The low 16 bits are reserved for EM, the upper bits are free
318 * for system-specific use.
319 */
320#define EM_QUEUE_FLAG_MASK 0x0000FFFF
321
322/**
323 * @def EM_QUEUE_FLAG_DEFAULT
324 *
325 * em_queue_flag_t default value. The EM queues will use implementation specific
326 * default values.
327 * The default values for this implementation values imply:
328 * EM_QUEUE_FLAG_DEFAULT = MTSAFE and BLOCKING queue implementation
329 */
330#define EM_QUEUE_FLAG_DEFAULT 0
331
332/**
333 * @def EM_QUEUE_FLAG_BLOCKING
334 *
335 * em_queue_flag_t value. Only combine flags with bitwise OR.
336 *
337 * Blocking queue implementation. A suspending thread may block all other
338 * threads, i.e. no block freedom guarantees.
339 * Implied by EM_QUEUE_FLAG_DEFAULT for the implementation on this system.
340 */
341#define EM_QUEUE_FLAG_BLOCKING 0 /* blocking, fastest (default) */
342
343/**
344 * @def EM_QUEUE_FLAG_NONBLOCKING_LF
345 *
346 * em_queue_flag_t value. Only combine flags with bitwise OR.
347 *
348 * Require a non-blocking and lock-free queue implementation.
349 * Other threads can make progress while a thread is suspended.
350 * Starvation freedom is not guaranteed.
351 * Queue creation will fail if set and not supported.
352 */
353#define EM_QUEUE_FLAG_NONBLOCKING_LF 1 /* non-blocking, lock-free */
354
355/**
356 * @def EM_QUEUE_FLAG_NONBLOCKING_WF
357 *
358 * em_queue_flag_t value. Only combine flags with bitwise OR.
359 *
360 * Require a non-blocking and wait-free queue implementation.
361 * Other threads can make progress while a thread is suspended.
362 * Starvation freedom is guaranteed.
363 * Queue creation will fail if set and not supported.
364 */
365#define EM_QUEUE_FLAG_NONBLOCKING_WF 2 /* non-blocking, wait-free */
366
367/**
368 * @def EM_QUEUE_FLAG_ENQ_NOT_MTSAFE
369 *
370 * em_queue_flag_t value. Only combine flags with bitwise OR.
371 *
372 * Default multithread safe enqueue implementation not needed, the application
373 * guarantees there is no concurrent accesses in enqueue, i.e. em_send().
374 * This can only be used with unscheduled queues and can potentially improve
375 * performance. The implementation may choose to ignore this flag.
376 * Use with care.
377 */
378#define EM_QUEUE_FLAG_ENQ_NOT_MTSAFE 4
379
380/**
381 * @def EM_QUEUE_FLAG_DEQ_NOT_MTSAFE
382 *
383 * em_queue_flag_t value. Only combine flags with bitwise OR.
384 *
385 * Default multithread safe dequeue implementation not needed, the application
386 * guarantees there is no concurrent accesses in dequeue, i.e.
387 * em_queue_dequeue(). This can only be used with unscheduled queues and can
388 * potentially improve performance. The implementation may choose to ignore this
389 * flag. Use with care.
390 */
391#define EM_QUEUE_FLAG_DEQ_NOT_MTSAFE 8
392
393/**
394 * Queue configuration data for queue-create APIs. The use of this conf is
395 * optional, but provides a standard way to pass extra parameters or specify
396 * extra requirements.
397 */
398typedef struct {
399 /**
400 * Extra flags. See em_queue_flag_t for choices.
401 * EM_QUEUE_FLAG_DEFAULT is defined by all systems and indicates a
402 * default multithread-safe queue without any special guarantees.
403 */
405 /**
406 * Request for a minimum amount of events the queue can hold or use
407 * 0 for EM default value. Queue creation will fail, if the system
408 * cannot support the requested amount.
409 */
410 unsigned int min_events;
411 /**
412 * Size of the data passed via 'conf'. 'conf' is ignored,
413 * if 'conf_len' is 0.
414 */
415 size_t conf_len;
416 /**
417 * Extra queue configuration data. This can also work
418 * as a placeholder for directly attached extra data.
419 */
420 void *conf;
422
423/**
424 * Output function, user provided callback for queues of type
425 * EM_QUEUE_TYPE_OUTPUT.
426 *
427 * This function will be called by em_send*() when sending to a queue of type
428 * EM_QUEUE_TYPE_OUTPUT and EM will take care of correct function calling order
429 * based on the scheduling context type.
430 * The function can use em_sched_context_type_current() if it needs information
431 * about e.g. ordering requirements set by the parent scheduled queue.
432 *
433 * @param events List of events to be sent out (ptr to array of events)
434 * @param num Number of events (positive integer)
435 * @param output_queue Output queue that the events were sent to (em_send*())
436 * @param output_fn_args Extra arguments to indicate e.g. ordering requirement
437 * of the source context.
438 *
439 * @return number of events successfully sent (equal to num if all successful)
440 */
441typedef int (*em_output_func_t)(const em_event_t events[],
442 const unsigned int num,
443 const em_queue_t output_queue,
444 void *output_fn_args);
445
446/**
447 * EM output queue configuration.
448 * Given to em_queue_create(type=EM_QUEUE_TYPE_OUTPUT) as em_queue_conf_t::conf
449 * or part of em_queue_param_t::output_conf when using em_queue_create_param().
450 */
451typedef struct {
452 /**
453 * User provided function for sending events out. This function will be
454 * called by em_send*() when sending to a queue of type
455 * EM_QUEUE_TYPE_OUTPUT
456 */
458 /**
459 * Extra output-function argument that will be passed.
460 */
462 /**
463 * Size of the argument-data passed via 'output_fn_args'.
464 * 'output_fn_args' is ignored, if 'args_len' is 0.
465 */
466 size_t args_len;
468
469/**
470 * Create a new queue with a dynamic queue handle (i.e. handle given by EM)
471 *
472 * The given name string is copied into an EM internal data structure. The
473 * maximum string length is EM_QUEUE_NAME_LEN.
474 *
475 * Create scheduled atomic, parallel or ordered queues by using the types
476 * EM_QUEUE_TYPE_ATOMIC, EM_QUEUE_TYPE_PARALLEL or EM_QUEUE_TYPE_ORDERED.
477 *
478 * To create an unscheduled queue, use the type EM_QUEUE_TYPE_UNSCHEDULED.
479 * The prio and queue group are not relevant, but need to be set to
480 * EM_QUEUE_PRIO_UNDEF and EM_QUEUE_GROUP_UNDEF. Unscheduled queues can't be
481 * associated with an EO (em_eo_add_queue() fails).
482 *
483 * To create a local queue, use type EM_QUEUE_TYPE_LOCAL. The queue group is not
484 * relevant and must be set to EM_QUEUE_GROUP_UNDEF. The virtual local queue
485 * is created for all cores in this EM instance. Note also that the
486 * implementation may not implement priorities for local queues.
487 *
488 * To create an output queue, use the type EM_QUEUE_TYPE_OUTPUT.
489 * Pass the needed information to bind a queue with an interface via the
490 * conf-argument (content is system and output-type specific).
491 * The queue group is not relevant and must be set to EM_QUEUE_GROUP_UNDEF.
492 * Note also that the implementation may not implement priorities for output
493 * queues.
494 *
495 * The 'conf' argument is optional and can be used to pass extra attributes
496 * (e.g. require non-blocking behaviour, if supported) to the system specific
497 * implementation.
498 *
499 * @param name Queue name (optional, NULL ok)
500 * @param type Queue type
501 * @param prio Queue priority class
502 * @param group Queue group for this queue
503 * @param conf Optional configuration data, NULL for defaults
504 *
505 * @return New queue handle or EM_QUEUE_UNDEF on an error.
506 *
507 * @see em_queue_group_create(), em_queue_delete(), em_queue_conf_t
508 */
509em_queue_t
510em_queue_create(const char *name, em_queue_type_t type, em_queue_prio_t prio,
511 em_queue_group_t group, const em_queue_conf_t *conf);
512
513/**
514 * Create a new queue with a static queue handle (i.e. given by the user).
515 *
516 * Note that the number of static queues is provided by the user through
517 * 'queue.num_static' in em-odp.conf at runtime. A valid static queue handle
518 * can be derived as follows:
519 * @code
520 * em_status_t status;
521 * em_queue_t static_queue = em_queue_static_handle(x);
522 * status = em_queue_create_static(NULL, EM_QUEUE_TYPE_ATOMIC,
523 * EM_QUEUE_PRIO_NORMAL,
524 * EM_QUEUE_GROUP_DEFAULT,
525 * static_queue, conf);
526 * @endcode
527 *
528 * The 'x' in above pseudocode must be in range 0 to 'queue.num_static' - 1.
529 *
530 * Otherwise like em_queue_create().
531 *
532 * @param name Queue name (optional, NULL ok)
533 * @param type Queue scheduling type
534 * @param prio Queue priority
535 * @param group Queue group for this queue
536 * @param queue Requested queue handle from the static range
537 * @param conf Optional configuration data, NULL for defaults
538 *
539 * @return EM_OK if successful.
540 *
541 * @see em_queue_create(), em_queue_static_handle()
542 */
544em_queue_create_static(const char *name, em_queue_type_t type,
545 em_queue_prio_t prio, em_queue_group_t group,
546 em_queue_t queue, const em_queue_conf_t *conf);
547
548/**
549 * Aggregator queue configuration parameters.
550 *
551 * Aggregator queues try to bundle multiple events into vector events
552 * before enqueuing the events or vector events to the parent scheduled
553 * or unscheduled queue.
554 *
555 * Always initialize with em_queue_aggr_conf_init() before setting fields
556 * to ensure forward compatibility with potentially added new options.
557 *
558 * @see em_queue_aggr_conf_init()
559 */
560typedef struct {
561 /**
562 * Event vector pool
563 *
564 * Pool from which to allocate event vectors when aggregating events.
565 * The pool must have been created with the EM_EVENT_TYPE_VECTOR type.
566 *
567 * EM pins the aggregator to the first subpool whose
568 * 'size' >= em_queue_aggr_conf_t::max_size at queue creation time.
569 * All vector events for the aggregator come from that one subpool.
570 * Different aggregators can target different subpools by using
571 * different 'max_size' values.
572 *
573 * Set to EM_POOL_UNDEF by em_queue_aggr_conf_init().
574 */
575 em_pool_t pool;
576
577 /**
578 * Maximum time to wait for events to fill a vector
579 *
580 * Maximum time in nanoseconds for event aggregation to form an
581 * event vector.
582 * A value of zero (0) means there is no timeout and events may await
583 * aggregation indefinitely.
584 * Set to 0 by em_queue_aggr_conf_init().
585 */
586 uint64_t max_tmo_ns;
587
588 /**
589 * Maximum number of events in vector
590 *
591 * Event aggregation forms an event vector event after '.max_size'
592 * events have been collected or '.max_tmo_ns' has passed.
593 *
594 * '.max_size' also determines which subpool of the vector pool
595 * ('.pool') is used: EM selects the first subpool whose
596 * em_pool_cfg_t::subpool[x].size >= '.max_size' at queue creation
597 * time, and all vector events for this aggregator are allocated from
598 * that subpool (see em_pool_cfg_t::subpool[].size for details).
599 *
600 * Must be non-zero; the default value of 0 set by
601 * em_queue_aggr_conf_init() is rejected at queue creation time.
602 */
603 uint32_t max_size;
604
605 /**
606 * Event type eligible for aggregation into vector events
607 *
608 * Only events of this type are collected into the vector.
609 * Use EM_EVENT_TYPE_ANY to allow all event types except event vectors.
610 *
611 * Regardless of 'event_type', a vector event (major type
612 * EM_EVENT_TYPE_VECTOR) must never be sent to an aggregator queue
613 * (no vectors within vectors), see @ref aggregator_queue.
614 *
615 * Set to EM_EVENT_TYPE_UNDEF by em_queue_aggr_conf_init(); must be set
616 * to a valid type before calling em_queue_create_param().
617 */
619
620 /**
621 * Internal check - don't touch!
622 *
623 * EM will verify that em_queue_aggr_conf_init(conf)
624 * has been called before use.
625 */
628
629/**
630 * Initialize configuration parameters for aggregator queue(s).
631 *
632 * Initialize an array of em_queue_aggr_conf_t:s to default values.
633 * Always call this before setting fields to ensure compatibility with
634 * potentially added new options.
635 * EM will enforce this and report an error if not done.
636 *
637 * @param num_aggr Number of elements in aggr_conf[] (1..EM_QUEUE_MAX_AGGR)
638 * @param aggr_conf Address of the em_queue_aggr_conf_t array to initialize
639 *
640 * @see em_queue_aggr_conf_t, em_queue_create_param()
641 */
642void em_queue_aggr_conf_init(uint32_t num_aggr,
643 em_queue_aggr_conf_t aggr_conf[/*num_aggr*/]);
644
645/**
646 * EM queue creation parameters.
647 *
648 * Used with em_queue_create_param() and is able to replace several
649 * queue-create APIs including:
650 * em_queue_create(), em_queue_create_static(), em_queue_create_ag() and
651 * em_queue_create_static_ag().
652 *
653 * @note em_queue_param_init() must be called to initialize the parameters to
654 * default values before filling in the desired values and calling
655 * em_queue_create_param() to ensure backwards compatibility with
656 * potentially added new options. EM will enforce this and report an error
657 * if not done.
658 *
659 * Create scheduled atomic, parallel or ordered queues by using the '.type'
660 * values EM_QUEUE_TYPE_ATOMIC, EM_QUEUE_TYPE_PARALLEL or EM_QUEUE_TYPE_ORDERED.
661 *
662 * To create an unscheduled queue, use the '.type' EM_QUEUE_TYPE_UNSCHEDULED.
663 * The '.prio' and '.queue_group' are not relevant, but need to be set to
664 * EM_QUEUE_PRIO_UNDEF and EM_QUEUE_GROUP_UNDEF. Unscheduled queues can't be
665 * associated with an EO (em_eo_add_queue() fails).
666 *
667 * To create a local queue, use '.type' EM_QUEUE_TYPE_LOCAL. The '.queue_group'
668 * is not relevant and must be set to EM_QUEUE_GROUP_UNDEF. The virtual local
669 * queue is created for all cores in this EM instance. Note also that the
670 * implementation may not implement (all) priorities for local queues.
671 *
672 * To create an output queue (i.e. output from EM), use the '.type'
673 * EM_QUEUE_TYPE_OUTPUT.
674 * Pass the needed information via the '.output_conf' field.
675 * The '.queue_group' is not relevant and must be set to EM_QUEUE_GROUP_UNDEF.
676 * Note also that the implementation may not implement priorities for output
677 * queues.
678 *
679 * @code
680 * em_queue_param_t param;
681 * em_queue_aggr_conf_t aggr_conf[num_aggr]; (optional)
682 *
683 * em_queue_param_init(&param);
684 * em_queue_aggr_conf_init(num_aggr, aggr_conf);
685 *
686 * param.type = EM_QUEUE_TYPE_ATOMIC;
687 * ...
688 *
689 * for (i = 0; i < num_aggr; i++) {
690 * aggr_conf[i].pool = my_vector_pool;
691 * ...
692 * }
693 * param.num_aggr = num_aggr;
694 * param.aggr_conf = aggr_conf;
695 * ...
696 * queue = em_queue_create_param("my-queue", &param);
697 * @endcode
698 */
699typedef struct {
700 /**
701 * Requested queue handle for static queues,
702 * use EM_QUEUE_UNDEF for dynamic queues.
703 *
704 * Dynamic queue: use EM_QUEUE_UNDEF and EM will allocate a queue handle
705 * for the new queue (similar to em_queue_create/_ag()).
706 * Static queue: use a valid free static queue handle (derived e.g.
707 * with em_queue_static_handle()) for the new queue
708 * (similar to em_queue_create_static/_ag()).
709 * Set to EM_QUEUE_UNDEF by em_queue_param_init(), which means
710 * a dynamic queue will be created unless changed by the user.
711 */
712 em_queue_t queue;
713
714 /**
715 * Queue type, mandatory.
716 * Set to EM_QUEUE_TYPE_UNDEF by em_queue_param_init(), but the user
717 * needs to change it to a valid type.
718 */
720
721 /**
722 * Queue priority, mandatory for certain queue types.
723 * Set to EM_QUEUE_PRIO_UNDEF by em_queue_param_init(), but the user
724 * needs to change it to a valid priority, or EM_QUEUE_PRIO_UNDEF
725 * if not relevant for the queue type.
726 */
728
729 /**
730 * Queue group for this queue, mandatory for certain queue types.
731 * Set to EM_QUEUE_GROUP_UNDEF by em_queue_param_init(), but the user
732 * needs to change it to a valid queue group, or EM_QUEUE_GROUP_UNDEF
733 * if not relevant for the queue type.
734 */
735 em_queue_group_t queue_group;
736
737 /**
738 * Atomic group for the queue, only use when wanting the new queue to be
739 * part of an existing atomic group (see the EM atomic group APIs).
740 * Note: can only be used when .type = EM_QUEUE_TYPE_ATOMIC.
741 * Set to EM_ATOMIC_GROUP_UNDEF by em_queue_param_init(), but the user
742 * needs to change it to a valid atomic group, or EM_ATOMIC_GROUP_UNDEF
743 * if not relevant for the queue.
744 */
745 em_atomic_group_t atomic_group;
746
747 /**
748 * Extra flags. See em_queue_flag_t for choices.
749 * EM_QUEUE_FLAG_DEFAULT indicates a default multithread-safe queue
750 * without any special guarantees.
751 * Set to EM_QUEUE_FLAG_DEFAULT by em_queue_param_init().
752 */
754
755 /**
756 * Request for a minimum amount of events the queue can hold or use
757 * 0 for the EM default value. Queue creation will fail, if the system
758 * cannot support the requested amount.
759 * Set to 0 by em_queue_param_init().
760 */
761 unsigned int min_events;
762
763 /**
764 * EM output queue configuration.
765 * Only evaluated when .type = EM_QUEUE_TYPE_OUTPUT.
766 */
768
769 /**
770 * Number of aggregator queues to create for this queue,
771 * use zero (0) for no aggregation.
772 *
773 * Aggregator queues try to aggregate multiple events into vector events
774 * before enqueuing to the 'parent' queue.
775 *
776 * Two events enqueued through different aggregators may appear in any
777 * order when dequeued.
778 *
779 * When >= 1, configuration must be provided for each aggregator
780 * through the 'aggr_conf' array.
781 * Must be smaller or equal to EM_QUEUE_MAX_AGGR.
782 *
783 * The default value is zero.
784 */
785 uint32_t num_aggr;
786
787 /** Aggregator queue configuration parameters
788 *
789 * When 'num_aggr' is non-zero, 'aggr_conf' must point to an array
790 * of size 'num_aggr'.
791 *
792 * The 'aggr_conf' array, if given, must be initialized with
793 * em_queue_aggr_conf_init(num_aggr, aggr_conf) before setting fields
794 * to ensure compatibility with potentially added new options.
795 *
796 * The default value is null.
797 */
799
800 /**
801 * Internal check - don't touch!
802 *
803 * EM will verify that em_queue_param_init(param)
804 * has been called before use.
805 */
808
809/**
810 * Initialize parameters for EM queue creation.
811 *
812 * Initialize em_queue_param_t to default values for all fields.
813 * After initialization, the user further needs to set the mandatory fields of
814 * 'em_queue_param_t' before calling em_queue_create_param().
815 * Always initialize 'param' first with em_queue_param_init(&param) to
816 * ensure backwards compatibility with potentially added new options. EM will
817 * enforce this initialization and report an error if not done.
818 *
819 * @param param Address of the em_queue_param_t to be initialized
820 *
821 * @see em_queue_create_param()
822 */
824
825/**
826 * Create a new EM queue according to the given parameters.
827 *
828 * The queue name is copied into queue internal data. The maximum length stored
829 * is EM_QUEUE_NAME_LEN. Duplicate names are allowed, but find will only match
830 * one of them.
831 *
832 * Always initialize 'param' first with em_queue_param_init(&param) to ensure
833 * backwards compatibility and default values for all fields before setting your
834 * own params and calling em_queue_create_param():
835 * @code
836 * em_queue_param_t param;
837 * em_queue_t queue;
838 *
839 * em_queue_param_init(&param); - Set default values for all fields
840 * param.queue = EM_QUEUE_UNDEF; - Request a dynamic queue
841 * param.type = EM_QUEUE_TYPE_ATOMIC;
842 * param.prio = EM_QUEUE_PRIO_NORMAL;
843 * ...
844 * queue = em_queue_create_param("my-queue", &param);
845 * if (unlikely(queue == EM_QUEUE_UNDEF))
846 * report_error();
847 * @endcode
848 *
849 * @param name Name of the queue (optional, NULL ok)
850 * @param param Queue parameters
851 *
852 * @return New queue handle if successful, otherwise EM_QUEUE_UNDEF.
853 * @retval EM_QUEUE_UNDEF on error
854 */
855em_queue_t em_queue_create_param(const char *name,
856 const em_queue_param_t *param);
857
858/**
859 * Delete a queue.
860 *
861 * Unallocates the queue handle. This is an immediate deletion and can only
862 * be done after the queue has been removed from scheduling using
863 * em_eo_remove_queue().
864 *
865 * @param queue Queue handle to delete
866 *
867 * @return EM_OK if successful.
868 *
869 * @see em_eo_remove_queue(), em_queue_create(), em_queue_create_static()
870 */
871em_status_t em_queue_delete(em_queue_t queue);
872
873/**
874 * Set queue specific (application) context.
875 *
876 * This is a single pointer associated with a queue. The application can use it
877 * to access some context data quickly (without a lookup). The context is given
878 * as an argument to the EO receive function. EM does not dereference it.
879 *
880 * @param queue Queue to which associate the context
881 * @param context Context pointer
882 *
883 * @return EM_OK if successful.
884 *
885 * @see em_receive_func_t(), em_queue_context()
886 */
887em_status_t em_queue_set_context(em_queue_t queue, const void *context);
888
889/**
890 * Get queue specific (application) context.
891 *
892 * Returns the value application has earlier set with em_queue_set_context().
893 *
894 * @param queue Queue for which the context is requested
895 *
896 * @return Queue specific context pointer or NULL on error.
897 *
898 * @see em_queue_set_context()
899 */
900void *em_queue_context(em_queue_t queue);
901
902/* Backwards compatible naming ("get") */
903#define em_queue_get_context em_queue_context
904
905/**
906 * Get the queue name.
907 *
908 * Returns the name given to a queue when it was created.
909 * A copy of the queue name string (up to 'maxlen' characters) is written to the
910 * user given buffer.
911 * The string is always null terminated even if the given buffer length is less
912 * than the name length.
913 *
914 * The function returns '0' and writes an empty string if the queue has no name.
915 *
916 * @param queue Queue handle
917 * @param[out] name Destination buffer
918 * @param maxlen Maximum length (including the terminating '0')
919 *
920 * @return Number of characters written (excludes the terminating '0').
921 *
922 * @see em_queue_create()
923 */
924size_t em_queue_name(em_queue_t queue, char *name, size_t maxlen);
925
926/* Backwards compatible naming ("get") */
927#define em_queue_get_name em_queue_name
928
929/**
930 * Find a queue by name.
931 *
932 * Finds a queue by the given name (exact match). An empty string will not match
933 * anything. The search is case sensitive. The function will return the first
934 * match only if there are duplicate names,
935 * Be aware of that the search may take a long time if there are many queues.
936 *
937 * @param name name to look for
938 *
939 * @return queue handle or EM_QUEUE_UNDEF if not found
940 *
941 * @see em_queue_create()
942 */
943em_queue_t em_queue_find(const char *name);
944
945/**
946 * Get the queue priority.
947 *
948 * @param queue Queue handle
949 *
950 * @return Priority class or EM_QUEUE_PRIO_UNDEF on an error.
951 *
952 * @see em_queue_create()
953 */
954em_queue_prio_t em_queue_priority(em_queue_t queue);
955
956/* Backwards compatible naming ("get") */
957#define em_queue_get_priority em_queue_priority
958
959/**
960 * Get the queue type.
961 *
962 * @param queue Queue handle
963 *
964 * @return Queue type or EM_QUEUE_TYPE_UNDEF on an error.
965 *
966 * @see em_queue_create()
967 */
968em_queue_type_t em_queue_type(em_queue_t queue);
969
970/* Backwards compatible naming ("get") */
971#define em_queue_get_type em_queue_type
972
973/**
974 * Construct a static queue handle from a given static offset.
975 *
976 * The first static queue handle is em_queue_static_handle(0), and the last
977 * one is em_queue_static_handle(em_queue_static_max_num() - 1).
978 * The static offset must be in range 0 .. em_queue_static_max_num() - 1,
979 * otherwise EM_QUEUE_UNDEF is returned.
980 *
981 * Use the constructed handle with em_queue_create_static() to create the
982 * corresponding queue if it has not been created already.
983 *
984 * @param static_offset offset from the first static queue ID. Must be in
985 * range 0 to em_queue_static_max_num() - 1
986 *
987 * @note The device id is not affected by this function and remains the same as
988 * in the first static queue handle. More specifically, the same device id
989 * as this EM instance is used.
990 * @note This function only constructs a static queue handle based on the
991 * provided offset. It does not verify whether the corresponding static
992 * queue has been created. The returned value is a handle, which may or
993 * may not refer to an existing queue.
994 *
995 * @return A valid static queue handle or EM_QUEUE_UNDEF on error.
996 *
997 * @see em_queue_create_static(), em_queue_static_max_num()
998 */
999em_queue_t em_queue_static_handle(uint16_t static_offset);
1000
1001/**
1002 * Get the associated queue group of the given queue.
1003 *
1004 * @param queue Queue handle
1005 *
1006 * @return Queue group or EM_QUEUE_GROUP_UNDEF on error.
1007 *
1008 * @see em_queue_create(), em_queue_group_create(), em_queue_group_modify()
1009 */
1010em_queue_group_t em_queue_qgroup(em_queue_t queue);
1011
1012/* Backwards compatible naming ("get") */
1013#define em_queue_get_group em_queue_qgroup
1014
1015/**
1016 * Get the associated atomic group (if any) of the given queue.
1017 *
1018 * Returns the atomic group of the given queue.
1019 *
1020 * @param queue Queue handle
1021 *
1022 * @return The atomic group the queue belongs to or EM_ATOMIC_GROUP_UNDEF if
1023 * the given queue is not valid or doesn't belong to an atomic group.
1024 *
1025 * @see em_atomic_group_create()
1026 */
1027em_atomic_group_t em_queue_agroup(em_queue_t queue);
1028
1029/* Backwards compatible naming ("get") - moved from the atomic group API */
1030#define em_atomic_group_get em_queue_agroup
1031
1032/**
1033 * Dequeue an event from an unscheduled queue
1034 *
1035 * This can only be used with unscheduled queues created with the type
1036 * EM_QUEUE_TYPE_UNSCHEDULED. Events are added to these queues with em_send(),
1037 * similar to queues of other types, but applications needs to explicitly
1038 * dequeue the event(s). Unscheduled queues are general purpose FIFOs, i.e.
1039 * send(enqueue) to tail and dequeue from head. The maximum length of an
1040 * unscheduled queue is system specific.
1041 *
1042 * An unscheduled queue can also have a context, but if used it needs to be
1043 * asked separately using em_queue_context().
1044 *
1045 * @param queue Unscheduled queue handle
1046 *
1047 * @return Event from head of queue or EM_EVENT_UNDEF if there was no events
1048 * or an error occurred.
1049 */
1050em_event_t em_queue_dequeue(em_queue_t queue);
1051
1052/**
1053 * Dequeue multiple events from an unscheduled queue
1054 *
1055 * This can only be used with unscheduled queues created with the type
1056 * EM_QUEUE_TYPE_UNSCHEDULED. Events are added to these queues with em_send(),
1057 * similar to queues of other types, but applications needs to explicitly
1058 * dequeue the event(s). Unscheduled queues are general purpose FIFOs, i.e.
1059 * send(enqueue) to tail and dequeue from head. The maximum length of an
1060 * unscheduled queue is system specific.
1061 *
1062 * An unscheduled queue can also have a context, but needs to be
1063 * asked separately using em_queue_context().
1064 *
1065 * @param queue Unscheduled queue handle
1066 * @param[out] events Array of event handles for output
1067 * @param num Maximum number of events to dequeue
1068 *
1069 * @return Number of successfully dequeued events (0 to num)
1070 */
1071int em_queue_dequeue_multi(em_queue_t queue,
1072 em_event_t events[/*out*/], int num);
1073
1074/**
1075 * Returns the current active queue
1076 *
1077 * The 'current active queue' is the queue that delivered the input event to
1078 * the EO-receive that is currently being run.
1079 *
1080 * Only valid if called within an EO-receive context, will return EM_QUEUE_UNDEF
1081 * otherwise, i.e. can be called from the EO-receive functions or subfunctions
1082 * thereof.
1083 * Note that calling em_queue_current() from an EO-start/stop function that was
1084 * launched from within an EO's receive function will return EM_QUEUE_UNDEF.
1085 *
1086 * @return The current queue or EM_QUEUE_UNDEF if no current queue (or error)
1087 */
1088em_queue_t em_queue_current(void);
1089
1090/**
1091 * Initialize queue iteration and return the first queue handle.
1092 *
1093 * Can be used to initialize the iteration to retrieve all created queues for
1094 * debugging or management purposes. Use em_queue_next() after this call
1095 * until it returns EM_QUEUE_UNDEF. A new call to em_queue_first() resets
1096 * the iteration, which is maintained per core (thread). The operation should be
1097 * completed in one go before returning from the EO's event receive function (or
1098 * start/stop).
1099 *
1100 * The number of queues (output arg 'num') may not match the amount of queues
1101 * actually returned by iterating using em_queue_next() if queues are added
1102 * or removed in parallel by another core. The order of the returned queue
1103 * handles is undefined.
1104 *
1105 * @code
1106 * unsigned int num;
1107 * em_queue_t q = em_queue_first(&num);
1108 * while (q != EM_QUEUE_UNDEF) {
1109 * q = em_queue_next();
1110 * }
1111 * @endcode
1112 *
1113 * @param[out] num Pointer to an unsigned int to store the amount of queues
1114 * into
1115 *
1116 * @return The first queue handle or EM_QUEUE_UNDEF if none exist
1117 *
1118 * @see em_queue_next()
1119 */
1120em_queue_t em_queue_first(unsigned int *num);
1121
1122/* Backwards compatible naming ("get") */
1123#define em_queue_get_first em_queue_first
1124
1125/**
1126 * Return the next queue handle.
1127 *
1128 * Continues the queue iteration started by em_queue_first() and returns the
1129 * next queue handle.
1130 *
1131 * @return The next queue handle or EM_QUEUE_UNDEF if the queue iteration is
1132 * completed (i.e. no more queues available).
1133 *
1134 * @see em_queue_first()
1135 */
1136em_queue_t em_queue_next(void);
1137/* Backwards compatible naming ("get") */
1138#define em_queue_get_next em_queue_next
1139
1140/**
1141 * Get a unique index corresponding to the given EM queue handle.
1142 *
1143 * Returns a unique index in the range 0 to em_queue_max_num() - 1.
1144 * The same EM queue handle will always map to the same index.
1145 *
1146 * Only meaningful for queues created within the current EM instance.
1147 *
1148 * @param queue EM queue handle
1149 * @return Index in the range 0 to em_queue_max_num() - 1
1150 */
1151int em_queue_index(em_queue_t queue);
1152
1153/* Backwards compatible naming ("get") */
1154#define em_queue_get_index em_queue_index
1155
1156/**
1157 * Returns the number of queue priorities available.
1158 *
1159 * Optionally the amount of actual runtime priorities can be inquired.
1160 * Valid queue priority range is from 0 (lowest priority) to
1161 * em_queue_num_prio() - 1.
1162 *
1163 * Runtime environment may provide different amount of levels. In that case EM
1164 * priorities are mapped to the runtime values depending on mapping mode
1165 * selected in the runtime configuration file.
1166 *
1167 * @param[out] num_runtime Pointer to an int to receive the number of
1168 * actual runtime priorities. Set to NULL if
1169 * not needed.
1170 *
1171 * @return number of queue priorities
1172 *
1173 * @see em-odp.conf
1174 */
1175int em_queue_num_prio(int *num_runtime);
1176
1177/* Backwards compatible naming ("get") */
1178#define em_queue_get_num_prio em_queue_num_prio
1179
1180/**
1181 * Returns the maximum number of EM queues that can be created.
1182 *
1183 * The maximum number of EM queues contains all EM queues (static and dynamic)
1184 * created by the application as well as the internal EM queues.
1185 * The number of static and dynamic queues can be configured via
1186 * 'queue.num_static' and 'queue.num_dynamic' in em-odp.conf.
1187 *
1188 * Note that the function returns the maximum number of queues that _can_ be
1189 * created, not the actual number of queues currently created nor the max number
1190 * of queues that has been created at any point in time in the EM instance.
1191 * The actual number of queues currently created can be obtained by calling
1192 * em_queue_first(&num).
1193 *
1194 * @return the maximum number of EM queues of any type that can be created in
1195 * the EM instance
1196 *
1197 * @see em_queue_internal_max_num(), em_queue_static_max_num(),
1198 * em_queue_dynamic_max_num()
1199 */
1200int em_queue_max_num(void);
1201
1202/* Backwards compatible naming ("get") */
1203#define em_queue_get_max_num em_queue_max_num
1204
1205/**
1206 * Get the maximum number of EM internal queues that EM might internally create.
1207 *
1208 * EM reserves a number of internal queues for its own use (core-local and
1209 * shared internal queues) - this function returns that number.
1210 * Note that this is a maximum number and that the actual number of internal
1211 * queues may be less depending on the EM configuration and runtime environment.
1212 *
1213 * @return the maximum number of internal queues reserved by EM
1214 *
1215 * @see em_queue_max_num()
1216 */
1218
1219/**
1220 * Get the maximum number of EM static queues that can be created.
1221 *
1222 * The maximum number of EM static queues that can be created are configured
1223 * via 'queue.num_static' in em-odp.conf.
1224 *
1225 * @return Number of static queues configured, or 0 if none configured
1226 *
1227 * @see em_queue_max_num(), em_queue_internal_max_num(),
1228 * em_queue_dynamic_max_num(), em_queue_aggr_max_num()
1229 */
1230int em_queue_static_max_num(void);
1231
1232/**
1233 * Get the maximum number of EM dynamic queues that can be created.
1234 *
1235 * The maximum number of dynamic queues that can be created is configured via
1236 * 'queue.num_dynamic' in em-odp.conf.
1237 *
1238 * @return The maximum number of dynamic queues that can be created in the
1239 * EM instance.
1240 *
1241 * @see em_queue_max_num(), em_queue_internal_max_num(),
1242 * em_queue_static_max_num(), em_queue_aggr_max_num()
1243 */
1244int em_queue_dynamic_max_num(void);
1245
1246/**
1247 * Get the maximum number of EM aggregator queues that can be created.
1248 *
1249 * The maximum number of aggregator queues that can be created is configured via
1250 * 'queue.num_aggr' in em-odp.conf.
1251 *
1252 * @return The maximum number of aggregator queues that can be created over all
1253 * parent (scheduled and unscheduled) queues in the EM instance.
1254 *
1255 * @see em_queue_max_num(), em_queue_internal_max_num(),
1256 * em_queue_static_max_num(), em_queue_dynamic_max_num()
1257 */
1258int em_queue_aggr_max_num(void);
1259
1260/**
1261 * Get the number of aggregator queues for the given parent queue.
1262 *
1263 * The parent queue can be a scheduled or unscheduled queue, but not an
1264 * aggregator queue itself.
1265 *
1266 * @param parent_queue Parent queue handle
1267 *
1268 * @return Number of aggregator queues configured for 'parent_queue', or 0 if
1269 * no aggregator queues are configured (or on an error).
1270 *
1271 * @see em_queue_aggr(), em_queue_aggr_info(), em_queue_aggr_list()
1272 */
1273uint32_t em_queue_aggr_num(em_queue_t parent_queue);
1274
1275/**
1276 * Get an aggregator queue handle by index for the given parent queue.
1277 *
1278 * The parent queue can be a scheduled or unscheduled queue, but not an
1279 * aggregator queue itself. The returned aggregator queue is associated with
1280 * the parent queue and can be used as destination queue for sending/enqueuing
1281 * events.
1282 * Events sent to this queue may be aggregated into vector events before being
1283 * enqueued to the parent queue.
1284 * The parent queue must have been configured with aggregator queues when
1285 * created with em_queue_create_param() to get any aggregator queue returned by
1286 * this function.
1287 *
1288 * @param parent_queue Parent queue handle
1289 * @param aggr_index Aggregator queue index, range 0 to
1290 * em_queue_aggr_num(parent_queue) - 1.
1291 *
1292 * @return Aggregator queue handle or EM_QUEUE_UNDEF if not found.
1293 * @retval EM_QUEUE_UNDEF Invalid 'parent_queue' (error reported).
1294 * @retval EM_QUEUE_UNDEF 'aggr_index' is out of range (no error).
1295 *
1296 * @see em_queue_create_param(), em_queue_aggr_conf_t,
1297 * em_queue_aggr_num(), em_queue_aggr_info(), em_queue_aggr_list()
1298 */
1299em_queue_t em_queue_aggr(em_queue_t parent_queue, uint32_t aggr_index);
1300
1301/**
1302 * Get aggregator queue handles for a given parent queue.
1303 *
1304 * This function outputs the total number of aggregator queues configured for
1305 * the given parent queue via the output parameter 'num_aggr' and writes queue
1306 * handles to 'aggr_list[]' up to the given 'max' length (<= EM_QUEUE_MAX_AGGR).
1307 *
1308 * The parent queue can be a scheduled or unscheduled queue, but not an
1309 * aggregator queue itself. The returned aggregator queues are associated with
1310 * the parent queue and can be used as destination queues for sending/enqueuing
1311 * events.
1312 * Events sent to these queues may be aggregated into vector events before
1313 * being enqueued to the parent queue.
1314 * The parent queue must have been configured with aggregator queues when
1315 * created with em_queue_create_param() to get any aggregator queues returned by
1316 * this function.
1317 *
1318 * To only get the number of aggregator queues without retrieving handles:
1319 * @code
1320 * uint32_t num_aggr = 0;
1321 *
1322 * (void)em_queue_aggr_list(parent_queue, NULL, 0, &num_aggr);
1323 * @endcode
1324 *
1325 * To get all aggregator queue handles for a parent queue:
1326 * @code
1327 * em_queue_t aggr_list[EM_QUEUE_MAX_AGGR];
1328 * uint32_t num_aggr = 0;
1329 * uint32_t num_out = em_queue_aggr_list(parent_queue, aggr_list,
1330 * EM_QUEUE_MAX_AGGR, &num_aggr);
1331 * for (uint32_t i = 0; i < num_out; i++)
1332 * use_aggr(aggr_list[i]);
1333 * @endcode
1334 *
1335 * @param parent_queue Parent queue handle for which to list the
1336 * aggregator queues.
1337 * @param[out] aggr_list Pointer to an aggregator queue handle array that
1338 * can fit 'max' amount of handles.
1339 * Use NULL if only interested in 'num_aggr'.
1340 * @param max Max number of handles that can be written into
1341 * 'aggr_list[]', ignored if 'aggr_list' is NULL.
1342 * 'max' is in the range 0 .. EM_QUEUE_MAX_AGGR.
1343 * 'max' is capped to EM_QUEUE_MAX_AGGR if greater.
1344 * @param[out] num_aggr Output for the total number of configured
1345 * aggregator queues for 'parent_queue'.
1346 * Optional, can be NULL if not needed.
1347 *
1348 * @return Number of handles written into 'aggr_list[]' (in the range
1349 * 0 to min(num_aggr, max)).
1350 *
1351 * @see em_queue_create_param(), em_queue_aggr_conf_t
1352 */
1353uint32_t em_queue_aggr_list(em_queue_t parent_queue,
1354 em_queue_t aggr_list[/*out:max*/], uint32_t max,
1355 uint32_t *num_aggr /*out*/);
1356
1357/**
1358 * Aggregator queue information.
1359 *
1360 * Contains the aggregator queue handle and the configuration that was
1361 * used when the parent queue was created with em_queue_create_param().
1362 * Filled by em_queue_aggr_info() for each aggregator queue of a parent queue.
1363 *
1364 * @see em_queue_aggr_info(), em_queue_aggr_conf_t
1365 */
1366typedef struct {
1367 /** Aggregator queue handle */
1368 em_queue_t queue;
1369 /** Event vector pool used for aggregation */
1370 em_pool_t pool;
1371 /** Maximum time in nanoseconds to wait for aggregation (0 = no limit) */
1372 uint64_t max_tmo_ns;
1373 /** Maximum number of events in vector */
1374 uint32_t max_size;
1375 /** Aggregation and vector event type */
1378
1379/**
1380 * Get aggregator queue information for the given parent queue.
1381 *
1382 * Returns information about the aggregator queues configured for the given
1383 * parent queue. Each element in the output array 'aggr_info[]' contains the
1384 * aggregator queue handle and the configuration that was used when the parent
1385 * queue was created.
1386 *
1387 * The parent queue can be a scheduled or unscheduled queue, but not an
1388 * aggregator queue itself.
1389 *
1390 * This is a heavier operation than em_queue_aggr() and em_queue_aggr_list() and
1391 * should only be used when the additional information about the aggregator
1392 * queues is needed.
1393 *
1394 * @code
1395 * em_queue_aggr_info_t info[EM_QUEUE_MAX_AGGR];
1396 * uint32_t num_aggr = 0;
1397 * uint32_t num = em_queue_aggr_info(parent_queue, info,
1398 * EM_QUEUE_MAX_AGGR, &num_aggr);
1399 * for (uint32_t i = 0; i < num; i++)
1400 * use_aggr(info[i].queue, info[i].pool, ...);
1401 * @endcode
1402 *
1403 * @param parent_queue Parent queue handle
1404 * @param[out] aggr_info Array for aggregator queue information output,
1405 * must have room for 'max' entries.
1406 * Use NULL if only interested in 'num_aggr'.
1407 * @param max Maximum number of entries to write into
1408 * 'aggr_info[]', ignored if 'aggr_info' is NULL.
1409 * 'max' is in the range 0 .. EM_QUEUE_MAX_AGGR.
1410 * @param[out] num_aggr Output for the total number of configured
1411 * aggregator queues for 'parent_queue'.
1412 * Optional, can be NULL if not needed.
1413 *
1414 * @return Number of entries written into 'aggr_info[]' (in the range
1415 * 0 to min(num_aggr, max)), or 0 on error.
1416 *
1417 * @see em_queue_create_param(), em_queue_aggr_conf_t,
1418 * em_queue_aggr_num(), em_queue_aggr(), em_queue_aggr_list()
1419 */
1420uint32_t em_queue_aggr_info(em_queue_t parent_queue,
1421 em_queue_aggr_info_t aggr_info[/*out*/],
1422 uint32_t max, uint32_t *num_aggr /*out*/);
1423
1424/**
1425 * Returns the device-id extracted from the given queue handle
1426 *
1427 * An EM queue handle consists of a device-id and a queue-id. This function
1428 * extracts the device-id from an EM queue handle and returns it.
1429 *
1430 * @param queue EM queue handle
1431 * @return the device-id extracted from the queue handle
1432 */
1433uint16_t em_queue_device_id(em_queue_t queue);
1434
1435/* Backwards compatible naming ("get") */
1436#define em_queue_get_device_id em_queue_device_id
1437
1438/**
1439 * Returns the queue-id extracted from the given queue handle
1440 *
1441 * An EM queue handle consists of a device-id and a queue-id. This function
1442 * extracts the queue-id from an EM queue handle and returns it.
1443 *
1444 * @param queue EM queue handle
1445 * @return the queue-id extracted from the queue handle
1446 */
1447uint16_t em_queue_qid(em_queue_t queue);
1448
1449/* Backwards compatible naming ("get") */
1450#define em_queue_get_qid em_queue_qid
1451
1452/**
1453 * Extract and output both the device-id and the queue-id from the given
1454 * queue handle.
1455 *
1456 * An EM queue handle consists of a device-id and a queue-id. This function
1457 * extracts both the device-id and the queue-id from an EM queue handle and
1458 * returns them to the caller via the output arguments 'device_id' and 'qid'.
1459 *
1460 * @param queue EM queue handle
1461 * @param[out] device_id device-id
1462 * @param[out] qid queue-id
1463 */
1464void em_queue_ids(em_queue_t queue, uint16_t *device_id /*out*/,
1465 uint16_t *qid /*out*/);
1466
1467/* Backwards compatible naming ("get") */
1468#define em_queue_get_ids em_queue_ids
1469
1470/**
1471 * Construct a raw EM queue handle from the provided device-id and queue-id.
1472 *
1473 * An EM queue handle consists of a device-id and a queue-id. This function
1474 * constructs an EM queue handle by combining the device-id and queue-id
1475 * together into an EM queue handle.
1476 *
1477 * @note No checks for the validity of the provided device-id or queue-id are
1478 * done. Thus the constructed EM queue handle is a raw value that may not refer
1479 * to any existing queue on this EM instance or on another. Be careful.
1480 *
1481 * @param device_id
1482 * @param qid
1483 * @return raw EM queue handle created from the given arguments
1484 */
1485em_queue_t em_queue_handle_raw(uint16_t device_id, uint16_t qid);
1486
1487/**
1488 * Convert an queue handle to an unsigned integer
1489 *
1490 * @param queue queue handle to be converted
1491 * @return uint32_t value that can be used to print/display the handle
1492 *
1493 * @note This routine is intended to be used for diagnostic purposes
1494 * to enable applications to e.g. generate a printable value that represents
1495 * an em_queue_t handle.
1496 *
1497 * @note Unlike other "EM handle to unsigned integer" conversion functions,
1498 * the queue handle is converted to a uint32_t (instead of a uint64_t) since
1499 * the handle consists of a 16-bit device-id and a 16-bit queue-id.
1500 */
1501uint32_t em_queue_to_u32(em_queue_t queue);
1502
1503/**
1504 * @}
1505 */
1506#ifdef __cplusplus
1507}
1508#endif
1509
1510#pragma GCC visibility pop
1511#endif /* EVENT_MACHINE_QUEUE_H_ */
uint32_t em_event_type_t
uint32_t em_status_t
void em_queue_ids(em_queue_t queue, uint16_t *device_id, uint16_t *qid)
em_queue_t em_queue_static_handle(uint16_t static_offset)
em_queue_t em_queue_handle_raw(uint16_t device_id, uint16_t qid)
em_event_t em_queue_dequeue(em_queue_t queue)
uint32_t em_queue_aggr_list(em_queue_t parent_queue, em_queue_t aggr_list[], uint32_t max, uint32_t *num_aggr)
em_atomic_group_t em_queue_agroup(em_queue_t queue)
void * em_queue_context(em_queue_t queue)
uint32_t em_queue_aggr_info(em_queue_t parent_queue, em_queue_aggr_info_t aggr_info[], uint32_t max, uint32_t *num_aggr)
uint16_t em_queue_qid(em_queue_t queue)
int em_queue_dequeue_multi(em_queue_t queue, em_event_t events[], int num)
em_status_t em_queue_delete(em_queue_t queue)
int em_queue_static_max_num(void)
uint32_t em_queue_type_t
uint16_t em_queue_device_id(em_queue_t queue)
int em_queue_max_num(void)
uint32_t em_queue_prio_t
void em_queue_param_init(em_queue_param_t *param)
em_status_t em_queue_set_context(em_queue_t queue, const void *context)
size_t em_queue_name(em_queue_t queue, char *name, size_t maxlen)
int em_queue_num_prio(int *num_runtime)
em_queue_prio_t em_queue_priority(em_queue_t queue)
int em_queue_dynamic_max_num(void)
int em_queue_index(em_queue_t queue)
em_queue_type_t em_queue_type(em_queue_t queue)
void em_queue_aggr_conf_init(uint32_t num_aggr, em_queue_aggr_conf_t aggr_conf[])
int(* em_output_func_t)(const em_event_t events[], const unsigned int num, const em_queue_t output_queue, void *output_fn_args)
em_status_t em_queue_create_static(const char *name, em_queue_type_t type, em_queue_prio_t prio, em_queue_group_t group, em_queue_t queue, const em_queue_conf_t *conf)
uint32_t em_queue_aggr_num(em_queue_t parent_queue)
em_queue_group_t em_queue_qgroup(em_queue_t queue)
em_queue_t em_queue_create_param(const char *name, const em_queue_param_t *param)
uint32_t em_queue_to_u32(em_queue_t queue)
em_queue_t em_queue_find(const char *name)
em_queue_t em_queue_first(unsigned int *num)
em_queue_t em_queue_aggr(em_queue_t parent_queue, uint32_t aggr_index)
int em_queue_aggr_max_num(void)
em_queue_t em_queue_create(const char *name, em_queue_type_t type, em_queue_prio_t prio, em_queue_group_t group, const em_queue_conf_t *conf)
uint32_t em_queue_flag_t
em_queue_t em_queue_next(void)
int em_queue_internal_max_num(void)
em_queue_t em_queue_current(void)
@ EM_QUEUE_TYPE_AGGR
@ EM_QUEUE_TYPE_ORDERED
@ EM_QUEUE_TYPE_ATOMIC
@ EM_QUEUE_TYPE_UNSCHEDULED
@ EM_QUEUE_TYPE_PARALLEL
@ EM_QUEUE_TYPE_PARALLEL_ORDERED
@ EM_QUEUE_TYPE_UNDEF
@ EM_QUEUE_TYPE_LOCAL
@ EM_QUEUE_TYPE_OUTPUT
@ EM_QUEUE_PRIO_LOW
@ EM_QUEUE_PRIO_NORMAL
@ EM_QUEUE_PRIO_LOWEST
@ EM_QUEUE_PRIO_HIGHEST
@ EM_QUEUE_PRIO_HIGH
em_queue_flag_t flags
em_queue_aggr_conf_t * aggr_conf
em_output_queue_conf_t output_conf
em_queue_flag_t flags
em_atomic_group_t atomic_group
em_queue_group_t queue_group