EM-ODP 4.4.0
Event Machine on ODP
Loading...
Searching...
No Matches
em_internal_event.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2012, Nokia Siemens Networks
3 * Copyright (c) 2014-2026, Nokia Solutions and Networks
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * * Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32/**
33 * @file
34 *
35 * EM Internal Control
36 */
37
38#ifndef _GNU_SOURCE
39#define _GNU_SOURCE
40#endif
41
42#ifdef HAVE_CONFIG_H
43#include "config.h"
44#endif
45
46#include <stdbool.h>
47#include <stdint.h>
48#include <string.h>
49
50#include <odp_api.h>
51
52#include <event_machine.h>
54
55#include "em_atomic_group.h"
57#include "em_core.h"
58#include "em_eo.h"
59#include "em_eo_types.h"
60#include "em_error.h"
61#include "em_event.h"
62#include "em_event_group.h"
64#include "em_event_inline.h"
65#include "em_event_state.h"
66#include "em_event_types.h"
67#include "em_internal_event.h"
69#include "em_mem.h"
70#include "em_queue.h"
71#include "em_queue_group.h"
73#include "em_queue_inline.h"
74#include "em_queue_types.h"
75
77{
78 em_queue_t shared_unsched_queue;
79 em_queue_t queue;
80 em_queue_param_t param;
81 const char *err_str = "";
82
83 DBG_PRINT("%s()\n", __func__);
84
85 /*
86 * Create shared internal unsched queue used for internal EM messaging.
87 * Cannot use em_queue_create_static() here since the requested handle
88 * em_shm->queue_tbl.shared_internal_queue_id lies outside of the normal
89 * static range.
90 */
91 shared_unsched_queue = queue_id2hdl(em_shm->queue_tbl.shared_internal_queue_id);
92
93 em_queue_param_init(&param);
94 param.queue = shared_unsched_queue;
96
97 queue = queue_create_param("EMctrl-unschedQ-shared", &param, &err_str);
98 if (queue == EM_QUEUE_UNDEF || queue != shared_unsched_queue)
100
101 return EM_OK;
102}
103
105{
106 const int thr = odp_thread_id();
107 char q_name[EM_QUEUE_NAME_LEN];
108 em_queue_t queue;
109 em_queue_t queue_req;
110 em_queue_param_t param;
111 const char *err_str = "";
112
113 snprintf(q_name, sizeof(q_name), "EMctrl-unschedQ-thr%d", thr);
114 q_name[EM_QUEUE_NAME_LEN - 1] = '\0';
115
116 DBG_PRINT("%s(): %s\n", __func__, q_name);
117
118 queue = em_queue_find(q_name);
119 if (queue != EM_QUEUE_UNDEF) {
120 DBG_PRINT("%s(): thr:%d, %s already created - reusing\n",
121 __func__, thr, q_name);
122
123 const queue_elem_t *q_elem = queue_elem_get(queue);
124
125 if (unlikely(!q_elem || !queue_allocated(q_elem))) {
126 DBG_PRINT("%s(): q_elem invalid for %s\n",
127 __func__, q_name);
128 return EM_ERR_BAD_POINTER;
129 }
130
131 return EM_OK;
132 }
133
134 /*
135 * Create static internal per-core UNSCHEDULED queues used for
136 * internal EM messaging. Cannot use em_queue_create_static()
137 * here since the requested handles lies outside of the normal
138 * static range.
139 */
140 queue_req = queue_id2hdl(em_shm->queue_tbl.first_internal_queue_id + (uint16_t)thr);
141
142 em_queue_param_init(&param);
143 param.queue = queue_req;
146
147 queue = queue_create_param(q_name, &param, &err_str);
148 if (unlikely(queue == EM_QUEUE_UNDEF || queue != queue_req))
150
151 return EM_OK;
152}
153
154/* doc in header file */
156{
157 em_queue_t unsched_queue;
158 em_event_t unsched_event;
159 const queue_elem_t *q_elem = NULL;
160 em_status_t stat;
161
162 unsched_queue = queue_id2hdl(em_shm->queue_tbl.shared_internal_queue_id);
163 for (;/* flush unsched queue */;) {
164 unsched_event = em_queue_dequeue(unsched_queue);
165 if (unsched_event == EM_EVENT_UNDEF)
166 break;
167 em_free(unsched_event);
168 }
169 stat = em_queue_delete(unsched_queue);
170 if (unlikely(stat != EM_OK))
171 return INTERNAL_ERROR(stat, EM_ESCOPE_DELETE_CTRL_QUEUES,
172 "shared unschedQ delete");
173
174 for (int i = 0; i < MAX_INTERNAL_QUEUES - 1; i++) {
175 unsched_queue = queue_id2hdl(em_shm->queue_tbl.first_internal_queue_id + i);
176 q_elem = queue_elem_get(unsched_queue);
177
178 if (!q_elem || !queue_allocated(q_elem) ||
180 continue;
181
182 for (;/* flush unsched queue */;) {
183 unsched_event = em_queue_dequeue(unsched_queue);
184 if (unsched_event == EM_EVENT_UNDEF)
185 break;
186 em_free(unsched_event);
187 }
188
189 stat = em_queue_delete(unsched_queue);
190 if (unlikely(stat != EM_OK))
191 return INTERNAL_ERROR(stat, EM_ESCOPE_DELETE_CTRL_QUEUES,
192 "core unschedQ:%d delete", i);
193 }
194
195 return stat;
196}
197
198int send_core_ctrl_events(const odp_thrmask_t *const thr_mask, em_event_t ctrl_event,
199 void (*f_done_callback)(void *arg_ptr),
200 void *f_done_arg_ptr,
201 int num_notif, const em_notif_t notif_tbl[],
202 bool sync_operation)
203{
204 em_status_t err;
205 em_event_group_t event_group = EM_EVENT_GROUP_UNDEF;
206 const internal_event_t *i_event = em_event_pointer(ctrl_event);
207 const int mask_count = odp_thrmask_count(thr_mask);
208 int alloc_count = 0;
209 int sent_count = 0;
210 int unsent_count = mask_count;
211 int first_qidx;
212 em_event_t events[mask_count];
213 int i;
214
215 if (unlikely(num_notif > EM_EVENT_GROUP_MAX_NOTIF)) {
216 INTERNAL_ERROR(EM_ERR_TOO_LARGE, EM_ESCOPE_INTERNAL_NOTIF,
217 "Too large notif table (%i)", num_notif);
218 return unsent_count;
219 }
220
221 /*
222 * Set up internal notification when all cores are done.
223 */
224 event_group = internal_done_w_notif_req(mask_count /*=evgrp count*/,
225 f_done_callback, f_done_arg_ptr,
226 num_notif, notif_tbl,
227 sync_operation);
228 if (unlikely(event_group == EM_EVENT_GROUP_UNDEF)) {
229 INTERNAL_ERROR(EM_ERR_NOT_FREE, EM_ESCOPE_INTERNAL_NOTIF,
230 "Internal 'done' notif setup failed");
231 return unsent_count;
232 }
233
234 /*
235 * Allocate ctrl events to be sent to the concerned cores.
236 * Reuse the input ctrl_event later so alloc one less.
237 * Copy content from input ctrl_event into all allocated events.
238 */
239 for (i = 0; i < mask_count - 1; i++) {
240 events[i] = em_alloc(sizeof(internal_event_t),
243 if (unlikely(events[i] == EM_EVENT_UNDEF)) {
245 EM_ESCOPE_INTERNAL_NOTIF,
246 "Internal event alloc failed");
247 goto err_free_resources;
248 }
249 alloc_count++;
250
251 internal_event_t *i_event_tmp = em_event_pointer(events[i]);
252 /* Copy input event content */
253 *i_event_tmp = *i_event;
254 }
255 /* Reuse the input event */
256 events[i] = ctrl_event;
257 /* don't increment alloc_count++, caller frees input event on error */
258
259 /*
260 * Send ctrl events to the concerned cores
261 */
262 first_qidx = queue_id2idx(em_shm->queue_tbl.first_internal_queue_id);
263
264 int thr = odp_thrmask_first(thr_mask);
265
266 while (thr >= 0) {
267 /*
268 * Send copy to each core-specific unscheduled ctrl queue,
269 * track completion using an event group.
270 */
271 err = send_ctrl_queue(events[sent_count],
272 queue_idx2hdl(first_qidx + thr),
273 event_group);
274 if (unlikely(err != EM_OK)) {
275 INTERNAL_ERROR(err, EM_ESCOPE_INTERNAL_NOTIF,
276 "Event group send failed");
277 goto err_free_resources;
278 }
279 sent_count++;
280 unsent_count--;
281
282 thr = odp_thrmask_next(thr_mask, thr);
283 }
284
285 return 0; /* Success, all ctrl events sent */
286
287 /* Error handling, free resources */
288err_free_resources:
289 for (i = sent_count; i < alloc_count; i++)
290 em_free(events[i]);
291 evgrp_abort_delete(event_group);
292 return unsent_count;
293}
294
295/**
296 * Handle the internal 'done' event
297 */
298static void i_event__internal_done(const internal_event_t *i_ev)
299{
300 int num_notif;
301 em_status_t ret;
302
303 /* Release the event group, we are done with it */
304 ret = em_event_group_delete(i_ev->done.event_group);
305
306 if (unlikely(ret != EM_OK))
307 INTERNAL_ERROR(ret, EM_ESCOPE_EVENT_INTERNAL_DONE,
308 "Event group %" PRI_EGRP " delete failed (ret=%u)",
309 i_ev->done.event_group, ret);
310
311 /* Call the callback function, performs custom actions at 'done' */
312 if (i_ev->done.f_done_callback != NULL)
313 i_ev->done.f_done_callback(i_ev->done.f_done_arg_ptr);
314
315 /*
316 * Send notification events if requested by the caller.
317 */
318 num_notif = i_ev->done.num_notif;
319
320 if (num_notif > 0) {
321 ret = send_notifs(num_notif, i_ev->done.notif_tbl);
322 if (unlikely(ret != EM_OK))
323 INTERNAL_ERROR(ret, EM_ESCOPE_EVENT_INTERNAL_DONE,
324 "em_send() of notifs(%d) failed",
325 num_notif);
326 }
327}
328
329/**
330 * Handle internal ctrl events
331 */
332static inline void
333internal_event_receive(void *eo_ctx, em_event_t event, em_event_type_t type,
334 em_queue_t queue, void *q_ctx)
335{
336 /* currently unused args */
337 (void)eo_ctx;
338 (void)type;
339 (void)q_ctx;
340
341 internal_event_t *i_event = em_event_pointer(event);
342
343 if (unlikely(!i_event)) {
344 if (event != EM_EVENT_UNDEF)
345 em_free(event); /* unrecognized odp event type? */
346 INTERNAL_ERROR(EM_ERR_BAD_POINTER, EM_ESCOPE_INTERNAL_EVENT_RECV_FUNC,
347 "Q:%" PRI_QUEUE ": Invalid event, evptr NULL", queue);
348 return;
349 }
350
351 switch (i_event->id) {
352 /*
353 * Internal Done event
354 */
355 case EM_INTERNAL_DONE:
356 i_event__internal_done(i_event);
357 break;
358
359 /*
360 * Internal event related to Queue Group modification: add a core
361 */
362 case QUEUE_GROUP_ADD_REQ:
363 i_event__qgrp_add_core_req(i_event);
364 break;
365
366 /*
367 * Internal event related to Queue Group modification: remove a core
368 */
369 case QUEUE_GROUP_REM_REQ:
370 i_event__qgrp_rem_core_req(i_event);
371 break;
372 /*
373 * Internal events related to EO local start&stop functionality
374 */
375 case EO_START_LOCAL_REQ:
376 case EO_START_SYNC_LOCAL_REQ:
377 case EO_STOP_LOCAL_REQ:
378 case EO_STOP_SYNC_LOCAL_REQ:
379 case EO_REM_QUEUE_LOCAL_REQ:
380 case EO_REM_QUEUE_SYNC_LOCAL_REQ:
381 case EO_REM_QUEUE_ALL_LOCAL_REQ:
382 case EO_REM_QUEUE_ALL_SYNC_LOCAL_REQ:
383 i_event__eo_local_func_call_req(i_event);
384 break;
385
386 case TERM_THREAD_REQ:
387 i_event__term_thread_req(i_event);
388 break;
389
390 default:
392 EM_ESCOPE_INTERNAL_EVENT_RECV_FUNC,
393 "Internal ev-id:0x%" PRIx64 " Q:%" PRI_QUEUE "",
394 i_event->id, queue);
395 break;
396 }
397
398 i_event->id = 0;
399 em_free(event);
400}
401
402/* doc in header file */
403em_event_group_t internal_done_w_notif_req(int event_group_count,
404 void (*f_done_callback)(void *arg_ptr),
405 void *f_done_arg_ptr,
406 int num_notif, const em_notif_t notif_tbl[],
407 bool sync_operation)
408{
409 em_event_group_t event_group;
410 em_event_t event;
411 internal_event_t *i_event;
412 em_notif_t i_notif;
413 em_status_t err;
414
417 if (unlikely(event == EM_EVENT_UNDEF)) {
419 EM_ESCOPE_INTERNAL_DONE_W_NOTIF_REQ,
420 "Internal event 'DONE' alloc failed!");
422 }
423
424 event_group = em_event_group_create();
425 if (unlikely(event_group == EM_EVENT_GROUP_UNDEF)) {
426 em_free(event);
428 EM_ESCOPE_INTERNAL_DONE_W_NOTIF_REQ,
429 "Event group create failed!");
431 }
432
433 i_event = em_event_pointer(event);
434 i_event->id = EM_INTERNAL_DONE;
435 i_event->done.event_group = event_group;
436 i_event->done.f_done_callback = f_done_callback;
437 i_event->done.f_done_arg_ptr = f_done_arg_ptr;
438 i_event->done.num_notif = num_notif;
439
440 for (int i = 0; i < num_notif; i++)
441 i_event->done.notif_tbl[i] = notif_tbl[i];
442
443 i_notif.event = event;
444 if (sync_operation)
445 i_notif.queue = queue_id2hdl(em_shm->queue_tbl.first_internal_queue_id +
446 (uint16_t)odp_thread_id());
447 else
448 i_notif.queue = queue_id2hdl(em_shm->queue_tbl.shared_internal_queue_id);
449
451
452 /*
453 * Request sending of EM_INTERNAL_DONE when 'event_group_count' events
454 * in 'event_group' have been seen. The 'Done' event will trigger the
455 * notifications to be sent.
456 */
457 err = em_event_group_apply(event_group, event_group_count,
458 1, &i_notif);
459 if (unlikely(err != EM_OK)) {
460 INTERNAL_ERROR(err, EM_ESCOPE_INTERNAL_DONE_W_NOTIF_REQ,
461 "Event group apply failed");
462 em_free(event);
463 (void)em_event_group_delete(event_group);
465 }
466
467 return event_group;
468}
469
470/* doc in header file */
471void evgrp_abort_delete(em_event_group_t event_group)
472{
473 em_notif_t free_notif_tbl[EM_EVENT_GROUP_MAX_NOTIF];
474
475 int num = em_event_group_notif(event_group,
477 free_notif_tbl);
478 em_status_t err = em_event_group_abort(event_group);
479
480 if (err == EM_OK && num > 0) {
481 for (int i = 0; i < num; i++)
482 em_free(free_notif_tbl[i].event);
483 }
484 (void)em_event_group_delete(event_group);
485}
486
487/* doc in header file */
488em_status_t send_notifs(const int num_notif, const em_notif_t notif_tbl[])
489{
490 em_status_t err;
491 em_status_t ret = EM_OK;
492
493 for (int i = 0; i < num_notif; i++) {
494 const em_event_t event = notif_tbl[i].event;
495 const em_queue_t queue = notif_tbl[i].queue;
496 const em_event_group_t egrp = notif_tbl[i].egroup;
497
498 /* 'egroup' may be uninit in old appl code, check */
499 if (invalid_egrp(egrp))
500 err = em_send(event, queue);
501 else
502 err = em_send_group(event, queue, egrp);
503
504 if (unlikely(err != EM_OK)) {
505 em_free(event);
506 if (ret == EM_OK)
507 ret = err; /* return the first error */
508 }
509 }
510
511 return ret;
512}
513
514/* doc in header file */
516{
517 if (unlikely(notif == NULL || notif->event == EM_EVENT_UNDEF))
518 return EM_ERR_BAD_POINTER;
519
520 const bool is_external = queue_external(notif->queue);
521
522 if (!is_external) {
523 const queue_elem_t *q_elem = queue_elem_get(notif->queue);
524
525 if (unlikely(q_elem == NULL || !queue_allocated(q_elem)))
526 return EM_ERR_NOT_FOUND;
527 }
528
529 if (notif->egroup != EM_EVENT_GROUP_UNDEF) {
530 const event_group_elem_t *egrp_elem =
531 event_group_elem_get(notif->egroup);
532
533 if (unlikely(egrp_elem == NULL ||
534 !event_group_allocated(egrp_elem)))
535 return EM_ERR_BAD_ID;
536 }
537
538 return EM_OK;
539}
540
541/* doc in header file */
542em_status_t check_notif_tbl(const int num_notif, const em_notif_t notif_tbl[])
543{
544 em_status_t err;
545
546 if (unlikely((unsigned int)num_notif > EM_EVENT_GROUP_MAX_NOTIF))
547 return EM_ERR_TOO_LARGE;
548
549 if (unlikely(num_notif > 0 && notif_tbl == NULL))
550 return EM_ERR_BAD_POINTER;
551
552 for (int i = 0; i < num_notif; i++) {
553 err = check_notif(&notif_tbl[i]);
554 if (unlikely(err != EM_OK))
555 return err;
556 }
557
558 return EM_OK;
559}
560
561/**
562 * @brief Helper for poll_unsched_ctrl_queue()
563 */
564static inline void
565handle_ctrl_events(em_queue_t unsched_queue,
566 const em_event_t ev_tbl[], const int num)
567{
568 em_locm_t *const locm = &em_locm;
569 event_hdr_t *evhdr_tbl[num];
570
571 event_to_hdr_multi(ev_tbl, evhdr_tbl/*out*/, num);
572
573 for (int i = 0; i < num; i++) {
574 /*
575 * Simulate a dispatch-round for the core-local ctrl event.
576 * Dispatch an unscheduled event as scheduled, be careful!
577 * Don't call dispatch enter/exit callbacks here.
578 */
579 em_event_t event = ev_tbl[i];
580 const event_hdr_t *ev_hdr = evhdr_tbl[i];
581 em_event_type_t event_type = ev_hdr->event_type;
582
583 /* Check and set core local event group */
584 event_group_set_local(ev_hdr->egrp, ev_hdr->egrp_gen, 1);
585
586 internal_event_receive(NULL, event, event_type,
587 unsched_queue, NULL);
588
589 /*
590 * Event belongs to an event_group, update the count and
591 * if requested send notifications
592 */
593 event_group_elem_t *const current_egrp_elem = locm->current.egrp_elem;
594
595 if (current_egrp_elem) {
596 /*
597 * Atomically decrease the event group count.
598 * If the new count is zero, send notification events.
599 */
600 event_group_count_decrement(1, current_egrp_elem);
601 locm->current.egrp_elem = NULL;
602 }
603 }
604}
605
606/* doc in header file */
608{
609 em_locm_t *const locm = &em_locm;
610
611 queue_elem_t *thr_unsch_qelem = locm->sync_api.ctrl_poll.thr_unsched_qelem;
612 em_queue_t thr_unsched_queue = locm->sync_api.ctrl_poll.thr_unsched_queue;
613
614 queue_elem_t *shared_unsch_qelem = locm->sync_api.ctrl_poll.shared_unsched_qelem;
615 em_queue_t shared_unsched_queue = locm->sync_api.ctrl_poll.shared_unsched_queue;
616
617 em_locm_current_t current;
618
619 const int deq_max = 16;
620 em_event_t thr_ev_tbl[deq_max];
621 em_event_t shared_ev_tbl[deq_max];
622 int thr_num;
623 int shared_num;
624 int round = 0;
625
626 do {
627 thr_num = queue_dequeue_multi(thr_unsch_qelem,
628 thr_ev_tbl/*out*/, deq_max);
629 shared_num = queue_dequeue_multi(shared_unsch_qelem,
630 shared_ev_tbl/*out*/, deq_max);
631 if (thr_num <= 0 && shared_num <= 0)
632 break; /* no ctrl events, exit loop */
633
634 /* Save local current state the first time only */
635 if (round == 0) {
636 current = locm->current; /* save */
637 locm->current.rcv_multi_cnt = 1;
639 }
640
641 if (thr_num > 0) {
642 locm->current.q_elem = thr_unsch_qelem;
643 locm->current.sched_q_elem = thr_unsch_qelem;
644 handle_ctrl_events(thr_unsched_queue, thr_ev_tbl, thr_num);
645 }
646 if (shared_num > 0) {
647 locm->current.q_elem = shared_unsch_qelem;
648 locm->current.sched_q_elem = shared_unsch_qelem;
649 handle_ctrl_events(shared_unsched_queue, shared_ev_tbl, shared_num);
650 }
651
652 round++;
653 } while (true);
654
655 if (round > 0)
656 locm->current = current; /* restore */
657}
#define INTERNAL_ERROR(error, escope, fmt,...)
Definition em_error.h:58
em_status_t send_ctrl_queue(em_event_t event, em_queue_t queue, em_event_group_t event_group)
em_status_t check_notif(const em_notif_t *const notif)
Check that the usage of a notification is valid.
em_status_t create_ctrl_queue(void)
Create EM's internal unscheduled control queues at startup - one per core.
int send_core_ctrl_events(const odp_thrmask_t *const thr_mask, em_event_t ctrl_event, void(*f_done_callback)(void *arg_ptr), void *f_done_arg_ptr, int num_notif, const em_notif_t notif_tbl[], bool sync_operation)
Sends an internal control event to each thread set in 'mask'.
em_event_group_t internal_done_w_notif_req(int event_group_count, void(*f_done_callback)(void *arg_ptr), void *f_done_arg_ptr, int num_notif, const em_notif_t notif_tbl[], bool sync_operation)
Helper func: Allocate & set up the internal 'done' event with function callbacks and notification eve...
void poll_unsched_ctrl_queue(void)
Poll EM's internal unscheduled control queues during dispatch.
em_status_t delete_ctrl_queues(void)
Delete EM's internal unscheduled control queues at teardown.
em_status_t check_notif_tbl(const int num_notif, const em_notif_t notif_tbl[])
Check that the usage of a table of notifications is valid.
em_status_t create_shared_ctrl_queue(void)
Create EM's internal shared unscheduled control queue at startup.
void evgrp_abort_delete(em_event_group_t event_group)
internal_done_w_notif_req() 'companion' to abort and delete the event group created by the mentioned ...
em_status_t send_notifs(const int num_notif, const em_notif_t notif_tbl[])
Helper func to send notifications events.
ENV_LOCAL em_locm_t em_locm
em_shm_t * em_shm
#define EM_EVENT_GROUP_MAX_NOTIF
#define EM_QUEUE_NAME_LEN
#define EM_POOL_DEFAULT
#define PRI_QUEUE
uint32_t em_event_type_t
#define EM_EVENT_UNDEF
#define EM_EVENT_GROUP_UNDEF
#define PRI_EGRP
#define EM_QUEUE_UNDEF
#define EM_OK
#define EM_FATAL(error)
uint32_t em_status_t
@ EM_ERR_NOT_FOUND
@ EM_ERR_TOO_LARGE
@ EM_ERR_BAD_ID
@ EM_ERR_NOT_FREE
@ EM_ERR_ALLOC_FAILED
@ EM_ERR_BAD_POINTER
em_status_t em_event_group_delete(em_event_group_t event_group)
em_event_group_t em_event_group_create(void)
em_status_t em_event_group_abort(em_event_group_t event_group)
em_status_t em_event_group_apply(em_event_group_t event_group, int count, int num_notif, const em_notif_t notif_tbl[])
em_status_t em_send_group(em_event_t event, em_queue_t queue, em_event_group_t event_group)
int em_event_group_notif(em_event_group_t event_group, int max_notif, em_notif_t notif_tbl[])
em_event_t em_alloc(uint32_t size, em_event_type_t type, em_pool_t pool)
em_status_t em_send(em_event_t event, em_queue_t queue)
void em_free(em_event_t event)
void * em_event_pointer(em_event_t event)
@ EM_EVENT_TYPE_SW
em_event_t em_queue_dequeue(em_queue_t queue)
em_status_t em_queue_delete(em_queue_t queue)
void em_queue_param_init(em_queue_param_t *param)
#define EM_QUEUE_FLAG_DEQ_NOT_MTSAFE
em_queue_t em_queue_find(const char *name)
@ EM_QUEUE_TYPE_UNSCHEDULED
@ EM_SCHED_CONTEXT_TYPE_NONE
queue_elem_t * q_elem
Definition em_mem.h:214
em_sched_context_type_t sched_context_type
Definition em_mem.h:210
int rcv_multi_cnt
Definition em_mem.h:212
event_group_elem_t * egrp_elem
Definition em_mem.h:218
queue_elem_t * sched_q_elem
Definition em_mem.h:216
em_locm_current_t current
Definition em_mem.h:228
sync_api_t sync_api
Definition em_mem.h:286
em_event_group_t egroup
em_queue_flag_t flags
em_event_type_t event_type
em_event_group_t egrp
uint32_t egrp_gen
em_queue_t shared_unsched_queue
em_queue_t thr_unsched_queue
queue_elem_t * thr_unsched_qelem
queue_elem_t * shared_unsched_qelem
struct internal_event_t::@49 done