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