EM-ODP 4.4.0
Event Machine on ODP
Loading...
Searching...
No Matches
event_machine_queue.c
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 _GNU_SOURCE
32#define _GNU_SOURCE
33#endif
34
35#ifdef HAVE_CONFIG_H
36#include "config.h"
37#endif
38
39#include <stdbool.h>
40#include <stdint.h>
41#include <stdio.h>
42#include <string.h>
43
44#include <odp_api.h>
45
46#include <event_machine.h>
48
49#include "em_eo.h"
50#include "em_eo_types.h"
51#include "em_error.h"
52#include "em_internal_event.h"
54#include "em_mem.h"
55#include "em_queue.h"
56#include "em_queue_group.h"
57#include "em_queue_inline.h"
58#include "em_queue_types.h"
59
60/* per core (thread) state for queue_next() */
61static ENV_LOCAL unsigned int _queue_tbl_iter_idx;
62
63COMPILE_TIME_ASSERT(EM_QUEUE_NAME_LEN <= ODP_QUEUE_NAME_LEN,
64 EM_QUEUE_NAME_LEN_OVER_ODP_LIMIT);
65
66em_queue_t
67em_queue_create(const char *name, em_queue_type_t type, em_queue_prio_t prio,
68 em_queue_group_t queue_group, const em_queue_conf_t *conf)
69{
70 const char *err_str = "";
71 em_queue_t queue;
72 em_queue_param_t param;
73
74 if (unlikely(em_shm->opt.queue.num_dynamic == 0)) {
75 INTERNAL_ERROR(EM_ERR_NOT_SUPPORTED, EM_ESCOPE_QUEUE_CREATE,
76 "Dynamic queues not configured!");
77 return EM_QUEUE_UNDEF;
78 }
79
80 em_queue_param_init(&param);
81 param.type = type;
82 param.prio = prio;
83 param.queue_group = queue_group;
84 queue_param_apply_conf(&param, conf);
85
86 queue = queue_create_param(name, &param, &err_str);
87
88 if (unlikely(queue == EM_QUEUE_UNDEF))
89 INTERNAL_ERROR(EM_ERR_LIB_FAILED, EM_ESCOPE_QUEUE_CREATE,
90 err_str);
91 return queue;
92}
93
96 em_queue_prio_t prio, em_queue_group_t queue_group,
97 em_queue_t queue, const em_queue_conf_t *conf)
98{
99 const char *err_str = "";
100 em_queue_t queue_static;
101 em_queue_param_t param;
102 internal_queue_t iq = {.queue = queue};
103
104 RETURN_ERROR_IF(em_shm->opt.queue.num_static == 0,
105 EM_ERR_NOT_SUPPORTED, EM_ESCOPE_QUEUE_CREATE_STATIC,
106 "Static queues not configured!");
107
109 EM_ERR_BAD_ARG, EM_ESCOPE_QUEUE_CREATE_STATIC,
110 "Invalid static queue requested:%" PRI_QUEUE "",
111 queue);
112
113 RETURN_ERROR_IF(iq.queue_id < em_shm->queue_tbl.first_static_queue_id ||
114 iq.queue_id > em_shm->queue_tbl.last_static_queue_id,
115 EM_ERR_BAD_ARG, EM_ESCOPE_QUEUE_CREATE_STATIC,
116 "Static queue id:%u out of range (%u-%u)",
117 iq.queue_id,
118 em_shm->queue_tbl.first_static_queue_id,
119 em_shm->queue_tbl.last_static_queue_id);
120
121 em_queue_param_init(&param);
122 param.queue = queue;
123 param.type = type;
124 param.prio = prio;
125 param.queue_group = queue_group;
126 queue_param_apply_conf(&param, conf);
127
128 queue_static = queue_create_param(name, &param, &err_str);
129 RETURN_ERROR_IF(queue_static == EM_QUEUE_UNDEF,
130 EM_ERR_NOT_FREE, EM_ESCOPE_QUEUE_CREATE_STATIC,
131 "Static queue:%" PRI_QUEUE " creation failed: %s", queue, err_str);
132
133 if (unlikely(queue_static != queue)) {
134 const char *qdel_err = "queue cleanup ok";
135 queue_elem_t *q_elem = queue_elem_get(queue_static);
136
137 /* Fatal error if q_elem == NULL, should never happen if queue_static != UNDEF */
139 EM_ESCOPE_QUEUE_CREATE_STATIC,
140 "Queue error - req:%" PRI_QUEUE " vs. %" PRI_QUEUE "(q_elem NULL)",
141 queue, queue_static);
142
143 (void)queue_delete(q_elem, &qdel_err);
144
145 return INTERNAL_ERROR(EM_ERR_BAD_ID, EM_ESCOPE_QUEUE_CREATE_STATIC,
146 "Queue req:%" PRI_QUEUE " vs. %" PRI_QUEUE " (deleted:%s)",
147 queue, queue_static, qdel_err);
148 }
149
150 return EM_OK;
151}
152
153void em_queue_aggr_conf_init(uint32_t num_aggr, em_queue_aggr_conf_t aggr_conf[])
154{
155 if (unlikely(num_aggr == 0 || num_aggr > EM_QUEUE_MAX_AGGR || !aggr_conf)) {
156 INTERNAL_ERROR(EM_FATAL(EM_ERR_BAD_ARG), EM_ESCOPE_QUEUE_AGGR_CONF_INIT,
157 "Invalid args: num_aggr=%u (valid: 1..%u), aggr_conf=%p",
158 num_aggr, EM_QUEUE_MAX_AGGR, aggr_conf);
159 return;
160 }
161
162 /* Set whole aggr_conf[] first to zero */
163 memset(aggr_conf, 0, sizeof(em_queue_aggr_conf_t) * num_aggr);
164
165 for (uint32_t i = 0; i < num_aggr; i++) {
166 aggr_conf[i].pool = EM_POOL_UNDEF;
167 aggr_conf[i].event_type = EM_EVENT_TYPE_UNDEF;
169 }
170}
171
173{
174 if (unlikely(!param)) {
175 INTERNAL_ERROR(EM_FATAL(EM_ERR_BAD_ARG), EM_ESCOPE_QUEUE_PARAM_INIT,
176 "Invalid arg: param=%p", param);
177 return;
178 }
179
180 memset(param, 0, sizeof(em_queue_param_t));
181 param->queue = EM_QUEUE_UNDEF;
182 param->type = EM_QUEUE_TYPE_UNDEF;
183 param->prio = EM_QUEUE_PRIO_UNDEF;
188}
189
190em_queue_t em_queue_create_param(const char *name,
191 const em_queue_param_t *param)
192{
193 if (unlikely(!param || param->__internal_check != EM_CHECK_INIT_CALLED)) {
194 INTERNAL_ERROR(EM_ERR_NOT_INITIALIZED, EM_ESCOPE_QUEUE_CREATE_PARAM,
195 "Invalid queue param: Use em_queue_param_init() before create");
196 return EM_QUEUE_UNDEF;
197 }
198
199 const char *err_str = "";
200 em_queue_t queue = queue_create_param(name, param, &err_str);
201
202 if (unlikely(queue == EM_QUEUE_UNDEF))
203 INTERNAL_ERROR(EM_ERR_LIB_FAILED, EM_ESCOPE_QUEUE_CREATE_PARAM, err_str);
204
205 return queue;
206}
207
209{
210 queue_elem_t *const q_elem = queue_elem_get(queue);
211 em_status_t status;
212 const char *del_err = "unknown error";
213
214 RETURN_ERROR_IF(q_elem == NULL || !queue_allocated(q_elem),
215 EM_ERR_BAD_ARG, EM_ESCOPE_QUEUE_DELETE,
216 "Invalid queue:%" PRI_QUEUE "", queue);
217
218 status = queue_delete(q_elem, &del_err);
219
220 RETURN_ERROR_IF(status != EM_OK, status, EM_ESCOPE_QUEUE_DELETE,
221 "%s", del_err);
222
223 return status;
224}
225
226em_status_t em_queue_set_context(em_queue_t queue, const void *context)
227{
228 queue_elem_t *const queue_elem = queue_elem_get(queue);
229
230 if (EM_CHECK_LEVEL > 0)
231 RETURN_ERROR_IF(queue_elem == NULL || !queue_allocated(queue_elem),
232 EM_ERR_BAD_ARG, EM_ESCOPE_QUEUE_SET_CONTEXT,
233 "Invalid queue:%" PRI_QUEUE "", queue);
234
235 queue_elem->context = (void *)(uintptr_t)context;
236
237 return EM_OK;
238}
239
240void *em_queue_context(em_queue_t queue)
241{
242 const queue_elem_t *queue_elem = queue_elem_get(queue);
243
244 if (EM_CHECK_LEVEL > 0 && unlikely(queue_elem == NULL)) {
245 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_QUEUE_CONTEXT,
246 "Invalid queue:%" PRI_QUEUE "", queue);
247 return NULL;
248 }
249
250 if (unlikely(EM_CHECK_LEVEL >= 2 && !queue_allocated(queue_elem))) {
251 INTERNAL_ERROR(EM_ERR_NOT_CREATED, EM_ESCOPE_QUEUE_CONTEXT,
252 "Queue:%" PRI_QUEUE " not created!", queue);
253 return NULL;
254 }
255
256 return queue_elem->context;
257}
258
259size_t em_queue_name(em_queue_t queue, char *name, size_t maxlen)
260{
261 const queue_elem_t *queue_elem = queue_elem_get(queue);
262
263 if (EM_CHECK_LEVEL > 0 &&
264 unlikely(name == NULL || maxlen == 0)) {
265 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_QUEUE_NAME,
266 "Invalid ptr or maxlen (name=0x%" PRIx64 ", maxlen=%zu)",
267 name, maxlen);
268 return 0;
269 }
270
271 name[0] = '\0';
272
273 if (EM_CHECK_LEVEL > 0 &&
274 unlikely(queue_elem == NULL || !queue_allocated(queue_elem))) {
275 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_QUEUE_NAME,
276 "Invalid queue:%" PRI_QUEUE "", queue);
277 return 0;
278 }
279
280 return queue_name(queue_elem, name, maxlen);
281}
282
283em_queue_t em_queue_find(const char *name)
284{
285 if (name && *name) {
286 /* this might be worth optimizing if maaany queues */
287 for (unsigned int i = 0; i < em_shm->queue_tbl.max_queue_num; i++) {
288 const queue_elem_t *q_elem =
289 &em_shm->queue_tbl.queue_elem[i];
290
291 if (queue_allocated(q_elem) &&
292 !strncmp(name, em_shm->queue_tbl.name[i], EM_QUEUE_NAME_LEN)) {
293 return (em_queue_t)(uintptr_t)
294 em_shm->queue_tbl.queue_elem[i].queue;
295 }
296 }
297 }
298 return EM_QUEUE_UNDEF;
299}
300
302{
303 const queue_elem_t *queue_elem = queue_elem_get(queue);
304
305 if (EM_CHECK_LEVEL > 0 &&
306 unlikely(queue_elem == NULL || !queue_allocated(queue_elem))) {
307 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_QUEUE_PRIORITY,
308 "Invalid queue:%" PRI_QUEUE "", queue);
309 return EM_QUEUE_PRIO_UNDEF;
310 }
311
312 return queue_elem->priority;
313}
314
316{
317 const queue_elem_t *queue_elem = queue_elem_get(queue);
318
319 if (EM_CHECK_LEVEL > 0 &&
320 unlikely(queue_elem == NULL || !queue_allocated(queue_elem))) {
321 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_QUEUE_TYPE,
322 "Invalid queue-id:%" PRI_QUEUE "", queue);
323 return EM_QUEUE_TYPE_UNDEF;
324 }
325
326 return queue_elem->type;
327}
328
329em_queue_t em_queue_static_handle(uint16_t static_offset)
330{
331 if (unlikely(em_shm->opt.queue.num_static == 0)) {
333 EM_ESCOPE_QUEUE_STATIC_HANDLE,
334 "Static queues not configured!");
335 return EM_QUEUE_UNDEF;
336 }
337
338 if (unlikely(static_offset >= em_shm->opt.queue.num_static)) {
340 EM_ESCOPE_QUEUE_STATIC_HANDLE,
341 "Static offset %u out of range (0-%u)!",
342 static_offset,
343 em_shm->opt.queue.num_static - 1);
344 return EM_QUEUE_UNDEF;
345 }
346
347 return queue_id2hdl(em_shm->queue_tbl.first_static_queue_id + static_offset);
348}
349
350em_queue_group_t em_queue_qgroup(em_queue_t queue)
351{
352 const queue_elem_t *q_elem = queue_elem_get(queue);
353
354 if (EM_CHECK_LEVEL > 0 &&
355 unlikely(q_elem == NULL || !queue_allocated(q_elem))) {
356 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_QUEUE_QGROUP,
357 "Invalid queue:%" PRI_QUEUE "", queue);
359 }
360
361 if (unlikely(q_elem->state == EM_QUEUE_STATE_INVALID))
363 else
364 return q_elem->queue_group;
365}
366
367em_atomic_group_t em_queue_agroup(em_queue_t queue)
368{
369 const queue_elem_t *q_elem = queue_elem_get(queue);
370 em_atomic_group_t atomic_group = EM_ATOMIC_GROUP_UNDEF;
371
372 if (unlikely(q_elem == NULL || !queue_allocated(q_elem))) {
373 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_QUEUE_AGROUP,
374 "Invalid queue:%" PRI_QUEUE "", queue);
376 }
377
378 if (q_elem->flags.in_atomic_group)
379 atomic_group = q_elem->agrp.atomic_group;
380
381 return atomic_group;
382}
383
384em_event_t em_queue_dequeue(em_queue_t queue)
385{
386 const queue_elem_t *q_elem = queue_elem_get(queue);
387 em_event_t event;
388
389 if (unlikely(EM_CHECK_LEVEL > 0 && !q_elem)) {
390 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_QUEUE_DEQUEUE,
391 "Invalid EM queue:%" PRI_QUEUE "", queue);
392 return EM_EVENT_UNDEF;
393 }
394
395 if (unlikely(EM_CHECK_LEVEL >= 2 && !queue_allocated(q_elem))) {
396 INTERNAL_ERROR(EM_ERR_NOT_CREATED, EM_ESCOPE_QUEUE_DEQUEUE,
397 "Queue:%" PRI_QUEUE " not created", queue);
398 return EM_EVENT_UNDEF;
399 }
400
401 if (EM_CHECK_LEVEL > 0 &&
402 unlikely(q_elem->type != EM_QUEUE_TYPE_UNSCHEDULED)) {
403 INTERNAL_ERROR(EM_ERR_BAD_CONTEXT, EM_ESCOPE_QUEUE_DEQUEUE,
404 "Queue is not unscheduled, cannot dequeue!");
405 return EM_EVENT_UNDEF;
406 }
407
408 event = queue_dequeue(q_elem);
409 return event;
410}
411
412int em_queue_dequeue_multi(em_queue_t queue,
413 em_event_t events[/*out*/], int num)
414{
415 const queue_elem_t *q_elem = queue_elem_get(queue);
416 int ret;
417
418 if (EM_CHECK_LEVEL > 0 &&
419 unlikely(!q_elem || !events || num < 0)) {
420 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_QUEUE_DEQUEUE_MULTI,
421 "Inv.args: Q:%" PRI_QUEUE " events[]:%p num:%d",
422 queue, events, num);
423 return 0;
424 }
425
426 if (unlikely(EM_CHECK_LEVEL >= 2 && !queue_allocated(q_elem))) {
427 INTERNAL_ERROR(EM_ERR_NOT_CREATED, EM_ESCOPE_QUEUE_DEQUEUE,
428 "Queue:%" PRI_QUEUE " not created", queue);
429 return 0;
430 }
431
432 if (unlikely(num == 0))
433 return 0;
434
435 if (EM_CHECK_LEVEL > 0 &&
436 unlikely(q_elem->type != EM_QUEUE_TYPE_UNSCHEDULED)) {
438 EM_ESCOPE_QUEUE_DEQUEUE_MULTI,
439 "Queue is not unscheduled, cannot dequeue!");
440 return 0;
441 }
442
443 ret = queue_dequeue_multi(q_elem, events /*out*/, num);
444 if (unlikely(ret < 0)) {
446 EM_ESCOPE_QUEUE_DEQUEUE_MULTI,
447 "odp_queue_deq_multi(%d):%d", num, ret);
448 return 0;
449 }
450
451 return ret;
452}
453
454em_queue_t em_queue_current(void)
455{
456 return queue_current();
457}
458
459em_queue_t em_queue_first(unsigned int *num)
460{
461 const queue_tbl_t *const queue_tbl = &em_shm->queue_tbl;
462 const unsigned int queue_cnt = queue_count();
463 const unsigned int max_queues = em_shm->queue_tbl.max_queue_num;
464
465 _queue_tbl_iter_idx = 0; /* reset iteration */
466
467 if (num)
468 *num = queue_cnt;
469
470 if (queue_cnt == 0) {
471 _queue_tbl_iter_idx = max_queues; /* UNDEF = _next() */
472 return EM_QUEUE_UNDEF;
473 }
474
475 /* find first */
476 while (!queue_allocated(&queue_tbl->queue_elem[_queue_tbl_iter_idx])) {
477 _queue_tbl_iter_idx++;
478 if (_queue_tbl_iter_idx >= max_queues)
479 return EM_QUEUE_UNDEF;
480 }
481
482 return queue_idx2hdl(_queue_tbl_iter_idx);
483}
484
485em_queue_t em_queue_next(void)
486{
487 const unsigned int max_queues = em_shm->queue_tbl.max_queue_num;
488
489 if (_queue_tbl_iter_idx >= max_queues - 1)
490 return EM_QUEUE_UNDEF;
491
492 _queue_tbl_iter_idx++;
493
494 const queue_tbl_t *const queue_tbl = &em_shm->queue_tbl;
495
496 /* find next */
497 while (!queue_allocated(&queue_tbl->queue_elem[_queue_tbl_iter_idx])) {
498 _queue_tbl_iter_idx++;
499 if (_queue_tbl_iter_idx >= max_queues)
500 return EM_QUEUE_UNDEF;
501 }
502
503 return queue_idx2hdl(_queue_tbl_iter_idx);
504}
505
506int em_queue_index(em_queue_t queue)
507{
508 const internal_queue_t iq = {.queue = queue};
509 const int queue_idx = queue_id2idx(iq.queue_id); /* return value */
510
511 if (unlikely((uint16_t)queue_idx > em_shm->queue_tbl.max_queue_num - 1))
512 goto error;
513
514 if (EM_CHECK_LEVEL > 0 &&
515 unlikely(iq.device_id != em_shm->conf.device_id))
516 goto error;
517
518 if (EM_CHECK_LEVEL >= 3) {
519 const queue_elem_t *q_elem =
520 &em_shm->queue_tbl.queue_elem[queue_idx];
521 if (unlikely(q_elem == NULL || !queue_allocated(q_elem)))
522 goto error;
523 }
524
525 return queue_idx;
526
527error:
528 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_QUEUE_INDEX,
529 "Bad arg, invalid queue:%" PRI_QUEUE ":\n"
530 " Q.device-id:0x%" PRIx16 " Q.id:0x%" PRIx16 "",
531 queue, iq.device_id, iq.queue_id);
532 return queue_idx % em_shm->queue_tbl.max_queue_num;
533}
534
535int em_queue_num_prio(int *num_runtime)
536{
537 if (EM_CHECK_LEVEL > 1 && unlikely(em_shm == NULL)) {
538 INTERNAL_ERROR(EM_ERR_NOT_INITIALIZED, EM_ESCOPE_QUEUE_NUM_PRIO,
539 "EM not initialized!");
540 return 0;
541 }
542 if (num_runtime != NULL)
543 *num_runtime = em_shm->queue_prio.num_runtime;
544
545 return EM_QUEUE_PRIO_NUM;
546}
547
549{
550 return em_shm->queue_tbl.max_queue_num;
551}
552
554{
555 return MAX_INTERNAL_QUEUES;
556}
557
559{
560 return em_shm->opt.queue.num_static;
561}
562
564{
565 return em_shm->opt.queue.num_dynamic;
566}
567
569{
570 return em_shm->opt.queue.num_aggr;
571}
572
573uint32_t em_queue_aggr_num(em_queue_t parent_queue)
574{
575 const queue_elem_t *q_elem = queue_elem_get(parent_queue);
576
577 if (EM_CHECK_LEVEL > 0 &&
578 unlikely(!q_elem || !queue_allocated(q_elem))) {
579 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_QUEUE_AGGR_NUM,
580 "Invalid arg: parent_queue=%" PRI_QUEUE "", parent_queue);
581 return 0;
582 }
583
584 if (unlikely(!q_elem->flags.has_aggr))
585 return 0;
586
587 return q_elem->aggr_parent.num_aggr;
588}
589
590em_queue_t em_queue_aggr(em_queue_t parent_queue, uint32_t aggr_index)
591{
592 const queue_elem_t *q_elem = queue_elem_get(parent_queue);
593
594 if (EM_CHECK_LEVEL > 0 &&
595 unlikely(!q_elem || !queue_allocated(q_elem))) {
596 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_QUEUE_AGGR,
597 "Invalid arg: parent_queue=%" PRI_QUEUE "", parent_queue);
598 return EM_QUEUE_UNDEF;
599 }
600
601 if (unlikely(!q_elem->flags.has_aggr ||
602 aggr_index >= q_elem->aggr_parent.num_aggr))
603 return EM_QUEUE_UNDEF;
604
605 return (em_queue_t)(uintptr_t)q_elem->aggr_parent.aggr_queues[aggr_index];
606}
607
608uint32_t em_queue_aggr_list(em_queue_t parent_queue,
609 em_queue_t aggr_list[/*out:max*/], uint32_t max,
610 uint32_t *num_aggr /*out*/)
611{
612 const queue_elem_t *q_elem = queue_elem_get(parent_queue);
613
614 if (EM_CHECK_LEVEL > 0 &&
615 unlikely(!q_elem || !queue_allocated(q_elem))) {
616 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_QUEUE_AGGR_LIST,
617 "Invalid arg: parent_queue=%" PRI_QUEUE "", parent_queue);
618 return 0;
619 }
620
621 if (unlikely(!q_elem->flags.has_aggr)) {
622 if (num_aggr)
623 *num_aggr = 0;
624 return 0;
625 }
626
627 const uint32_t num = q_elem->aggr_parent.num_aggr; /* <= EM_QUEUE_MAX_AGGR */
628 const uint32_t num_out = MIN(num, max);
629
630 if (num_aggr)
631 *num_aggr = num;
632 if (!aggr_list || num_out == 0)
633 return 0;
634
635 for (uint32_t i = 0; i < num_out; i++)
636 aggr_list[i] = (em_queue_t)(uintptr_t)q_elem->aggr_parent.aggr_queues[i];
637
638 return num_out;
639}
640
641uint32_t em_queue_aggr_info(em_queue_t parent_queue,
642 em_queue_aggr_info_t aggr_info[/*out*/],
643 uint32_t max, uint32_t *num_aggr /*out*/)
644{
645 const queue_elem_t *q_elem = queue_elem_get(parent_queue);
646
647 if (EM_CHECK_LEVEL > 0 &&
648 unlikely(!q_elem || !queue_allocated(q_elem))) {
649 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_QUEUE_AGGR_INFO,
650 "Invalid args: parent_queue=%" PRI_QUEUE "", parent_queue);
651 return 0;
652 }
653
654 if (unlikely(!q_elem->flags.has_aggr)) {
655 if (num_aggr)
656 *num_aggr = 0;
657 return 0;
658 }
659
660 const uint32_t num = q_elem->aggr_parent.num_aggr; /* <= EM_QUEUE_MAX_AGGR */
661 const uint32_t num_out = MIN(num, max);
662
663 if (num_aggr)
664 *num_aggr = num;
665 if (!aggr_info || num_out == 0)
666 return 0;
667
668 for (uint32_t i = 0; i < num_out; i++) {
669 em_queue_t aggr_queue = (em_queue_t)(uintptr_t)q_elem->aggr_parent.aggr_queues[i];
670 queue_elem_t *aggr_qelem = queue_elem_get(aggr_queue);
671
672 if (unlikely(!aggr_qelem)) {
673 INTERNAL_ERROR(EM_ERR_BAD_STATE, EM_ESCOPE_QUEUE_AGGR_INFO,
674 "Q:%" PRI_QUEUE " - Invalid aggr-Q:%" PRI_QUEUE ", idx:%u",
675 parent_queue, aggr_queue, i);
676 return i;
677 }
678
679 if (EM_CHECK_LEVEL >= 3 &&
680 unlikely(!queue_allocated(aggr_qelem) ||
681 aggr_qelem->type != EM_QUEUE_TYPE_AGGR ||
682 aggr_qelem->aggr.parent_queue != parent_queue)) {
683 INTERNAL_ERROR(EM_ERR_BAD_STATE, EM_ESCOPE_QUEUE_AGGR_INFO,
684 "Q:%" PRI_QUEUE " - Invalid aggr-Q:%" PRI_QUEUE ", idx:%u\n"
685 " aggr-Q:{type=%u, parent-Q=%" PRI_QUEUE "}",
686 parent_queue, aggr_queue, i,
687 aggr_qelem->type, aggr_qelem->aggr.parent_queue);
688 return i;
689 }
690
691 aggr_info[i].queue = aggr_queue;
692 aggr_info[i].pool = aggr_qelem->aggr.pool;
693 aggr_info[i].max_tmo_ns = aggr_qelem->aggr.max_tmo_ns;
694 aggr_info[i].max_size = aggr_qelem->aggr.max_size;
695 aggr_info[i].event_type = aggr_qelem->aggr.event_type;
696 }
697
698 return num_out;
699}
700
701uint16_t em_queue_device_id(em_queue_t queue)
702{
703 internal_queue_t iq = {.queue = queue};
704
705 return iq.device_id;
706}
707
708uint16_t em_queue_qid(em_queue_t queue)
709{
710 internal_queue_t iq = {.queue = queue};
711
712 return iq.queue_id;
713}
714
715void em_queue_ids(em_queue_t queue, uint16_t *device_id /*out*/, uint16_t *qid /*out*/)
716{
717 internal_queue_t iq = {.queue = queue};
718
719 if (likely(device_id))
720 *device_id = iq.device_id;
721 if (likely(qid))
722 *qid = iq.queue_id;
723}
724
725em_queue_t em_queue_handle_raw(uint16_t device_id, uint16_t qid)
726{
727 internal_queue_t iq = {.device_id = device_id, .queue_id = qid};
728
729 return iq.queue;
730}
731
732uint32_t em_queue_to_u32(em_queue_t queue)
733{
734 uint64_t queue_uptr = (uintptr_t)queue;
735 uint32_t queue_u32 = (uint32_t)(queue_uptr & UINT32_MAX);
736
737 return queue_u32;
738}
#define INTERNAL_ERROR(error, escope, fmt,...)
Definition em_error.h:58
#define RETURN_ERROR_IF(cond, error, escope, fmt,...)
Definition em_error.h:65
#define EM_CHECK_INIT_CALLED
em_shm_t * em_shm
@ EM_QUEUE_STATE_INVALID
#define EM_QUEUE_MAX_AGGR
#define EM_QUEUE_PRIO_NUM
#define EM_QUEUE_NAME_LEN
#define EM_CHECK_LEVEL
#define PRI_QUEUE
#define EM_QUEUE_GROUP_UNDEF
#define EM_POOL_UNDEF
#define EM_EVENT_UNDEF
#define EM_ATOMIC_GROUP_UNDEF
#define EM_QUEUE_UNDEF
#define EM_OK
#define EM_FATAL(error)
uint32_t em_status_t
@ EM_ERR_BAD_ID
@ EM_ERR_NOT_CREATED
@ EM_ERR_NOT_FREE
@ EM_ERR_BAD_CONTEXT
@ EM_ERR_BAD_ARG
@ EM_ERR_NOT_SUPPORTED
@ EM_ERR_BAD_STATE
@ EM_ERR_LIB_FAILED
@ EM_ERR_NOT_INITIALIZED
@ EM_ERR_BAD_POINTER
@ EM_EVENT_TYPE_UNDEF
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)
#define EM_QUEUE_PRIO_UNDEF
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[])
#define EM_QUEUE_FLAG_DEFAULT
em_status_t em_queue_create_static(const char *name, em_queue_type_t type, em_queue_prio_t prio, em_queue_group_t queue_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 queue_group, const em_queue_conf_t *conf)
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_UNSCHEDULED
@ EM_QUEUE_TYPE_UNDEF
em_queue_flag_t flags
em_atomic_group_t atomic_group
em_queue_group_t queue_group
struct em_shm_t::@53 queue_prio
em_conf_t conf
Definition em_mem.h:93
em_cfgfile_opts_t opt
Definition em_mem.h:99
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
queue_state_t state
q_elem_atomic_group_t agrp
em_queue_group_t queue_group
queue_elem_flags_t flags