EM-ODP 4.4.0
Event Machine on ODP
Loading...
Searching...
No Matches
event_machine_event.c
1/*
2 * Copyright (c) 2015-2023, 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 <string.h>
42
43#include <odp_api.h>
44
45#include <event_machine.h>
46
47#include "em_chaining.h"
48#include "em_eo.h"
49#include "em_error.h"
50#include "em_event.h"
51#include "em_event_group.h"
53#include "em_event_inline.h"
54#include "em_event_state.h"
55#include "em_event_types.h"
56#include "em_hooks.h"
57#include "em_internal_event.h"
58#include "em_libconfig.h"
59#include "em_mem.h"
60#include "em_pool.h"
61#include "em_pool_inline.h"
62#include "em_pool_types.h"
63#include "em_queue.h"
64#include "em_queue_inline.h"
65#include "em_queue_types.h"
66
67em_event_t em_alloc(uint32_t size, em_event_type_t type, em_pool_t pool)
68{
69 const mpool_elem_t *const pool_elem = pool_elem_get(pool);
70 em_event_type_t major_type = em_event_type_major(type);
71
72 if (EM_CHECK_LEVEL > 0 &&
73 unlikely(size == 0 || !pool_elem || major_type == EM_EVENT_TYPE_TIMER_IND ||
74 major_type == EM_EVENT_TYPE_ODP)) {
75 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_ALLOC,
76 "Invalid args: size:%u type:%u pool:%" PRI_POOL "",
77 size, type, pool);
78 return EM_EVENT_UNDEF;
79 }
80 if (EM_CHECK_LEVEL >= 2 && unlikely(!pool_allocated(pool_elem)))
81 INTERNAL_ERROR(EM_ERR_NOT_CREATED, EM_ESCOPE_ALLOC,
82 "Invalid pool:%" PRI_POOL ", pool not created", pool);
83
84 /*
85 * EM event pools created with type=SW can not support pkt events.
86 */
87 if (EM_CHECK_LEVEL >= 1 &&
88 unlikely(pool_elem->event_type == EM_EVENT_TYPE_SW &&
89 major_type == EM_EVENT_TYPE_PACKET)) {
91 "EM-pool:%s(%" PRI_POOL "):\n"
92 "Invalid event type:0x%x for buf",
93 pool_elem->name, pool_elem->em_pool, type);
94 return EM_EVENT_UNDEF;
95 }
96 if (EM_CHECK_LEVEL >= 1 &&
97 unlikely(pool_elem->event_type == EM_EVENT_TYPE_VECTOR &&
98 major_type != EM_EVENT_TYPE_VECTOR)) {
100 "EM-pool:%s(%" PRI_POOL "):\n"
101 "Invalid event type:0x%x for vector",
102 pool_elem->name, pool_elem->em_pool, type);
103 return EM_EVENT_UNDEF;
104 }
105
106 const em_event_t event = event_alloc(pool_elem, size, type, EVSTATE__ALLOC);
107
108 if (EM_CHECK_LEVEL > 0 && unlikely(event == EM_EVENT_UNDEF)) {
109 em_status_t err =
110 INTERNAL_ERROR(EM_ERR_ALLOC_FAILED, EM_ESCOPE_ALLOC,
111 "EM-pool:'%s': sz:%u type:0x%x pool:%" PRI_POOL "",
112 pool_elem->name, size, type, pool);
113 if (EM_DEBUG_PRINT_BASE && err != EM_OK &&
114 (pool_elem->stats_opt.bit.available ||
115 pool_elem->stats_opt.bit.cache_available)) {
116 em_pool_info_print(pool);
117 }
118 return EM_EVENT_UNDEF;
119 }
120
121 if (EM_API_HOOKS_ENABLE && event != EM_EVENT_UNDEF)
122 call_api_hooks_alloc(&event, 1, 1, size, type, pool);
123
124 return event;
125}
126
127int em_alloc_multi(em_event_t events[/*out*/], int num,
128 uint32_t size, em_event_type_t type, em_pool_t pool)
129{
130 if (unlikely(num == 0))
131 return 0;
132
133 const mpool_elem_t *const pool_elem = pool_elem_get(pool);
134 int ret = 0;
135 em_event_type_t major_type = em_event_type_major(type);
136
137 if (EM_CHECK_LEVEL > 0 &&
138 unlikely(!events || num < 0 || size == 0 || !pool_elem ||
139 major_type == EM_EVENT_TYPE_TIMER_IND || major_type == EM_EVENT_TYPE_ODP)) {
140 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_ALLOC_MULTI,
141 "Invalid args: events:%p num:%d size:%u type:%u pool:%" PRI_POOL "",
142 events, num, size, type, pool);
143 return 0;
144 }
145 if (EM_CHECK_LEVEL >= 2 && unlikely(!pool_allocated(pool_elem)))
146 INTERNAL_ERROR(EM_ERR_BAD_ID, EM_ESCOPE_ALLOC_MULTI,
147 "Invalid pool:%" PRI_POOL ", pool not created", pool);
148
149 if (pool_elem->event_type == EM_EVENT_TYPE_PACKET) {
150 /*
151 * EM event pools created with type=PKT can support SW events
152 * as well as pkt events.
153 */
154 ret = event_alloc_pkt_multi(events, num, pool_elem, size, type);
155 } else if (pool_elem->event_type == EM_EVENT_TYPE_SW) {
156 /*
157 * EM event pools created with type=SW can not support
158 * pkt events.
159 */
160 if (EM_CHECK_LEVEL >= 1 &&
161 unlikely(major_type == EM_EVENT_TYPE_PACKET)) {
162 INTERNAL_ERROR(EM_ERR_NOT_IMPLEMENTED, EM_ESCOPE_ALLOC_MULTI,
163 "EM-pool:%s(%" PRI_POOL "): Invalid event type:0x%x for buf",
164 pool_elem->name, pool, type);
165 return 0;
166 }
167 ret = event_alloc_buf_multi(events, num, pool_elem, size, type);
168 } else if (pool_elem->event_type == EM_EVENT_TYPE_VECTOR) {
169 if (EM_CHECK_LEVEL >= 1 &&
170 unlikely(major_type != EM_EVENT_TYPE_VECTOR)) {
171 INTERNAL_ERROR(EM_ERR_NOT_IMPLEMENTED, EM_ESCOPE_ALLOC,
172 "EM-pool:%s(%" PRI_POOL "): Inv. event type:0x%x for vector",
173 pool_elem->name, pool, type);
174 return 0;
175 }
176 ret = event_alloc_vector_multi(events, num, pool_elem, size, type);
177 }
178
179 if (unlikely(EM_CHECK_LEVEL > 0 && ret != num)) {
180 em_status_t err =
181 INTERNAL_ERROR(EM_ERR_ALLOC_FAILED, EM_ESCOPE_ALLOC_MULTI,
182 "Requested num:%d events, allocated:%d\n"
183 "EM-pool:'%s': sz:%u type:0x%x pool:%" PRI_POOL "",
184 num, ret,
185 pool_elem->name, size, type, pool);
186 if (EM_DEBUG_PRINT_BASE && err != EM_OK &&
187 (pool_elem->stats_opt.bit.available ||
188 pool_elem->stats_opt.bit.cache_available)) {
189 em_pool_info_print(pool);
190 }
191 }
192
193 if (EM_API_HOOKS_ENABLE && ret > 0)
194 call_api_hooks_alloc(events, ret, num, size, type, pool);
195
196 return ret;
197}
198
199/**
200 * @brief Helper to check if the event is a vector
201 *
202 * @param vector_event Event handle
203 * @return true the event is a vector
204 * @return false the event is NOT a vector
205 */
206static inline bool is_vector_type(em_event_t vector_event)
207{
208 odp_event_t odp_event = event_em2odp(vector_event);
209 odp_event_type_t odp_etype = odp_event_type(odp_event);
210
211 if (odp_etype == ODP_EVENT_VECTOR ||
212 odp_etype == ODP_EVENT_PACKET_VECTOR)
213 return true;
214
215 return false;
216}
217
218/**
219 * @brief Helper to check if the event is a vector, if not report an error
220 *
221 * @param vector_event Event handle
222 * @param escope Error scope to use if reporting an error
223 * @return true the event is a vector
224 * @return false the event is NOT a vector, reports an error
225 */
226static inline bool is_vector_type_or_error(em_event_t vector_event,
227 em_escope_t escope)
228{
229 bool is_vec = is_vector_type(vector_event);
230
231 if (likely(is_vec))
232 return true;
233
234 INTERNAL_ERROR(EM_ERR_BAD_TYPE, escope, "Event not a vector");
235 return false;
236}
237
238static inline void
239event_vector_prepare_free_full__odp_evvec(odp_event_vector_t evvec, const uint16_t api_op)
240{
241 em_event_t *ev_tbl = NULL;
242 uint32_t sz = event_vector_tbl__odp_evvec(evvec, &ev_tbl /*out*/);
243
244 if (sz) {
245 event_hdr_t *ev_hdrs[sz];
246
247 /* same as event_to_hdr_multi(), removes gcc-12 LTO error in haswell */
248 for (uint32_t i = 0; i < sz; i++)
249 ev_hdrs[i] = event_to_hdr(ev_tbl[i]);
250
251 evstate_free_multi(ev_tbl, ev_hdrs, sz, api_op);
252
253 /* drop ESV generation from event handles */
254 (void)events_em2odp_inplace(ev_tbl, sz);
255 }
256}
257
258static inline void
259event_vector_prepare_free_full__odp_pktvec(odp_packet_vector_t pkt_vec, const uint16_t api_op)
260{
261 em_event_t *ev_tbl = NULL;
262 uint32_t sz = event_vector_tbl__odp_pktvec(pkt_vec, &ev_tbl /*out*/);
263
264 if (sz) {
265 event_hdr_t *ev_hdrs[sz];
266
267 /* same as event_to_hdr_multi(), removes gcc-12 LTO error in haswell */
268 for (uint32_t i = 0; i < sz; i++)
269 ev_hdrs[i] = event_to_hdr(ev_tbl[i]);
270
271 evstate_free_multi(ev_tbl, ev_hdrs, sz, api_op);
272
273 /* drop ESV generation from event handles */
274 (void)events_em2pkt_inplace(ev_tbl, sz);
275 }
276}
277
278/**
279 * @brief Handle ESV state for 'em_free' for the event-table of a vector event
280 *
281 * @param event Vector event handle
282 */
283static void event_vector_prepare_free_full(em_event_t vector_event, const uint16_t api_op)
284{
285 /* em_free() frees the vector as well as all the events it contains */
286 odp_event_t odp_event = event_em2odp(vector_event);
287 odp_event_type_t odp_etype = odp_event_type(odp_event);
288
289 if (odp_etype == ODP_EVENT_VECTOR) {
290 odp_event_vector_t evvec = odp_event_vector_from_event(odp_event);
291
292 event_vector_prepare_free_full__odp_evvec(evvec, api_op);
293 } else {
294 /* odp_etype == ODP_EVENT_PACKET_VECTOR */
295 odp_packet_vector_t pkt_vec = odp_packet_vector_from_event(odp_event);
296
297 event_vector_prepare_free_full__odp_pktvec(pkt_vec, api_op);
298 }
299}
300
301/**
302 * @brief Handle ESV state for 'em_event_unmark_free/_multi' for the event-table
303 * of a vector event.
304 *
305 * @param event Vector event handle
306 */
307static void event_vector_prepare_free_full__revert(em_event_t event, const uint16_t api_op)
308{
309 /* em_free() frees the vector as well as all the events it contains */
310 em_event_t *ev_tbl;
311 uint32_t sz = event_vector_tbl(event, &ev_tbl);
312
313 if (sz) {
314 event_hdr_t *ev_hdrs[sz];
315
316 event_to_hdr_multi(ev_tbl, ev_hdrs, sz);
317 evstate_unmark_free_multi(ev_tbl, ev_hdrs, sz, api_op);
318
319 /* restore dropped ESV generation to event handles, unmodified in header */
320 for (unsigned int i = 0; i < sz; i++)
321 ev_tbl[i] = ev_hdrs[i]->event;
322 }
323}
324
325/**
326 * Helper to em_free() and em_free_multi() to determine whether timeout events
327 * from periodic timer rings can exist and if free() needs to check for them.
328 * Active tmo events from ring timers must never be freed (user error), only
329 * inactive (last tmo event after cancel) can be freed.
330 */
331static inline bool timer_rings_used(void)
332{
333 return em_shm->timers.num_ring_create_calls > 0 ? true : false;
334}
335
336void em_free(em_event_t event)
337{
338 if (EM_CHECK_LEVEL > 0 && unlikely(event == EM_EVENT_UNDEF)) {
339 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_FREE,
340 "event undefined!");
341 return;
342 }
343
344 odp_event_t odp_event = event_em2odp(event);
345 const bool esv_ena = esv_enabled();
346 /* Is a check for an active periodic tmo event from a timer ring needed? */
347 const bool check_tmos = EM_CHECK_LEVEL >= 2 && timer_rings_used();
348
349 if (unlikely(check_tmos && odp_event_type(odp_event) == ODP_EVENT_TIMEOUT)) {
350 event_hdr_t *ev_hdr = event_to_hdr(event);
351
352 if (unlikely(ev_hdr->flags.tmo_type != EM_TMO_TYPE_NONE)) {
353 INTERNAL_ERROR(EM_ERR_BAD_STATE, EM_ESCOPE_FREE,
354 "Can't free active TIMER event");
355 return;
356 }
357 if (esv_ena)
358 evstate_free(event, ev_hdr, EVSTATE__FREE);
359 } else if (esv_ena) {
360 event_hdr_t *ev_hdr = event_to_hdr(event);
361 /* If event has a hdr, change esv state */
362 if (likely(ev_hdr->event_type != EM_EVENT_TYPE_ODP)) {
363 evstate_free(event, ev_hdr, EVSTATE__FREE);
364 if (is_vector_type(event))
365 event_vector_prepare_free_full(event, EVSTATE__FREE);
366 }
367 }
368
370 call_api_hooks_free(&event, 1);
371
372 odp_event_free(odp_event);
373}
374
375/**
376 * Helper to em_free_multi() to remove active periodic tmo events
377 * (from ring timers) from the free list.
378 *
379 * Active tmo events from ring timers must never be freed (user error), only
380 * inactive (last tmo event after cancel) can be freed. Thus remove the active
381 * ones if the user incorrectly tries to free them.
382 */
383static inline int
384rem_active_ring_timer_tmos(const int num, odp_event_t odp_evtbl[/*in/out*/],
385 event_hdr_t *ev_hdr_tbl[/*in/out*/],
386 em_event_t ev_tbl[/*in/out*/])
387{
388 int first_tmo_idx = -1;
389
390 /* find first active tmo-event */
391 for (int i = 0; i < num; i++) {
392 if (unlikely(odp_event_type(odp_evtbl[i]) == ODP_EVENT_TIMEOUT &&
393 ev_hdr_tbl[i]->flags.tmo_type != EM_TMO_TYPE_NONE)) {
394 first_tmo_idx = i;
395 break;
396 }
397 }
398
399 /*
400 * No active tmo events found - all OK, return.
401 * This is the normal, no-error, scenario.
402 */
403 if (likely(first_tmo_idx == -1))
404 return num;
405
406 /*
407 * Error: Active tmo events found - remove them from the arrays
408 */
409
410 /* last event is tmo, no need to move/copy anything, just drop last */
411 if (first_tmo_idx == num - 1)
412 return num - 1;
413
414 /*
415 * Store indexes of "normal events" (i.e. events other than active
416 * tmo events) to copy from 'first_tmo_idx + 1' onwards.
417 */
418 int num_cpy = 0;
419 int cpy_idx[num - first_tmo_idx - 1];
420
421 for (int i = first_tmo_idx + 1; i < num; i++) {
422 if (likely(!(odp_event_type(odp_evtbl[i]) == ODP_EVENT_TIMEOUT &&
423 ev_hdr_tbl[i]->flags.tmo_type != EM_TMO_TYPE_NONE)))
424 cpy_idx[num_cpy++] = i;
425 }
426
427 /* all further events were active tmo events, drop them */
428 if (num_cpy == 0)
429 return first_tmo_idx;
430
431 /*
432 * Remove all active tmo events from the arrays by copying the "normal"
433 * events into the slots occupied by the active tmo events.
434 */
435 for (int i = 0; i < num_cpy; i++) {
436 int src_idx = cpy_idx[i];
437 int dst_idx = first_tmo_idx + i;
438
439 odp_evtbl[dst_idx] = odp_evtbl[src_idx];
440 ev_hdr_tbl[dst_idx] = ev_hdr_tbl[src_idx];
441 ev_tbl[dst_idx] = ev_tbl[src_idx];
442 }
443
444 return first_tmo_idx + num_cpy;
445}
446
447void em_free_multi(em_event_t events[], int num)
448{
449 if (EM_CHECK_LEVEL > 0 && unlikely(!events || num < 0)) {
450 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_FREE_MULTI,
451 "Inv.args: events[]:%p num:%d", events, num);
452 return;
453 }
454 if (unlikely(num == 0))
455 return;
456
457 if (EM_CHECK_LEVEL >= 3) {
458 int i;
459
460 for (i = 0; i < num && events[i] != EM_EVENT_UNDEF; i++)
461 ;
462 if (unlikely(i != num)) {
463 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_FREE_MULTI,
464 "events[%d] undefined!", i);
465 return;
466 }
467 }
468
469 int num_free = num;
470 const bool esv_ena = esv_enabled();
471 odp_event_t odp_events[num];
472
473 events_em2odp(events, odp_events/*out*/, num);
474
475 /* Is a check for active periodic tmo events from timer rings needed? */
476 const bool check_tmos = EM_CHECK_LEVEL >= 2 && timer_rings_used();
477
478 if (check_tmos || esv_ena) {
479 event_hdr_t *ev_hdrs[num];
480
481 event_to_hdr_multi(events, ev_hdrs, num);
482
483 if (check_tmos) {
484 num_free = rem_active_ring_timer_tmos(num, odp_events, ev_hdrs, events);
485 if (unlikely(num_free != num))
486 INTERNAL_ERROR(EM_ERR_BAD_STATE, EM_ESCOPE_FREE_MULTI,
487 "Can't free active TIMER events: %d of %d ignored",
488 num_free, num);
489 }
490
491 if (esv_ena) {
492 evstate_free_multi(events, ev_hdrs, num_free, EVSTATE__FREE_MULTI);
493
494 for (int i = 0; i < num_free; i++) {
495 if (is_vector_type(events[i]))
496 event_vector_prepare_free_full(events[i],
497 EVSTATE__FREE_MULTI);
498 }
499 }
500 }
501
503 call_api_hooks_free(events, num_free);
504
505 odp_event_free_multi(odp_events, num_free);
506}
507
508/**
509 * Helper to em_send().
510 * Send out of EM via event-chaining and a user-provided function
511 * 'event_send_device()' to another device
512 */
513static inline em_status_t
514send_external(em_event_t event, em_queue_t queue)
515{
517 call_api_hooks_send(&event, 1, queue, EM_EVENT_GROUP_UNDEF);
518
519 em_status_t stat = send_chaining(event, queue);
520
521 if (EM_CHECK_LEVEL == 0)
522 return stat;
523
524 RETURN_ERROR_IF(stat != EM_OK, stat, EM_ESCOPE_SEND,
525 "send out-of-EM via event-chaining failed: Q:%" PRI_QUEUE "", queue);
526 return EM_OK;
527}
528
529/**
530 * Helper to em_send_multi().
531 * Send out of EM via event-chaining and a user-provided function
532 * 'event_send_device()' to another device
533 */
534static inline int
535send_external_multi(const em_event_t events[], int num, em_queue_t queue)
536{
538 call_api_hooks_send(events, num, queue, EM_EVENT_GROUP_UNDEF);
539
540 int num_sent = send_chaining_multi(events, num, queue);
541
542 if (EM_CHECK_LEVEL > 0 && unlikely(num_sent != num)) {
543 INTERNAL_ERROR(EM_ERR_OPERATION_FAILED, EM_ESCOPE_SEND_MULTI,
544 "send_chaining_multi: req:%d, sent:%d",
545 num, num_sent);
546 }
547
548 return num_sent;
549}
550
551/**
552 * Helper to em_send().
553 * Send to an EM internal queue.
554 */
555static inline em_status_t
556send_internal(em_event_t event, event_hdr_t *ev_hdr, em_queue_t queue)
557{
558 queue_elem_t *q_elem = queue_elem_get(queue);
559 em_status_t stat;
560
561 RETURN_ERROR_IF(EM_CHECK_LEVEL > 0 && !q_elem,
562 EM_ERR_BAD_ARG, EM_ESCOPE_SEND,
563 "Invalid queue:%" PRI_QUEUE "", queue);
564 RETURN_ERROR_IF(EM_CHECK_LEVEL >= 2 && !queue_allocated(q_elem),
565 EM_ERR_BAD_STATE, EM_ESCOPE_SEND,
566 "Invalid queue:%" PRI_QUEUE "", queue);
567
568 /* Buffer events sent from EO-start to scheduled queues */
569 if (unlikely(em_locm.start_eo_elem && q_elem->flags.scheduled)) {
570 /*
571 * em_send() called from within an EO-start function:
572 * all events sent to scheduled queues will be buffered
573 * and sent when the EO-start operation completes.
574 */
575 if (esv_enabled())
576 evstate_usr2em(event, ev_hdr, EVSTATE__SEND);
577
578 int num_sent = eo_start_buffer_events(&event, 1, queue);
579
580 if (unlikely(num_sent != 1)) {
582 goto error_return;
583 }
584
585 return EM_OK; /* Success */
586 }
587
589 call_api_hooks_send(&event, 1, queue, EM_EVENT_GROUP_UNDEF);
590
591 if (q_elem->type == EM_QUEUE_TYPE_OUTPUT) {
592 /*
593 * Send out of EM via an EM output-queue and a user provided
594 * function of type em_output_func_t
595 */
596 stat = send_output(event, q_elem);
597
598 if (unlikely(stat != EM_OK))
599 goto error_return_noesv;
600
601 return EM_OK; /* Success */
602 }
603
604 /*
605 * Normal send to a queue on this device
606 */
607 if (esv_enabled())
608 evstate_usr2em(event, ev_hdr, EVSTATE__SEND);
609
610 switch (q_elem->type) {
614 stat = send_sched(event, q_elem);
615 break;
617 stat = queue_unsched_enqueue(event, q_elem);
618 break;
620 stat = send_aggr(event, ev_hdr, q_elem);
621 break;
623 stat = send_local(event, q_elem);
624 break;
625 default:
626 stat = EM_ERR_NOT_FOUND;
627 break;
628 }
629
630 if (likely(stat == EM_OK))
631 return EM_OK; /* Success */
632
633error_return:
634 if (esv_enabled())
635 evstate_usr2em_revert(event, ev_hdr, EVSTATE__SEND__FAIL);
636error_return_noesv:
637 if (EM_CHECK_LEVEL == 0)
638 return stat;
639 stat = INTERNAL_ERROR(stat, EM_ESCOPE_SEND,
640 "send failed: Q:%" PRI_QUEUE " type:%" PRI_QTYPE "",
641 queue, q_elem->type);
642 return stat;
643}
644
645/**
646 * Helper to em_send_multi().
647 * Send to an EM internal queue.
648 */
649static inline int
650send_internal_multi(const em_event_t events[], event_hdr_t *ev_hdrs[],
651 int num, em_queue_t queue)
652{
653 queue_elem_t *q_elem = queue_elem_get(queue);
654 int num_sent;
655
656 if (EM_CHECK_LEVEL > 0 && unlikely(!q_elem)) {
657 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_SEND_MULTI,
658 "Invalid queue:%" PRI_QUEUE "", queue);
659 return 0;
660 }
661 if (EM_CHECK_LEVEL >= 2 && unlikely(!queue_allocated(q_elem))) {
662 INTERNAL_ERROR(EM_ERR_BAD_STATE, EM_ESCOPE_SEND_MULTI,
663 "Invalid queue:%" PRI_QUEUE "", queue);
664 return 0;
665 }
666
667 /* Buffer events sent from EO-start to scheduled queues */
668 if (unlikely(em_locm.start_eo_elem && q_elem->flags.scheduled)) {
669 /*
670 * em_send_multi() called from within an EO-start function:
671 * all events sent to scheduled queues will be buffered
672 * and sent when the EO-start operation completes.
673 */
674 if (esv_enabled())
675 evstate_usr2em_multi(events, ev_hdrs, num,
676 EVSTATE__SEND_MULTI);
677 num_sent = eo_start_buffer_events(events, num, queue);
678
679 if (unlikely(num_sent != num))
680 goto error_return;
681
682 return num_sent; /* Success */
683 }
684
686 call_api_hooks_send(events, num, queue, EM_EVENT_GROUP_UNDEF);
687
688 if (q_elem->type == EM_QUEUE_TYPE_OUTPUT) {
689 /*
690 * Send out of EM via an EM output-queue and a user provided
691 * function of type em_output_func_t
692 */
693 num_sent = send_output_multi(events, num, q_elem);
694
695 if (unlikely(num_sent != num))
696 goto error_return_noesv;
697
698 return num_sent; /* Success */
699 }
700
701 /*
702 * Normal send to a queue on this device
703 */
704 if (esv_enabled())
705 evstate_usr2em_multi(events, ev_hdrs, num, EVSTATE__SEND_MULTI);
706
707 switch (q_elem->type) {
711 num_sent = send_sched_multi(events, num, q_elem);
712 break;
714 num_sent = queue_unsched_enqueue_multi(events, num, q_elem);
715 break;
717 num_sent = send_aggr_multi(events, ev_hdrs, num, q_elem);
718 break;
720 num_sent = send_local_multi(events, num, q_elem);
721 break;
722 default:
723 num_sent = 0;
724 break;
725 }
726
727 if (likely(num_sent == num))
728 return num_sent; /* Success */
729
730error_return:
731 if (esv_enabled())
732 evstate_usr2em_revert_multi(&events[num_sent],
733 &ev_hdrs[num_sent],
734 num - num_sent,
735 EVSTATE__SEND_MULTI__FAIL);
736error_return_noesv:
737 if (EM_CHECK_LEVEL > 0)
738 INTERNAL_ERROR(EM_ERR_LIB_FAILED, EM_ESCOPE_SEND_MULTI,
739 "send-multi failed: req:%d, sent:%d",
740 num, num_sent);
741 return num_sent;
742}
743
744em_status_t em_send(em_event_t event, em_queue_t queue)
745{
746 const bool is_external = queue_external(queue);
747
749 EM_ERR_BAD_ARG, EM_ESCOPE_SEND, "Invalid event");
750
751 event_hdr_t *ev_hdr = event_to_hdr(event);
752
754 EM_ERR_BAD_ARG, EM_ESCOPE_SEND, "Timer-ring event can't be sent");
755
756 /* avoid unnecessary writing 'undef' in case event is a ref */
757 if (ev_hdr->egrp != EM_EVENT_GROUP_UNDEF)
758 ev_hdr->egrp = EM_EVENT_GROUP_UNDEF;
759
760 /*
761 * External queue belongs to another EM instance, send out via EMC/BIP
762 */
763 if (is_external)
764 return send_external(event, queue);
765
766 /*
767 * Queue belongs to this EM instance
768 */
769 return send_internal(event, ev_hdr, queue);
770}
771
772/*
773 * em_send_group_multi() helper: check events
774 */
775static inline em_status_t
776send_multi_check_events(const em_event_t events[], int num)
777{
778 if (EM_CHECK_LEVEL > 0 && unlikely(!events || num <= 0))
779 return EM_ERR_BAD_ARG;
780
781 if (EM_CHECK_LEVEL >= 3) {
782 int i;
783
784 for (i = 0; i < num && events[i] != EM_EVENT_UNDEF; i++)
785 ;
786 if (unlikely(i != num))
787 return EM_ERR_BAD_POINTER;
788 }
789
790 return EM_OK;
791}
792
793int em_send_multi(const em_event_t events[], int num, em_queue_t queue)
794{
795 const bool is_external = queue_external(queue);
796 event_hdr_t *ev_hdrs[num];
797
798 /* Check events */
799 em_status_t err = send_multi_check_events(events, num);
800
801 if (unlikely(err != EM_OK)) {
802 INTERNAL_ERROR(err, EM_ESCOPE_SEND_MULTI,
803 "Invalid events:%p num:%d", events, num);
804 return 0;
805 }
806
807 event_to_hdr_multi(events, ev_hdrs, num);
808
809 for (int i = 0; i < num; i++) {
810 if (EM_CHECK_LEVEL > 0 &&
811 unlikely(ev_hdrs[i]->event_type == EM_EVENT_TYPE_TIMER_IND)) {
812 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_SEND_MULTI,
813 "Timer-ring event[%d] can't be sent", i);
814 return 0;
815 }
816 /* avoid unnecessary writing 'undef' in case event is a ref */
817 if (ev_hdrs[i]->egrp != EM_EVENT_GROUP_UNDEF)
818 ev_hdrs[i]->egrp = EM_EVENT_GROUP_UNDEF;
819 }
820
821 /*
822 * External queue belongs to another EM instance, send out via EMC/BIP
823 */
824 if (is_external)
825 return send_external_multi(events, num, queue);
826
827 /*
828 * Queue belongs to this EM instance
829 */
830 return send_internal_multi(events, ev_hdrs, num, queue);
831}
832
833void *em_event_pointer(em_event_t event)
834{
835 if (EM_CHECK_LEVEL > 0 && unlikely(event == EM_EVENT_UNDEF)) {
836 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_POINTER,
837 "event undefined!");
838 return NULL;
839 }
840
841 void *ev_ptr = event_pointer(event);
842
843 if (EM_CHECK_LEVEL > 0 && unlikely(!ev_ptr))
844 INTERNAL_ERROR(EM_ERR_BAD_POINTER, EM_ESCOPE_EVENT_POINTER,
845 "Event pointer NULL (unsupported event type)");
846
847 return ev_ptr;
848}
849
850void *em_event_pointer_and_size(em_event_t event, uint32_t *size /*out*/)
851{
852 if (EM_CHECK_LEVEL > 0 && unlikely(event == EM_EVENT_UNDEF)) {
853 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_POINTER_AND_SIZE,
854 "event undefined!");
855 return NULL;
856 }
857
858 if (!size) {
859 /* User not interested in 'size',
860 * fall back to em_event_pointer() functionality
861 */
862 void *ev_ptr = event_pointer(event);
863
864 if (EM_CHECK_LEVEL > 0 && unlikely(!ev_ptr))
865 INTERNAL_ERROR(EM_ERR_BAD_POINTER, EM_ESCOPE_EVENT_POINTER_AND_SIZE,
866 "Event pointer NULL (unsupported event type)");
867 return ev_ptr;
868 }
869
870 const odp_event_t odp_event = event_em2odp(event);
871 const odp_event_type_t odp_etype = odp_event_type(odp_event);
872 uint32_t event_size = 0;
873 void *ev_ptr = NULL; /* return value */
874
875 if (odp_etype == ODP_EVENT_PACKET) {
876 const odp_packet_t odp_pkt = odp_packet_from_event(odp_event);
877
878 ev_ptr = odp_packet_data_seg_len(odp_pkt, &event_size);
879 } else if (odp_etype == ODP_EVENT_BUFFER) {
880 const odp_buffer_t odp_buf = odp_buffer_from_event(odp_event);
881 const event_hdr_t *ev_hdr = odp_buffer_user_area(odp_buf);
882 const uint32_t align_offset = ev_hdr->align_offset;
883
884 ev_ptr = odp_buffer_addr(odp_buf);
885 if (align_offset)
886 ev_ptr = (void *)((uintptr_t)ev_ptr + 32 - align_offset);
887 event_size = ev_hdr->event_size;
888 }
889
890 if (EM_CHECK_LEVEL > 0 && unlikely(!ev_ptr)) {
891 INTERNAL_ERROR(EM_ERR_BAD_TYPE, EM_ESCOPE_EVENT_POINTER_AND_SIZE,
892 "Event pointer NULL (odp event type:%u)", odp_etype);
893 /* NULL for unrecognized odp_etype, also for vectors and timer ring tmos */
894 return NULL;
895 }
896
897 *size = event_size;
898 return ev_ptr;
899}
900
901uint32_t em_event_size(em_event_t event)
902{
903 if (unlikely(EM_CHECK_LEVEL > 0 && event == EM_EVENT_UNDEF)) {
904 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_SIZE,
905 "event undefined!");
906 return 0;
907 }
908
909 const odp_event_t odp_event = event_em2odp(event);
910 const odp_event_type_t odp_etype = odp_event_type(odp_event);
911
912 if (odp_etype == ODP_EVENT_PACKET) {
913 odp_packet_t odp_pkt = odp_packet_from_event(odp_event);
914
915 return odp_packet_seg_len(odp_pkt);
916 } else if (odp_etype == ODP_EVENT_BUFFER) {
917 odp_buffer_t odp_buf = odp_buffer_from_event(odp_event);
918 const event_hdr_t *ev_hdr = odp_buffer_user_area(odp_buf);
919
920 return ev_hdr->event_size;
921 } else if (odp_etype == ODP_EVENT_TIMEOUT) {
922 return 0;
923 }
924
925 if (EM_CHECK_LEVEL > 0)
926 INTERNAL_ERROR(EM_ERR_NOT_FOUND, EM_ESCOPE_EVENT_SIZE,
927 "Unexpected odp event type:%u", odp_etype);
928 return 0;
929}
930
931static inline odp_pool_t event_odp_pool(em_event_t event)
932{
933 odp_event_t odp_event = event_em2odp(event);
934
935 return odp_event_pool(odp_event);
936}
937
938em_pool_t em_event_pool(em_event_t event)
939{
940 if (EM_CHECK_LEVEL > 0 && unlikely(event == EM_EVENT_UNDEF)) {
941 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_POOL,
942 "event undefined!");
943 return EM_POOL_UNDEF;
944 }
945
946 odp_pool_t odp_pool = event_odp_pool(event);
947
948 if (unlikely(odp_pool == ODP_POOL_INVALID))
949 return EM_POOL_UNDEF;
950
951 em_pool_t pool = pool_odp2em(odp_pool);
952
953 /*
954 * Don't report an error if 'pool == EM_POOL_UNDEF' since that might
955 * happen if the event is e.g. input from pktio that is using external
956 * (to EM) odp pools.
957 */
958 return pool;
959}
960
961em_pool_t em_event_pool_subpool(em_event_t event, int *subpool /*out*/)
962{
963 if (EM_CHECK_LEVEL > 0 && unlikely(event == EM_EVENT_UNDEF)) {
964 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_POOL_SUBPOOL,
965 "event undefined!");
966 return EM_POOL_UNDEF;
967 }
968
969 odp_pool_t odp_pool = event_odp_pool(event);
970
971 if (unlikely(odp_pool == ODP_POOL_INVALID))
972 return EM_POOL_UNDEF;
973
974 pool_subpool_t pool_subpool = pool_subpool_odp2em(odp_pool);
975
976 if (unlikely(pool_subpool.pool == (uint32_t)(uintptr_t)EM_POOL_UNDEF))
977 return EM_POOL_UNDEF;
978
979 if (subpool)
980 *subpool = pool_subpool.subpool;
981
982 return (em_pool_t)(uintptr_t)pool_subpool.pool;
983}
984
986{
987 if (EM_CHECK_LEVEL > 0)
989 EM_ESCOPE_EVENT_SET_TYPE, "event undefined!");
990
991 /* similar to 'ev_hdr = event_to_hdr(event)', slightly extended: */
992 odp_event_t odp_event = event_em2odp(event);
993 odp_event_type_t evtype = odp_event_type(odp_event);
994 event_hdr_t *ev_hdr;
995
996 switch (evtype) {
997 case ODP_EVENT_PACKET: {
998 odp_packet_t odp_pkt = odp_packet_from_event(odp_event);
999
1000 ev_hdr = odp_packet_user_area(odp_pkt);
1001 break;
1002 }
1003 case ODP_EVENT_BUFFER: {
1004 odp_buffer_t odp_buf = odp_buffer_from_event(odp_event);
1005
1006 ev_hdr = odp_buffer_user_area(odp_buf);
1007 break;
1008 }
1009 case ODP_EVENT_VECTOR: {
1010 odp_event_vector_t odp_evvec = odp_event_vector_from_event(odp_event);
1011
1012 if (EM_CHECK_LEVEL >= 1) {
1013 em_event_type_t new_major = em_event_type_major(newtype);
1014
1016 EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_SET_TYPE,
1017 "Event type:0x%x not suitable for a vector", newtype);
1018 }
1019 ev_hdr = odp_event_vector_user_area(odp_evvec);
1020 break;
1021 }
1022 case ODP_EVENT_PACKET_VECTOR: {
1023 odp_packet_vector_t odp_pktvec = odp_packet_vector_from_event(odp_event);
1024
1025 if (EM_CHECK_LEVEL >= 1) {
1026 em_event_type_t new_major = em_event_type_major(newtype);
1027
1029 EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_SET_TYPE,
1030 "Event type:0x%x not suitable for a vector", newtype);
1031 }
1032 ev_hdr = odp_packet_vector_user_area(odp_pktvec);
1033 break;
1034 }
1035 default:
1036 return INTERNAL_ERROR(EM_ERR_NOT_IMPLEMENTED, EM_ESCOPE_EVENT_SET_TYPE,
1037 "Unsupported odp event type:%u", evtype);
1038 }
1039
1040 ev_hdr->event_type = newtype;
1041
1042 return EM_OK;
1043}
1044
1046{
1047 if (EM_CHECK_LEVEL > 0 && unlikely(event == EM_EVENT_UNDEF)) {
1048 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_TYPE,
1049 "event undefined!");
1050 return EM_EVENT_TYPE_UNDEF;
1051 }
1052
1053 const event_hdr_t *ev_hdr = event_to_hdr(event);
1054
1055 return ev_hdr->event_type;
1056}
1057
1058int em_event_type_multi(const em_event_t events[], int num,
1059 em_event_type_t types[/*out:num*/])
1060{
1061 int i;
1062
1063 /* Check all args */
1064 if (EM_CHECK_LEVEL > 0) {
1065 if (unlikely(!events || num < 0 || !types)) {
1067 EM_ESCOPE_EVENT_TYPE_MULTI,
1068 "Inv.args: events:%p num:%d types:%p",
1069 events, num, types);
1070 return 0;
1071 }
1072 if (unlikely(!num))
1073 return 0;
1074 }
1075
1076 if (EM_CHECK_LEVEL >= 3) {
1077 for (i = 0; i < num && events[i] != EM_EVENT_UNDEF; i++)
1078 ;
1079 if (unlikely(i != num)) {
1081 EM_ESCOPE_EVENT_TYPE_MULTI,
1082 "events[%d] undefined!", i);
1083 return 0;
1084 }
1085 }
1086
1087 event_hdr_t *ev_hdrs[num];
1088
1089 event_to_hdr_multi(events, ev_hdrs, num);
1090
1091 for (i = 0; i < num; i++)
1092 types[i] = ev_hdrs[i]->event_type;
1093
1094 return num;
1095}
1096
1097int em_event_same_type_multi(const em_event_t events[], int num,
1098 em_event_type_t *same_type /*out*/)
1099{
1100 /* Check all args */
1101 if (EM_CHECK_LEVEL > 0) {
1102 if (unlikely(!events || num < 0 || !same_type)) {
1104 EM_ESCOPE_EVENT_SAME_TYPE_MULTI,
1105 "Inv.args: events:%p num:%d same_type:%p",
1106 events, num, same_type);
1107 return 0;
1108 }
1109 if (unlikely(!num))
1110 return 0;
1111 }
1112
1113 if (EM_CHECK_LEVEL >= 3) {
1114 int i;
1115
1116 for (i = 0; i < num && events[i] != EM_EVENT_UNDEF; i++)
1117 ;
1118 if (unlikely(i != num)) {
1120 EM_ESCOPE_EVENT_SAME_TYPE_MULTI,
1121 "events[%d] undefined!", i);
1122 return 0;
1123 }
1124 }
1125
1126 const em_event_type_t type = event_to_hdr(events[0])->event_type;
1127 int same = 1;
1128
1129 for (; same < num && type == event_to_hdr(events[same])->event_type;
1130 same++)
1131 ;
1132
1133 *same_type = type;
1134 return same;
1135}
1136
1137em_status_t em_event_mark_send(em_event_t event, em_queue_t queue)
1138{
1139 if (!esv_enabled())
1140 return EM_OK;
1141
1142 /* Check all args */
1143 if (EM_CHECK_LEVEL > 0)
1145 EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_MARK_SEND,
1146 "Inv.args: event:%" PRI_EVENT "", event);
1147
1148 event_hdr_t *ev_hdr = event_to_hdr(event);
1149 em_event_type_t evtype_major = em_event_type_major(ev_hdr->event_type);
1150
1151 if (unlikely(evtype_major == EM_EVENT_TYPE_ODP))
1152 return EM_OK;
1153
1154 if (EM_CHECK_LEVEL >= 3) {
1155 const queue_elem_t *const q_elem = queue_elem_get(queue);
1156
1157 RETURN_ERROR_IF(!q_elem, EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_MARK_SEND,
1158 "Inv.args: Q:%" PRI_QUEUE "", queue);
1159 RETURN_ERROR_IF(!queue_allocated(q_elem) || !q_elem->flags.scheduled,
1160 EM_ERR_BAD_STATE, EM_ESCOPE_EVENT_MARK_SEND,
1161 "Inv.queue:%" PRI_QUEUE " type:%" PRI_QTYPE "",
1162 queue, q_elem->type);
1163 }
1164
1166 EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_MARK_SEND,
1167 "Event type:%u not allowed", evtype_major);
1168
1169 /* avoid unnecessary writing 'undef' in case event is a ref */
1170 if (ev_hdr->egrp != EM_EVENT_GROUP_UNDEF)
1171 ev_hdr->egrp = EM_EVENT_GROUP_UNDEF;
1172
1173 evstate_usr2em(event, ev_hdr, EVSTATE__MARK_SEND);
1174
1175 /*
1176 * Data memory barrier, we are bypassing em_send(), odp_queue_enq()
1177 * and need to guarantee memory sync before the event ends up into an
1178 * EM queue again.
1179 */
1180 odp_mb_full();
1181
1182 return EM_OK;
1183}
1184
1186{
1187 if (!esv_enabled())
1188 return EM_OK;
1189
1190 /* Check all args */
1191 if (EM_CHECK_LEVEL > 0)
1193 EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_UNMARK_SEND,
1194 "Inv.args: event:%" PRI_EVENT "", event);
1195
1196 event_hdr_t *ev_hdr = event_to_hdr(event);
1197 em_event_type_t evtype_major = em_event_type_major(ev_hdr->event_type);
1198
1199 if (unlikely(evtype_major == EM_EVENT_TYPE_ODP))
1200 return EM_OK;
1201
1203 EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_UNMARK_SEND,
1204 "Event type:%u not allowed", evtype_major);
1205
1206 evstate_unmark_send(event, ev_hdr);
1207
1208 return EM_OK;
1209}
1210
1211void em_event_mark_free(em_event_t event)
1212{
1213 if (!esv_enabled())
1214 return;
1215
1216 if (EM_CHECK_LEVEL > 0 && unlikely(event == EM_EVENT_UNDEF)) {
1217 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_MARK_FREE,
1218 "Event undefined!");
1219 return;
1220 }
1221
1222 event_hdr_t *const ev_hdr = event_to_hdr(event);
1223 em_event_type_t evtype_major = em_event_type_major(ev_hdr->event_type);
1224
1225 if (unlikely(evtype_major == EM_EVENT_TYPE_ODP))
1226 return;
1227
1228 if (EM_CHECK_LEVEL > 0 && unlikely(evtype_major == EM_EVENT_TYPE_TIMER_IND)) {
1229 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_MARK_FREE,
1230 "Timer-ring event not allowed");
1231 return;
1232 }
1233
1234 evstate_free(event, ev_hdr, EVSTATE__MARK_FREE);
1235
1236 if (is_vector_type(event))
1237 event_vector_prepare_free_full(event, EVSTATE__MARK_FREE);
1238}
1239
1240void em_event_unmark_free(em_event_t event)
1241{
1242 if (!esv_enabled())
1243 return;
1244
1245 if (EM_CHECK_LEVEL > 0 && unlikely(event == EM_EVENT_UNDEF)) {
1246 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_UNMARK_FREE,
1247 "Event undefined!");
1248 return;
1249 }
1250
1251 event_hdr_t *const ev_hdr = event_to_hdr(event);
1252 em_event_type_t evtype_major = em_event_type_major(ev_hdr->event_type);
1253
1254 if (unlikely(evtype_major == EM_EVENT_TYPE_ODP))
1255 return;
1256
1257 if (EM_CHECK_LEVEL > 0 && unlikely(evtype_major == EM_EVENT_TYPE_TIMER_IND)) {
1258 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_UNMARK_FREE,
1259 "Timer-ring event not allowed");
1260 return;
1261 }
1262
1263 evstate_unmark_free(event, ev_hdr, EVSTATE__UNMARK_FREE);
1264 if (is_vector_type(event))
1265 event_vector_prepare_free_full__revert(event, EVSTATE__UNMARK_FREE);
1266}
1267
1268void em_event_mark_free_multi(const em_event_t events[], int num)
1269{
1270 if (!esv_enabled())
1271 return;
1272
1273 if (EM_CHECK_LEVEL > 0 && unlikely(!events || num < 0)) {
1274 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_MARK_FREE_MULTI,
1275 "Inv.args: events[]:%p num:%d", events, num);
1276 return;
1277 }
1278 if (unlikely(num == 0))
1279 return;
1280
1281 if (EM_CHECK_LEVEL >= 3) {
1282 int i;
1283
1284 for (i = 0; i < num && events[i] != EM_EVENT_UNDEF; i++)
1285 ;
1286 if (unlikely(i != num)) {
1288 EM_ESCOPE_EVENT_MARK_FREE_MULTI,
1289 "events[%d] undefined!", i);
1290 return;
1291 }
1292 }
1293
1294 event_hdr_t *ev_hdrs[num];
1295
1296 event_to_hdr_multi(events, ev_hdrs, num);
1297
1298 for (int i = 0; i < num; i++) {
1299 em_event_type_t evtype_major = em_event_type_major(ev_hdrs[i]->event_type);
1300
1301 if (unlikely(evtype_major == EM_EVENT_TYPE_ODP))
1302 continue;
1303
1304 if (EM_CHECK_LEVEL > 0 &&
1305 unlikely(evtype_major == EM_EVENT_TYPE_TIMER_IND)) {
1306 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_MARK_FREE_MULTI,
1307 "Timer-ring event[%d] not allowed", i);
1308 continue;
1309 }
1310
1311 evstate_free(events[i], ev_hdrs[i], EVSTATE__MARK_FREE_MULTI);
1312 if (is_vector_type(events[i]))
1313 event_vector_prepare_free_full(events[i], EVSTATE__MARK_FREE_MULTI);
1314 }
1315}
1316
1317void em_event_unmark_free_multi(const em_event_t events[], int num)
1318{
1319 if (!esv_enabled())
1320 return;
1321
1322 if (unlikely(!events || num < 0)) {
1323 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_UNMARK_FREE_MULTI,
1324 "Inv.args: events[]:%p num:%d", events, num);
1325 return;
1326 }
1327 if (unlikely(num == 0))
1328 return;
1329
1330 if (EM_CHECK_LEVEL >= 3) {
1331 int i;
1332
1333 for (i = 0; i < num && events[i] != EM_EVENT_UNDEF; i++)
1334 ;
1335 if (unlikely(i != num)) {
1337 EM_ESCOPE_EVENT_UNMARK_FREE_MULTI,
1338 "events[%d] undefined!", i);
1339 return;
1340 }
1341 }
1342
1343 event_hdr_t *ev_hdrs[num];
1344
1345 event_to_hdr_multi(events, ev_hdrs, num);
1346
1347 for (int i = 0; i < num; i++) {
1348 em_event_type_t evtype_major = em_event_type_major(ev_hdrs[i]->event_type);
1349
1350 if (unlikely(evtype_major == EM_EVENT_TYPE_ODP))
1351 continue;
1352
1353 if (EM_CHECK_LEVEL > 0 &&
1354 unlikely(evtype_major == EM_EVENT_TYPE_TIMER_IND)) {
1355 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_UNMARK_FREE_MULTI,
1356 "Timer-ring event[%d] not allowed", i);
1357 continue;
1358 }
1359
1360 evstate_unmark_free(events[i], ev_hdrs[i], EVSTATE__UNMARK_FREE_MULTI);
1361 if (is_vector_type(events[i]))
1362 event_vector_prepare_free_full__revert(events[i],
1363 EVSTATE__UNMARK_FREE_MULTI);
1364 }
1365}
1366
1367static em_event_t event_clone_part(em_event_t event, em_pool_t pool/*or EM_POOL_UNDEF*/,
1368 uint32_t offset, uint32_t len, bool clone_uarea,
1369 em_escope_t escope)
1370{
1371 const mpool_elem_t *pool_elem = pool_elem_get(pool);
1372 /* use escope to distinguish between em_event_clone() and em_event_clone_part() */
1373 const bool is_clone_part = escope == EM_ESCOPE_EVENT_CLONE_PART ? true : false;
1374
1375 /* Check all args */
1376 if (EM_CHECK_LEVEL > 0 &&
1377 unlikely(event == EM_EVENT_UNDEF ||
1378 (pool != EM_POOL_UNDEF && !pool_elem))) {
1380 "Inv.args: event:%" PRI_EVENT " pool:%" PRI_POOL "",
1381 event, pool);
1382 return EM_EVENT_UNDEF;
1383 }
1384
1385 if (EM_CHECK_LEVEL >= 2 &&
1386 unlikely(pool_elem && !pool_allocated(pool_elem))) {
1388 "Inv.args: pool:%" PRI_POOL " not created", pool);
1389 return EM_EVENT_UNDEF;
1390 }
1391
1392 odp_event_t odp_event = event_em2odp(event);
1393 odp_event_type_t odp_evtype = odp_event_type(odp_event);
1394 odp_pool_t odp_pool = ODP_POOL_INVALID;
1395 odp_packet_t pkt = ODP_PACKET_INVALID;
1396 odp_buffer_t buf = ODP_BUFFER_INVALID;
1397
1398 if (unlikely(odp_evtype != ODP_EVENT_PACKET &&
1399 odp_evtype != ODP_EVENT_BUFFER)) {
1401 "Inv. odp-event-type:%d", odp_evtype);
1402 return EM_EVENT_UNDEF;
1403 }
1404
1405 /* Obtain the event-hdr, event-size and the pool to use */
1406 const event_hdr_t *ev_hdr;
1407 uint32_t size;
1408 em_event_type_t type;
1409 em_pool_t em_pool = pool;
1410 event_hdr_t *clone_hdr;
1411 em_event_t clone_event; /* return value */
1412
1413 if (odp_evtype == ODP_EVENT_PACKET) {
1414 pkt = odp_packet_from_event(odp_event);
1415 ev_hdr = odp_packet_user_area(pkt);
1416 size = odp_packet_seg_len(pkt);
1417 if (pool == EM_POOL_UNDEF) {
1418 odp_pool = odp_packet_pool(pkt);
1419 em_pool = pool_odp2em(odp_pool);
1420 }
1421 } else /* ODP_EVENT_BUFFER */ {
1422 buf = odp_buffer_from_event(odp_event);
1423 ev_hdr = odp_buffer_user_area(buf);
1424 size = ev_hdr->event_size;
1425 if (pool == EM_POOL_UNDEF) {
1426 odp_pool = odp_buffer_pool(buf);
1427 em_pool = pool_odp2em(odp_pool);
1428 }
1429 }
1430
1431 if (is_clone_part) {
1432 if (EM_CHECK_LEVEL >= 1) {
1433 uint64_t offset64 = offset;
1434 uint64_t len64 = len;
1435 uint64_t size64 = size;
1436
1437 if (unlikely(len == 0 || offset64 + len64 > size64)) {
1439 "Inv.args: offset=%u len=%u (0 < offset+len <= %u)",
1440 offset, len, size);
1441 return EM_EVENT_UNDEF;
1442 }
1443 }
1444 if (len < size)
1445 size = len;
1446 }
1447
1448 /* No EM-pool found */
1449 if (em_pool == EM_POOL_UNDEF) {
1450 if (unlikely(odp_evtype == ODP_EVENT_BUFFER)) {
1452 "No suitable event-pool found");
1453 return EM_EVENT_UNDEF;
1454 }
1455 /* odp_evtype == ODP_EVENT_PACKET:
1456 * Not an EM-pool, e.g. event from external pktio odp-pool.
1457 * Allocate and clone pkt via ODP directly.
1458 */
1459 clone_event = pkt_clone_odp(pkt, odp_pool, offset, size,
1460 clone_uarea, is_clone_part);
1461 if (unlikely(clone_event == EM_EVENT_UNDEF)) {
1463 "Cloning from ext odp-pool:%" PRIu64 " failed",
1464 odp_pool_to_u64(odp_pool));
1465 }
1466 return clone_event;
1467 }
1468
1469 /*
1470 * Clone the event from an EM-pool:
1471 */
1472 if (em_pool != pool)
1473 pool_elem = pool_elem_get(em_pool);
1474 type = ev_hdr->event_type;
1475
1476 /* EM event pools created with type=SW can not support pkt events */
1477 if (unlikely(EM_CHECK_LEVEL > 0 &&
1478 pool_elem->event_type == EM_EVENT_TYPE_SW &&
1479 em_event_type_major(type) == EM_EVENT_TYPE_PACKET)) {
1481 "EM-pool:%s(%" PRI_POOL "):\n"
1482 "Invalid event type:0x%x for buf",
1483 pool_elem->name, em_pool, type);
1484 return EM_EVENT_UNDEF;
1485 }
1486
1487 if (EM_CHECK_LEVEL > 0 &&
1488 unlikely(clone_uarea && ev_hdr->user_area.isinit &&
1489 pool_elem->user_area.size < ev_hdr->user_area.size)) {
1491 "EM-pool:%s(%" PRI_POOL "):\n"
1492 "Available user-area too small, clone uarea %u < needed uarea %u",
1493 pool_elem->name, em_pool, pool_elem->user_area.size,
1494 ev_hdr->user_area.size);
1495 return EM_EVENT_UNDEF;
1496 }
1497
1498 if (pool_elem->event_type == EM_EVENT_TYPE_PACKET)
1499 clone_hdr = event_alloc_pkt(pool_elem, size);
1500 else /* EM_EVENT_TYPE_SW */
1501 clone_hdr = event_alloc_buf(pool_elem, size);
1502
1503 if (unlikely(!clone_hdr)) {
1505 "EM-pool:'%s': sz:%u type:0x%x pool:%" PRI_POOL "",
1506 pool_elem->name, size, type, em_pool);
1507 if (EM_DEBUG_PRINT_BASE && err != EM_OK &&
1508 (pool_elem->stats_opt.bit.available ||
1509 pool_elem->stats_opt.bit.cache_available))
1510 em_pool_info_print(em_pool);
1511 return EM_EVENT_UNDEF;
1512 }
1513
1514 /* Update event ESV state for alloc/clone */
1515 if (esv_enabled())
1516 (void)evstate_alloc(clone_hdr->event, clone_hdr, EVSTATE__EVENT_CLONE);
1517
1518 clone_hdr->flags.all = 0; /* clear only after evstate_alloc() */
1519 clone_hdr->event_type = type; /* store the event type */
1520 clone_hdr->event_size = size; /* store requested size */
1521 clone_hdr->egrp = EM_EVENT_GROUP_UNDEF;
1522 clone_hdr->user_area.all = ev_hdr->user_area.all;
1523 clone_hdr->user_area.size = pool_elem->user_area.size; /* uarea size comes from pool */
1524 clone_hdr->user_area.isinit = 1;
1525
1526 /* Copy the event uarea content if used */
1527 if (clone_uarea &&
1528 ev_hdr->user_area.isinit && ev_hdr->user_area.size > 0) {
1529 const void *uarea_ptr = (void *)((uintptr_t)ev_hdr + sizeof(event_hdr_t));
1530 void *clone_uarea_ptr = (void *)((uintptr_t)clone_hdr + sizeof(event_hdr_t));
1531 size_t sz = MIN(pool_elem->user_area.size, ev_hdr->user_area.size);
1532
1533 memcpy(clone_uarea_ptr, uarea_ptr, sz);
1534 }
1535
1536 clone_event = clone_hdr->event;
1537
1538 /* Copy event payload from the parent event into the clone event */
1539 uintptr_t src_addr = (uintptr_t)event_pointer(event) + offset;
1540 const void *src = (void *)src_addr;
1541 void *dst = event_pointer(clone_event);
1542
1543 memcpy(dst, src, size);
1544
1545 /* Call the 'alloc' API hook function also for event-clone */
1546 if (EM_API_HOOKS_ENABLE && clone_event != EM_EVENT_UNDEF)
1547 call_api_hooks_alloc(&clone_event, 1, 1, size, type, pool);
1548
1549 return clone_event;
1550}
1551
1552em_event_t em_event_clone(em_event_t event, em_pool_t pool/*or EM_POOL_UNDEF*/)
1553{
1554 return event_clone_part(event, pool, 0, 0, true, EM_ESCOPE_EVENT_CLONE);
1555}
1556
1557em_event_t em_event_clone_part(em_event_t event, em_pool_t pool/*or EM_POOL_UNDEF*/,
1558 uint32_t offset, uint32_t len, bool clone_uarea)
1559{
1560 return event_clone_part(event, pool, offset, len, clone_uarea,
1561 EM_ESCOPE_EVENT_CLONE_PART);
1562}
1563
1564static inline int
1565event_uarea_init(em_event_t event, event_hdr_t **ev_hdr/*out*/)
1566{
1567 const odp_event_t odp_event = event_em2odp(event);
1568 const odp_event_type_t odp_evtype = odp_event_type(odp_event);
1569 odp_pool_t odp_pool = ODP_POOL_INVALID;
1570 event_hdr_t *hdr;
1571 bool is_init;
1572
1573 switch (odp_evtype) {
1574 case ODP_EVENT_PACKET: {
1575 odp_packet_t odp_pkt = odp_packet_from_event(odp_event);
1576
1577 hdr = odp_packet_user_area(odp_pkt);
1578 is_init = hdr->user_area.isinit;
1579 if (!is_init)
1580 odp_pool = odp_packet_pool(odp_pkt);
1581 break;
1582 }
1583 case ODP_EVENT_BUFFER: {
1584 odp_buffer_t odp_buf = odp_buffer_from_event(odp_event);
1585
1586 hdr = odp_buffer_user_area(odp_buf);
1587 is_init = hdr->user_area.isinit;
1588 if (!is_init)
1589 odp_pool = odp_buffer_pool(odp_buf);
1590 break;
1591 }
1592 case ODP_EVENT_VECTOR: {
1593 odp_event_vector_t odp_evvec = odp_event_vector_from_event(odp_event);
1594
1595 hdr = odp_event_vector_user_area(odp_evvec);
1596 is_init = hdr->user_area.isinit;
1597 if (!is_init)
1598 odp_pool = odp_event_vector_pool(odp_evvec);
1599 break;
1600 }
1601 case ODP_EVENT_PACKET_VECTOR: {
1602 odp_packet_vector_t odp_pktvec = odp_packet_vector_from_event(odp_event);
1603
1604 hdr = odp_packet_vector_user_area(odp_pktvec);
1605 is_init = hdr->user_area.isinit;
1606 if (!is_init)
1607 odp_pool = odp_packet_vector_pool(odp_pktvec);
1608 break;
1609 }
1610 default:
1611 /* Not an EM event */
1612 return -1;
1613 }
1614
1615 *ev_hdr = hdr;
1616
1617 if (!is_init) {
1618 /*
1619 * Event user area metadata is not initialized in
1620 * the event header - initialize it:
1621 */
1622 hdr->user_area.all = 0; /* user_area.{} = all zero (.sizes=0) */
1623 hdr->user_area.isinit = 1;
1624
1625 em_pool_t pool = pool_odp2em(odp_pool);
1626
1627 if (pool == EM_POOL_UNDEF)
1628 return 0; /* ext ODP pool: OK, no user area, sz=0 */
1629
1630 /* Event from an EM event pool, can init event user area */
1631 const mpool_elem_t *pool_elem = pool_elem_get(pool);
1632
1633 if (unlikely(!pool_elem))
1634 return -2; /* invalid pool_elem */
1635
1636 hdr->user_area.size = pool_elem->user_area.size;
1637 }
1638
1639 return 0;
1640}
1641
1642void *em_event_uarea(em_event_t event, size_t *size /*out, if given*/)
1643{
1644 /* Check args */
1645 if (EM_CHECK_LEVEL > 0 && unlikely(event == EM_EVENT_UNDEF)) {
1646 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_UAREA,
1647 "Inv.arg: event undef");
1648 goto no_uarea;
1649 }
1650
1651 event_hdr_t *ev_hdr = NULL;
1652 int err = event_uarea_init(event, &ev_hdr/*out*/);
1653
1654 if (EM_CHECK_LEVEL > 0 && unlikely(err)) {
1655 INTERNAL_ERROR(EM_ERR_OPERATION_FAILED, EM_ESCOPE_EVENT_UAREA,
1656 "Cannot init event user area: %d", err);
1657 goto no_uarea;
1658 }
1659
1660 if (ev_hdr->user_area.size == 0)
1661 goto no_uarea;
1662
1663 /*
1664 * Event has user area configured, return pointer and size
1665 */
1666 void *uarea_ptr = (void *)((uintptr_t)ev_hdr + sizeof(event_hdr_t));
1667
1668 if (size)
1669 *size = ev_hdr->user_area.size;
1670
1671 return uarea_ptr;
1672
1673no_uarea:
1674 if (size)
1675 *size = 0;
1676 return NULL;
1677}
1678
1679em_status_t em_event_uarea_id_set(em_event_t event, uint16_t id)
1680{
1681 /* Check args */
1682 if (EM_CHECK_LEVEL > 0)
1684 EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_UAREA_ID_SET,
1685 "Inv.arg: event undef");
1686
1687 event_hdr_t *ev_hdr = NULL;
1688 int err = event_uarea_init(event, &ev_hdr/*out*/);
1689
1690 if (EM_CHECK_LEVEL > 0)
1692 EM_ESCOPE_EVENT_UAREA_ID_SET,
1693 "Cannot init event user area: %d", err);
1694
1695 ev_hdr->user_area.id = id;
1696 ev_hdr->user_area.isset_id = 1;
1697
1698 return EM_OK;
1699}
1700
1701em_status_t em_event_uarea_id(em_event_t event, bool *isset /*out*/,
1702 uint16_t *id /*out*/)
1703{
1704 bool id_set = false;
1705 em_status_t status = EM_OK;
1706
1707 /* Check args, either 'isset' or 'id' ptrs must be provided (or both) */
1708 if (EM_CHECK_LEVEL > 0 &&
1709 (event == EM_EVENT_UNDEF || !(id || isset))) {
1710 status = INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_UAREA_ID,
1711 "Inv.args: event:%" PRI_EVENT " isset:%p id:%p",
1712 event, isset, id);
1713 goto id_isset;
1714 }
1715
1716 event_hdr_t *ev_hdr = NULL;
1717 int err = event_uarea_init(event, &ev_hdr/*out*/);
1718
1719 if (EM_CHECK_LEVEL > 0 && unlikely(err)) {
1720 status = INTERNAL_ERROR(EM_ERR_OPERATION_FAILED, EM_ESCOPE_EVENT_UAREA_ID,
1721 "Cannot init event user area: %d", err);
1722 goto id_isset;
1723 }
1724
1725 if (ev_hdr->user_area.isset_id) {
1726 /* user-area-id has been set */
1727 id_set = true;
1728 if (id)
1729 *id = ev_hdr->user_area.id; /*out*/
1730 }
1731
1732id_isset:
1733 if (isset)
1734 *isset = id_set; /*out*/
1735 return status;
1736}
1737
1739 em_event_uarea_info_t *uarea_info /*out*/)
1740{
1741 em_status_t status = EM_ERROR;
1742
1743 /* Check args */
1744 if (EM_CHECK_LEVEL > 0 &&
1745 unlikely(event == EM_EVENT_UNDEF || !uarea_info)) {
1746 status = INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_UAREA_INFO,
1747 "Inv.args: event:%" PRI_EVENT " uarea_info:%p",
1748 event, uarea_info);
1749 goto err_uarea;
1750 }
1751
1752 event_hdr_t *ev_hdr = NULL;
1753 int err = event_uarea_init(event, &ev_hdr/*out*/);
1754
1755 if (EM_CHECK_LEVEL > 0 && unlikely(err)) {
1757 EM_ESCOPE_EVENT_UAREA_INFO,
1758 "Cannot init event user area: %d", err);
1759 goto err_uarea;
1760 }
1761
1762 if (ev_hdr->user_area.size == 0) {
1763 uarea_info->uarea = NULL;
1764 uarea_info->size = 0;
1765 } else {
1766 uarea_info->uarea = (void *)((uintptr_t)ev_hdr +
1767 sizeof(event_hdr_t));
1768 uarea_info->size = ev_hdr->user_area.size;
1769 }
1770
1771 if (ev_hdr->user_area.isset_id) {
1772 uarea_info->id.isset = true;
1773 uarea_info->id.value = ev_hdr->user_area.id;
1774 } else {
1775 uarea_info->id.isset = false;
1776 uarea_info->id.value = 0;
1777 }
1778
1779 return EM_OK;
1780
1781err_uarea:
1782 if (uarea_info) {
1783 uarea_info->uarea = NULL;
1784 uarea_info->size = 0;
1785 uarea_info->id.isset = false;
1786 uarea_info->id.value = 0;
1787 }
1788 return status;
1789}
1790
1791em_event_t em_event_ref(em_event_t event)
1792{
1793 /* Check args */
1794 if (unlikely(EM_CHECK_LEVEL > 0 && event == EM_EVENT_UNDEF)) {
1795 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_REF,
1796 "Invalid arg: event:%" PRI_EVENT "", event);
1797 return EM_EVENT_UNDEF;
1798 }
1799
1800 odp_event_t odp_event = event_em2odp(event);
1801 odp_event_type_t odp_etype = odp_event_type(odp_event);
1802
1803 if (EM_CHECK_LEVEL > 0 && unlikely(odp_etype != ODP_EVENT_PACKET)) {
1804 INTERNAL_ERROR(EM_ERR_NOT_IMPLEMENTED, EM_ESCOPE_EVENT_REF,
1805 "Event not a packet! Refs not supported for odp-events of type:%d",
1806 odp_etype);
1807 return EM_EVENT_UNDEF;
1808 }
1809
1810 odp_packet_t odp_pkt = odp_packet_from_event(odp_event);
1811 odp_packet_t pkt_ref = odp_packet_ref_static(odp_pkt);
1812 event_hdr_t *ev_hdr = odp_packet_user_area(odp_pkt);
1813
1814 if (EM_CHECK_LEVEL > 0 && unlikely(pkt_ref == ODP_PACKET_INVALID)) {
1815 INTERNAL_ERROR(EM_ERR_LIB_FAILED, EM_ESCOPE_EVENT_REF,
1816 "ODP failure in odp_packet_ref_static()");
1817 return EM_EVENT_UNDEF;
1818 }
1819
1820 if (unlikely(EM_CHECK_LEVEL >= 2 && odp_pkt != pkt_ref)) {
1821 INTERNAL_ERROR(EM_FATAL(EM_ERR_NOT_IMPLEMENTED), EM_ESCOPE_EVENT_REF,
1822 "EM assumes all refs use the same handle");
1823 odp_packet_free(odp_pkt);
1824 return EM_EVENT_UNDEF;
1825 }
1826
1827 /*
1828 * Indicate that this event has references and some of the ESV checks
1829 * must be omitted (evgen) - 'refs_used' will be set for the whole
1830 * lifetime of this event, i.e. until the event is freed back into the
1831 * pool. Important only for the first call of em_event_ref(), subsequent
1832 * calls write same value.
1833 */
1834 ev_hdr->flags.refs_used = 1;
1835
1836 em_event_t ref = event;
1837
1838 if (esv_enabled())
1839 ref = evstate_ref(event, ev_hdr);
1840
1841 return ref;
1842}
1843
1844bool em_event_has_ref(em_event_t event)
1845{
1846 /* Check args */
1847 if (unlikely(EM_CHECK_LEVEL > 0 && event == EM_EVENT_UNDEF)) {
1848 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_HAS_REF,
1849 "Invalid arg: event:%" PRI_EVENT "", event);
1850 return false;
1851 }
1852
1853 return event_has_ref(event);
1854}
1855
1856void em_event_vector_free(em_event_t vector_event)
1857{
1858 if (EM_CHECK_LEVEL > 0 &&
1859 unlikely(vector_event == EM_EVENT_UNDEF)) {
1860 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_VECTOR_FREE,
1861 "Invalid args: vector_event:%" PRI_EVENT "",
1862 vector_event);
1863 return;
1864 }
1865
1866 if (EM_CHECK_LEVEL > 2 &&
1867 unlikely(!is_vector_type_or_error(vector_event, EM_ESCOPE_EVENT_VECTOR_FREE))) {
1868 return;
1869 }
1870
1872 call_api_hooks_free(&vector_event, 1);
1873
1874 if (esv_enabled()) {
1875 event_hdr_t *const ev_hdr = eventvec_to_hdr(vector_event);
1876
1877 evstate_free(vector_event, ev_hdr, EVSTATE__EVENT_VECTOR_FREE);
1878 }
1879
1880 odp_event_t odp_event = event_em2odp(vector_event);
1881 odp_event_type_t odp_etype = odp_event_type(odp_event);
1882
1883 if (odp_etype == ODP_EVENT_PACKET_VECTOR) {
1884 odp_packet_vector_t pkt_vec = odp_packet_vector_from_event(odp_event);
1885
1886 odp_packet_vector_free(pkt_vec);
1887 } else {
1888 /* odp_etype == ODP_EVENT_VECTOR */
1889 odp_event_vector_t ev_vec = odp_event_vector_from_event(odp_event);
1890
1891 odp_event_vector_free(ev_vec);
1892 }
1893}
1894
1895uint32_t em_event_vector_tbl(em_event_t vector_event,
1896 em_event_t **event_tbl/*out*/)
1897{
1898 if (EM_CHECK_LEVEL > 0 &&
1899 unlikely(vector_event == EM_EVENT_UNDEF || !event_tbl)) {
1900 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_VECTOR_TBL,
1901 "Invalid args: vector_event:%" PRI_EVENT " event_tbl:%p",
1902 vector_event, event_tbl);
1903 return 0;
1904 }
1905
1906 if (EM_CHECK_LEVEL > 2 &&
1907 unlikely(!is_vector_type_or_error(vector_event, EM_ESCOPE_EVENT_VECTOR_TBL))) {
1908 *event_tbl = NULL;
1909 return 0;
1910 }
1911
1912 return event_vector_tbl(vector_event, event_tbl /*out*/);
1913}
1914
1915static em_event_type_t event_vector_type(em_event_t vector_event, em_escope_t escope)
1916{
1917 odp_event_t odp_event = event_em2odp(vector_event);
1918 odp_event_type_t odp_etype = odp_event_type(odp_event);
1919
1920 if (odp_etype == ODP_EVENT_PACKET_VECTOR) {
1921 odp_packet_vector_t odp_pktvec = odp_packet_vector_from_event(odp_event);
1922 const event_hdr_t *ev_hdr = odp_packet_vector_user_area(odp_pktvec);
1923
1924 if (ev_hdr->flags.vectype_set)
1925 return ev_hdr->vector_type;
1926 else
1927 return EM_EVENT_TYPE_PACKET;
1928 } else if (unlikely(odp_etype != ODP_EVENT_VECTOR)) {
1929 /* Not a vector, log error and return */
1931 "Event:%" PRI_EVENT " not a vector", vector_event);
1932 return EM_EVENT_TYPE_UNDEF;
1933 }
1934
1935 /*
1936 * odp_etype == ODP_EVENT_VECTOR:
1937 */
1938 odp_event_vector_t odp_evvec = odp_event_vector_from_event(odp_event);
1939 event_hdr_t *ev_hdr = odp_event_vector_user_area(odp_evvec);
1940
1941 if (ev_hdr->flags.vectype_set)
1942 return ev_hdr->vector_type;
1943
1944 /*
1945 * ev_hdr->flags.vectype_set == 0: determine type from ODP
1946 */
1947 odp_event_type_t odp_vtype = odp_event_vector_type(odp_evvec);
1948 em_event_type_t vector_type;
1949
1950 switch (odp_vtype) {
1951 case ODP_EVENT_PACKET:
1952 vector_type = EM_EVENT_TYPE_PACKET;
1953 break;
1954 case ODP_EVENT_ANY:
1955 vector_type = EM_EVENT_TYPE_ANY;
1956 break;
1957 case ODP_EVENT_BUFFER:
1958 vector_type = EM_EVENT_TYPE_SW;
1959 break;
1960 case ODP_EVENT_TIMEOUT:
1961 vector_type = EM_EVENT_TYPE_TIMER_IND;
1962 break;
1963 case ODP_EVENT_IPSEC_STATUS: /* fallthrough */
1964 case ODP_EVENT_PACKET_TX_COMPL: /* fallthrough */
1965 case ODP_EVENT_DMA_COMPL: /* fallthrough */
1966 case ODP_EVENT_ML_COMPL:
1967 vector_type = EM_EVENT_TYPE_ODP;
1968 break;
1969 default:
1970 /* also ODP_EVENT_VECTOR, ODP_EVENT_PACKET_VECTOR */
1971 (void)INTERNAL_ERROR(EM_ERR_BAD_TYPE, escope,
1972 "Invalid odp event-vector type:%d", odp_vtype);
1973 return EM_EVENT_TYPE_UNDEF;
1974 }
1975
1976 ev_hdr->vector_type = vector_type;
1977 ev_hdr->flags.vectype_set = 1;
1978
1979 return vector_type;
1980}
1981
1983{
1984 if (EM_CHECK_LEVEL > 0 &&
1985 unlikely(vector_event == EM_EVENT_UNDEF)) {
1986 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_VECTOR_TYPE,
1987 "Invalid args: vector_event:%" PRI_EVENT "", vector_event);
1988 return EM_EVENT_TYPE_UNDEF;
1989 }
1990
1991 return event_vector_type(vector_event, EM_ESCOPE_EVENT_VECTOR_TYPE);
1992}
1993
1994em_status_t em_event_vector_type_set(em_event_t vector_event, em_event_type_t vector_type)
1995{
1996 em_event_type_t evtype_major = em_event_type_major(vector_type);
1997
1999 (vector_event == EM_EVENT_UNDEF || vector_type == EM_EVENT_TYPE_UNDEF ||
2000 evtype_major == EM_EVENT_TYPE_VECTOR || evtype_major > EM_EVENT_TYPE_ANY),
2001 EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_VECTOR_TYPE_SET,
2002 "Invalid args: vector_event:%" PRI_EVENT ", vector_type:%u",
2003 vector_event, vector_type);
2004
2005 odp_event_t odp_event = event_em2odp(vector_event);
2006 odp_event_type_t odp_etype = odp_event_type(odp_event);
2007
2008 if (odp_etype == ODP_EVENT_PACKET_VECTOR) {
2009 odp_packet_vector_t odp_pktvec = odp_packet_vector_from_event(odp_event);
2010 event_hdr_t *ev_hdr = odp_packet_vector_user_area(odp_pktvec);
2011
2012 RETURN_ERROR_IF(evtype_major != EM_EVENT_TYPE_PACKET,
2013 EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_VECTOR_TYPE_SET,
2014 "Invalid major event type:%u for packet vector table",
2015 evtype_major);
2016
2017 ev_hdr->vector_type = vector_type;
2018 ev_hdr->flags.vectype_set = 1;
2019
2020 return EM_OK;
2021 }
2022
2023 RETURN_ERROR_IF(odp_etype != ODP_EVENT_VECTOR,
2024 EM_ERR_NOT_SUPPORTED, EM_ESCOPE_EVENT_VECTOR_TYPE_SET,
2025 "Event:%" PRI_EVENT " not a vector", vector_event);
2026
2027 /*
2028 * odp_etype == ODP_EVENT_VECTOR:
2029 */
2030 odp_event_vector_t odp_evvec = odp_event_vector_from_event(odp_event);
2031 event_hdr_t *ev_hdr = odp_event_vector_user_area(odp_evvec);
2032 odp_event_type_t odp_vtype;
2033
2034 switch (evtype_major) {
2036 odp_vtype = ODP_EVENT_PACKET;
2037 break;
2038 case EM_EVENT_TYPE_SW:
2039 odp_vtype = ODP_EVENT_BUFFER;
2040 break;
2042 odp_vtype = ODP_EVENT_TIMEOUT;
2043 break;
2044 case EM_EVENT_TYPE_TIMER: /* fallthrough */
2045 case EM_EVENT_TYPE_CRYPTO: /* fallthrough */
2046 case EM_EVENT_TYPE_ODP: /* fallthrough */
2047 case EM_EVENT_TYPE_ANY:
2048 odp_vtype = ODP_EVENT_ANY;
2049 break;
2050 default:
2051 /* also EM_EVENT_TYPE_VECTOR */
2052 return INTERNAL_ERROR(EM_ERR_BAD_TYPE, EM_ESCOPE_EVENT_VECTOR_TYPE_SET,
2053 "Invalid event vector_type:%u", vector_type);
2054 }
2055
2056 odp_event_vector_type_set(odp_evvec, odp_vtype);
2057 ev_hdr->vector_type = vector_type;
2058 ev_hdr->flags.vectype_set = 1;
2059
2060 return EM_OK;
2061}
2062
2063uint32_t em_event_vector_size(em_event_t vector_event)
2064{
2065 if (EM_CHECK_LEVEL > 0 &&
2066 unlikely(vector_event == EM_EVENT_UNDEF)) {
2067 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_VECTOR_SIZE,
2068 "Invalid arg, vector_event undefined!", vector_event);
2069 return 0;
2070 }
2071
2072 if (EM_CHECK_LEVEL > 2 &&
2073 unlikely(!is_vector_type_or_error(vector_event, EM_ESCOPE_EVENT_VECTOR_SIZE)))
2074 return 0;
2075
2076 odp_event_t odp_event = event_em2odp(vector_event);
2077 odp_event_type_t odp_etype = odp_event_type(odp_event);
2078
2079 if (odp_etype == ODP_EVENT_PACKET_VECTOR) {
2080 odp_packet_vector_t pkt_vec = odp_packet_vector_from_event(odp_event);
2081
2082 return odp_packet_vector_size(pkt_vec);
2083 }
2084
2085 /* odp_etype == ODP_EVENT_VECTOR */
2086 odp_event_vector_t ev_vec = odp_event_vector_from_event(odp_event);
2087
2088 return odp_event_vector_size(ev_vec);
2089}
2090
2091void em_event_vector_size_set(em_event_t vector_event, uint32_t size)
2092{
2093 if (EM_CHECK_LEVEL > 0 &&
2094 unlikely(vector_event == EM_EVENT_UNDEF)) {
2095 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_VECTOR_SIZE_SET,
2096 "Invalid arg, vector_event undefined!", vector_event);
2097 return;
2098 }
2099
2100 if (EM_CHECK_LEVEL > 2) {
2101 bool is_vec = is_vector_type_or_error(vector_event,
2102 EM_ESCOPE_EVENT_VECTOR_SIZE_SET);
2103 if (unlikely(!is_vec))
2104 return;
2105
2106 uint32_t max_size = 0;
2107 em_status_t err = event_vector_max_size(vector_event, &max_size,
2108 EM_ESCOPE_EVENT_VECTOR_SIZE_SET);
2109 if (unlikely(err != EM_OK ||
2110 /* 'max_size=0 && EM_OK' is not error: odp pool used */
2111 (size > max_size && max_size > 0))) {
2112 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_VECTOR_SIZE_SET,
2113 "Invalid arg, given size:%u > max_size:%u", size, max_size);
2114 return;
2115 }
2116 }
2117
2118 odp_event_t odp_event = event_em2odp(vector_event);
2119 odp_event_type_t odp_etype = odp_event_type(odp_event);
2120
2121 if (odp_etype == ODP_EVENT_PACKET_VECTOR) {
2122 odp_packet_vector_t pkt_vec = odp_packet_vector_from_event(odp_event);
2123
2124 odp_packet_vector_size_set(pkt_vec, size);
2125 } else {
2126 /* odp_etype == ODP_EVENT_VECTOR */
2127 odp_event_vector_t ev_vec = odp_event_vector_from_event(odp_event);
2128
2129 odp_event_vector_size_set(ev_vec, size);
2130 }
2131}
2132
2133uint32_t em_event_vector_max_size(em_event_t vector_event)
2134{
2135 if (EM_CHECK_LEVEL > 0 &&
2136 unlikely(vector_event == EM_EVENT_UNDEF)) {
2137 INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_VECTOR_MAX_SIZE,
2138 "Invalid arg, vector_event undefined!", vector_event);
2139 return 0;
2140 }
2141
2142 if (EM_CHECK_LEVEL > 2 &&
2143 unlikely(!is_vector_type_or_error(vector_event, EM_ESCOPE_EVENT_VECTOR_MAX_SIZE)))
2144 return 0;
2145
2146 uint32_t max_size = 0;
2147 em_status_t err = event_vector_max_size(vector_event, &max_size,
2148 EM_ESCOPE_EVENT_VECTOR_MAX_SIZE);
2149 if (unlikely(err != EM_OK))
2150 return 0;
2151
2152 return max_size;
2153}
2154
2155em_status_t em_event_vector_info(em_event_t vector_event,
2156 em_event_vector_info_t *vector_info /*out*/)
2157{
2158 em_status_t status = EM_ERROR;
2159
2160 /* Check args */
2161 if (EM_CHECK_LEVEL > 0 &&
2162 unlikely(vector_event == EM_EVENT_UNDEF || !vector_info)) {
2163 status = INTERNAL_ERROR(EM_ERR_BAD_ARG, EM_ESCOPE_EVENT_VECTOR_INFO,
2164 "Invalid args: vector_event:%" PRI_EVENT " vector_info:%p",
2165 vector_event, vector_info);
2166 goto err_vecinfo;
2167 }
2168
2169 if (EM_CHECK_LEVEL > 2 &&
2170 unlikely(!is_vector_type_or_error(vector_event, EM_ESCOPE_EVENT_VECTOR_INFO))) {
2171 status = EM_ERR_BAD_TYPE;
2172 goto err_vecinfo;
2173 }
2174
2175 /* Get the event type of events stored in the vector's event-table */
2176 vector_info->event_type = event_vector_type(vector_event, EM_ESCOPE_EVENT_VECTOR_INFO);
2177
2178 /* Get the max size */
2179 status = event_vector_max_size(vector_event, &vector_info->max_size,
2180 EM_ESCOPE_EVENT_VECTOR_INFO);
2181 if (unlikely(status != EM_OK))
2182 goto err_vecinfo;
2183
2184 /* Get vector size and the event-table */
2185 vector_info->size = event_vector_tbl(vector_event, &vector_info->event_tbl/*out*/);
2186
2187 return EM_OK;
2188
2189err_vecinfo:
2190 if (vector_info) {
2191 vector_info->event_type = EM_EVENT_TYPE_UNDEF;
2192 vector_info->event_tbl = NULL;
2193 vector_info->size = 0;
2194 vector_info->max_size = 0;
2195 }
2196 return status;
2197}
2198
2199uint64_t em_event_to_u64(em_event_t event)
2200{
2201 return (uint64_t)event;
2202}
#define INTERNAL_ERROR(error, escope, fmt,...)
Definition em_error.h:58
#define RETURN_ERROR_IF(cond, error, escope, fmt,...)
Definition em_error.h:65
struct event_hdr event_hdr_t
ENV_LOCAL em_locm_t em_locm
em_shm_t * em_shm
#define EM_CHECK_LEVEL
#define EM_DEBUG_PRINT_BASE
#define EM_API_HOOKS_ENABLE
#define PRI_QUEUE
uint32_t em_event_type_t
#define PRI_POOL
#define EM_POOL_UNDEF
#define EM_EVENT_UNDEF
#define EM_EVENT_GROUP_UNDEF
#define PRI_EVENT
#define EM_OK
uint32_t em_escope_t
#define EM_ERROR
#define EM_FATAL(error)
uint32_t em_status_t
@ EM_ERR_NOT_FOUND
@ EM_ERR_OPERATION_FAILED
@ EM_ERR_BAD_ID
@ EM_ERR_NOT_CREATED
@ EM_ERR_TOO_SMALL
@ EM_ERR_ALLOC_FAILED
@ EM_ERR_BAD_ARG
@ EM_ERR_NOT_IMPLEMENTED
@ EM_ERR_NOT_SUPPORTED
@ EM_ERR_BAD_STATE
@ EM_ERR_BAD_TYPE
@ EM_ERR_LIB_FAILED
@ EM_ERR_BAD_POINTER
em_event_t em_event_ref(em_event_t event)
bool em_event_has_ref(em_event_t event)
em_status_t em_event_uarea_id(em_event_t event, bool *isset, uint16_t *id)
Get the event user area ID along with information if it has been set.
em_status_t em_event_uarea_id_set(em_event_t event, uint16_t id)
Set the event user area ID.
em_status_t em_event_uarea_info(em_event_t event, em_event_uarea_info_t *uarea_info)
Get the event user area information for a given event.
void * em_event_uarea(em_event_t event, size_t *size)
Get a pointer to the event user area, optionally along with its size.
uint32_t em_event_vector_tbl(em_event_t vector_event, em_event_t **event_tbl)
Get the event vector table from an event of (major) type EM_EVENT_TYPE_VECTOR.
uint32_t em_event_vector_max_size(em_event_t vector_event)
Maximum number of event handles that can be stored in a vector.
em_status_t em_event_vector_type_set(em_event_t vector_event, em_event_type_t vector_type)
em_status_t em_event_vector_info(em_event_t vector_event, em_event_vector_info_t *vector_info)
Retrieve information about the given vector event.
void em_event_vector_free(em_event_t vector_event)
Free the vector event only, not the events it contains.
uint32_t em_event_vector_size(em_event_t vector_event)
Number of event handles available (set) in a vector.
void em_event_vector_size_set(em_event_t vector_event, uint32_t size)
Set the number of event handles stored in a vector.
em_event_type_t em_event_vector_type(em_event_t vector_event)
em_event_t em_event_clone(em_event_t event, em_pool_t pool)
Clone an event.
int em_event_same_type_multi(const em_event_t events[], int num, em_event_type_t *same_type)
void * em_event_pointer_and_size(em_event_t event, uint32_t *size)
Get a pointer to the event structure/data as well as the event size.
em_event_type_t em_event_type(em_event_t event)
uint32_t em_event_size(em_event_t event)
int em_send_multi(const em_event_t events[], int num, em_queue_t queue)
int em_alloc_multi(em_event_t events[], int num, uint32_t size, em_event_type_t type, em_pool_t pool)
void em_event_mark_free(em_event_t event)
Mark the event as "free".
em_status_t em_event_unmark_send(em_event_t event)
em_event_t em_alloc(uint32_t size, em_event_type_t type, em_pool_t pool)
void em_event_unmark_free(em_event_t event)
Unmark an event previously marked as "free" (i.e mark as "allocated" again).
void em_event_mark_free_multi(const em_event_t events[], int num)
Mark multiple events as "free".
void em_event_unmark_free_multi(const em_event_t events[], int num)
Unmark multiple events previously marked as "free".
em_status_t em_event_mark_send(em_event_t event, em_queue_t queue)
void em_free_multi(em_event_t events[], int num)
em_pool_t em_event_pool(em_event_t event)
Returns the EM event-pool the event was allocated from.
em_status_t em_event_set_type(em_event_t event, em_event_type_t newtype)
int em_event_type_multi(const em_event_t events[], int num, em_event_type_t types[])
em_event_t em_event_clone_part(em_event_t event, em_pool_t pool, uint32_t offset, uint32_t len, bool clone_uarea)
Partially clone an event.
em_pool_t em_event_pool_subpool(em_event_t event, int *subpool)
Returns the EM event-pool and subpool the event was allocated from.
uint64_t em_event_to_u64(em_event_t event)
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_TYPE_UNDEF
@ EM_EVENT_TYPE_ODP
@ EM_EVENT_TYPE_PACKET
@ EM_EVENT_TYPE_TIMER_IND
@ EM_EVENT_TYPE_ANY
@ EM_EVENT_TYPE_TIMER
@ EM_EVENT_TYPE_CRYPTO
@ EM_EVENT_TYPE_VECTOR
void em_pool_info_print(em_pool_t pool)
#define PRI_QTYPE
@ EM_QUEUE_TYPE_AGGR
@ EM_QUEUE_TYPE_ORDERED
@ EM_QUEUE_TYPE_ATOMIC
@ EM_QUEUE_TYPE_UNSCHEDULED
@ EM_QUEUE_TYPE_PARALLEL
@ EM_QUEUE_TYPE_LOCAL
@ EM_QUEUE_TYPE_OUTPUT
Event user area information filled by em_event_uarea_info()
struct em_event_uarea_info_t::@1 id
Vector event information filled by em_event_vector_info()
eo_elem_t * start_eo_elem
Definition em_mem.h:275
uint8_t refs_used
em_event_t event
uint8_t align_offset
uint8_t tmo_type
ev_hdr_user_area_t user_area
uint8_t vectype_set
union event_hdr::@43 flags
uint32_t event_size
em_event_type_t event_type
em_event_group_t egrp
em_event_type_t vector_type
struct mpool_elem_t::@54 user_area
odp_pool_stats_opt_t stats_opt
em_pool_t em_pool
uint16_t size
em_event_type_t event_type
queue_elem_flags_t flags