11#ifndef EM_DISPATCHER_INLINE_H_
12#define EM_DISPATCHER_INLINE_H_
52#define DISPATCH_MULTI_MAX_BURST \
53 MAX(EM_SCHED_MULTI_MAX_BURST, EM_SCHED_AG_MULTI_MAX_BURST)
56dispatch_eo_multircv_single(em_event_t event,
event_hdr_t *ev_hdr,
59dispatch_eo_multircv_burst(em_event_t ev_tbl[],
event_hdr_t *ev_hdr_tbl[],
61 const bool check_local_qs);
63dispatch_eo_rcv_single(em_event_t event,
event_hdr_t *ev_hdr,
66dispatch_eo_rcv_burst(em_event_t ev_tbl[],
event_hdr_t *ev_hdr_tbl[],
68 const bool check_local_qs);
73static inline int pack_ev_tbl(em_event_t ev_tbl[],
const int num)
84 for (
int i = 0; i < num; i++) {
87 ev_tbl[pack] = ev_tbl[i];
95static inline uint64_t debug_timestamp(
void)
118dispatch_enter_cb(em_eo_t eo,
void **eo_ctx,
119 em_event_t ev_tbl[],
const int num_events,
120 em_queue_t *queue,
void **q_ctx)
124 int num = num_events;
126 for (
int i = 0; i < EM_CALLBACKS_MAX && num > 0; i++) {
127 dispatch_enter_fn = cb_tbl->tbl[i].disp_enter;
128 if (dispatch_enter_fn == NULL)
130 dispatch_enter_fn(eo, eo_ctx, ev_tbl, num, queue, q_ctx);
131 num = pack_ev_tbl(ev_tbl, num);
143dispatch_exit_cb(em_eo_t eo)
149 dispatch_exit_fn = dispatch_exit_cb_tbl->tbl[i].disp_exit;
150 if (dispatch_exit_fn == NULL)
152 dispatch_exit_fn(eo);
163dispatch_callbacks_registered(
void)
165 return EM_DISPATCH_CALLBACKS_ENABLE &&
166 (
em_shm->dispatch_enter_cb_tbl->tbl[0].disp_enter != NULL ||
175 em_queue_t queue = (em_queue_t)(uintptr_t)q_elem->
queue;
176 void *queue_ctx = q_elem->
context;
177 void *eo_ctx = q_elem->
eo_ctx;
182 event_group_set_local(ev_hdr->
egrp, ev_hdr->
egrp_gen, 1);
184 if (EM_DISPATCH_CALLBACKS_ENABLE) {
185 em_event_t ev_tbl[1] = {
event};
187 num = dispatch_enter_cb(eo, &eo_ctx, ev_tbl, 1,
189 if (num && ev_tbl[0] != event) {
192 ev_hdr = event_to_hdr(event);
196 if (likely(num == 1)) {
202 eo_receive_func(eo_ctx, event, event_type,
206 if (EM_DISPATCH_CALLBACKS_ENABLE)
207 dispatch_exit_cb(eo);
215 if (current_egrp_elem) {
220 event_group_count_decrement(1, current_egrp_elem);
242 const em_queue_t queue,
void *
const queue_ctx,
248 event_group_set_local(ev_hdr->
egrp, ev_hdr->
egrp_gen, 1);
250 eo_receive_func(eo_ctx, event, ev_hdr->
event_type,
255 if (current_egrp_elem) {
256 event_group_count_decrement(1, current_egrp_elem);
266call_eo_multircv_fn(
const em_eo_t eo,
272 em_queue_t queue = (em_queue_t)(uintptr_t)q_elem->
queue;
273 void *queue_ctx = q_elem->
context;
274 void *eo_ctx = q_elem->
eo_ctx;
275 int num = num_events;
279 event_group_set_local(ev_hdr_tbl[0]->egrp, ev_hdr_tbl[0]->egrp_gen,
282 if (EM_DISPATCH_CALLBACKS_ENABLE)
283 num = dispatch_enter_cb(eo, &eo_ctx,
286 if (likely(num > 0)) {
291 eo_receive_multi_func(eo_ctx, ev_tbl, num, queue, queue_ctx);
294 if (EM_DISPATCH_CALLBACKS_ENABLE)
295 dispatch_exit_cb(eo);
303 if (current_egrp_elem) {
308 event_group_count_decrement(num_events, current_egrp_elem);
330 const int num_events,
331 const em_queue_t queue,
void *
const queue_ctx,
337 event_group_set_local(ev_hdr_tbl[0]->egrp, ev_hdr_tbl[0]->egrp_gen,
340 eo_receive_multi_func(eo_ctx, ev_tbl, num_events, queue, queue_ctx);
344 if (current_egrp_elem) {
345 event_group_count_decrement(num_events, current_egrp_elem);
357 odp_event_t odp_event;
362 const int qidx = entry.qidx;
363 const em_queue_t queue = queue_idx2hdl(qidx);
368 odp_event = (odp_event_t)(uintptr_t)entry.evptr;
370 event = event_init_odp(odp_event,
true, q_elem, &ev_hdr);
376 "EM info: %s(): localQ:%" PRI_QUEUE ":\n"
377 "Not ready - state:%d drop:1 event\n",
378 __func__, queue, q_elem ? q_elem->
state : 0);
383 dispatch_eo_multircv_single(event, ev_hdr, q_elem,
false);
385 dispatch_eo_rcv_single(event, ev_hdr, q_elem,
false);
392dispatch_local_burst(
const stash_entry_t entry_tbl[],
const int num)
403 for (
int i = 0; i < num; i++)
404 odp_evtbl[i] = (odp_event_t)(uintptr_t)entry_tbl[i].evptr;
409 const int qidx = entry_tbl[idx].qidx;
410 const em_queue_t queue = queue_idx2hdl(qidx);
420 for (i = idx + 1; i < num && entry_tbl[i].qidx == qidx; i++)
426 event_init_odp_multi(&odp_evtbl[idx], ev_tbl, evhdr_tbl,
427 ev_cnt,
true, q_elem);
433 "EM info: %s(): localQ:%" PRI_QUEUE ":\n"
434 "Not ready - state:%d drop:%d events\n",
435 __func__, queue, q_elem ? q_elem->
state : 0, ev_cnt);
441 dispatch_eo_multircv_burst(ev_tbl, evhdr_tbl, ev_cnt, q_elem,
false);
443 dispatch_eo_rcv_burst(ev_tbl, evhdr_tbl, ev_cnt, q_elem,
false);
450dispatch_local_queues(
const stash_entry_t entry_tbl[],
const int num)
453 dispatch_local_single(entry_tbl[0]);
455 dispatch_local_burst(entry_tbl, num);
459check_local_queues(
void)
475 locm->
debug_ts[EM_DEBUG_TSP_SCHED_ENTRY] = debug_timestamp();
477 int num = next_local_queue_events(entry_tbl ,
480 locm->
debug_ts[EM_DEBUG_TSP_SCHED_RETURN] = debug_timestamp();
486 dispatch_local_queues(entry_tbl, num);
497count_same_evgroup(
event_hdr_t *ev_hdr_tbl[],
const unsigned int num)
499 if (unlikely(num < 2))
502 const em_event_group_t egrp = ev_hdr_tbl[0]->
egrp;
510 const uint32_t egrp_gen = ev_hdr_tbl[0]->
egrp_gen;
513 egrp == ev_hdr_tbl[i]->
egrp &&
514 egrp_gen == ev_hdr_tbl[i]->
egrp_gen; i++)
532dispatch_eo_multircv_single(em_event_t event,
event_hdr_t *ev_hdr,
535 const em_eo_t eo = (em_eo_t)(uintptr_t)q_elem->
eo;
538 if (dispatch_callbacks_registered()) {
544 if (check_local_qs) {
548 call_eo_multircv_fn(eo, eo_rcv_multi_fn,
549 &event, &ev_hdr, 1, q_elem);
550 check_local_queues();
552 call_eo_multircv_fn(eo, eo_rcv_multi_fn,
553 &event, &ev_hdr, 1, q_elem);
562 const em_queue_t queue = (em_queue_t)(uintptr_t)q_elem->
queue;
563 void *
const queue_ctx = q_elem->
context;
564 void *
const eo_ctx = q_elem->
eo_ctx;
566 if (check_local_qs) {
570 call_eo_multircv_fn__no_cb(eo_rcv_multi_fn, &event, &ev_hdr, 1,
571 queue, queue_ctx, eo_ctx);
572 check_local_queues();
574 call_eo_multircv_fn__no_cb(eo_rcv_multi_fn, &event, &ev_hdr, 1,
575 queue, queue_ctx, eo_ctx);
589dispatch_eo_multircv_burst(em_event_t ev_tbl[],
event_hdr_t *ev_hdr_tbl[],
591 const bool check_local_qs)
594 const em_eo_t eo = (em_eo_t)(uintptr_t)q_elem->
eo;
599 if (dispatch_callbacks_registered()) {
608 const int egrp_cnt = count_same_evgroup(&ev_hdr_tbl[idx],
616 const int egrp_end = MIN(idx + egrp_cnt, num_events);
618 const int num = MIN(egrp_cnt, max);
620 if (check_local_qs) {
624 while (egrp_end - j >= num) {
626 call_eo_multircv_fn(eo, eo_rcv_multi_fn,
627 &ev_tbl[j], &ev_hdr_tbl[j],
629 check_local_queues();
635 call_eo_multircv_fn(eo, eo_rcv_multi_fn,
636 &ev_tbl[j], &ev_hdr_tbl[j],
637 egrp_end - j, q_elem);
638 check_local_queues();
643 while (egrp_end - j >= num) {
644 call_eo_multircv_fn(eo, eo_rcv_multi_fn,
645 &ev_tbl[j], &ev_hdr_tbl[j],
650 call_eo_multircv_fn(eo, eo_rcv_multi_fn,
651 &ev_tbl[j], &ev_hdr_tbl[j],
652 egrp_end - j, q_elem);
657 }
while (idx < num_events);
667 const em_queue_t queue = (em_queue_t)(uintptr_t)q_elem->
queue;
668 void *
const queue_ctx = q_elem->
context;
669 void *
const eo_ctx = q_elem->
eo_ctx;
672 const int egrp_cnt = count_same_evgroup(&ev_hdr_tbl[idx],
675 const int egrp_end = MIN(idx + egrp_cnt, num_events);
677 const int num = MIN(egrp_cnt, max);
679 if (check_local_qs) {
683 while (egrp_end - j >= num) {
685 call_eo_multircv_fn__no_cb(eo_rcv_multi_fn,
686 &ev_tbl[j], &ev_hdr_tbl[j],
688 queue, queue_ctx, eo_ctx);
689 check_local_queues();
695 call_eo_multircv_fn__no_cb(eo_rcv_multi_fn,
696 &ev_tbl[j], &ev_hdr_tbl[j],
698 queue, queue_ctx, eo_ctx);
699 check_local_queues();
704 while (egrp_end - j >= num) {
705 call_eo_multircv_fn__no_cb(eo_rcv_multi_fn,
706 &ev_tbl[j], &ev_hdr_tbl[j],
708 queue, queue_ctx, eo_ctx);
712 call_eo_multircv_fn__no_cb(eo_rcv_multi_fn,
713 &ev_tbl[j], &ev_hdr_tbl[j],
715 queue, queue_ctx, eo_ctx);
720 }
while (idx < num_events);
734dispatch_eo_rcv_single(em_event_t event,
event_hdr_t *ev_hdr,
737 const em_eo_t eo = (em_eo_t)(uintptr_t)q_elem->
eo;
740 if (dispatch_callbacks_registered()) {
746 if (check_local_qs) {
750 call_eo_rcv_fn(eo, eo_rcv_fn, event, ev_hdr, q_elem);
751 check_local_queues();
753 call_eo_rcv_fn(eo, eo_rcv_fn, event, ev_hdr, q_elem);
762 const em_queue_t queue = (em_queue_t)(uintptr_t)q_elem->
queue;
763 void *
const queue_ctx = q_elem->
context;
764 void *
const eo_ctx = q_elem->
eo_ctx;
766 if (check_local_qs) {
770 call_eo_rcv_fn__no_cb(eo_rcv_fn, event, ev_hdr,
771 queue, queue_ctx, eo_ctx);
772 check_local_queues();
774 call_eo_rcv_fn__no_cb(eo_rcv_fn, event, ev_hdr,
775 queue, queue_ctx, eo_ctx);
789dispatch_eo_rcv_burst(em_event_t ev_tbl[],
event_hdr_t *ev_hdr_tbl[],
791 const bool check_local_qs)
794 const em_eo_t eo = (em_eo_t)(uintptr_t)q_elem->
eo;
797 if (dispatch_callbacks_registered()) {
803 if (check_local_qs) {
804 for (
int i = 0; i < num_events; i++) {
806 call_eo_rcv_fn(eo, eo_rcv_fn,
807 ev_tbl[i], ev_hdr_tbl[i],
809 check_local_queues();
812 for (
int i = 0; i < num_events; i++)
813 call_eo_rcv_fn(eo, eo_rcv_fn,
814 ev_tbl[i], ev_hdr_tbl[i],
826 const em_queue_t queue = (em_queue_t)(uintptr_t)q_elem->
queue;
827 void *
const queue_ctx = q_elem->
context;
828 void *
const eo_ctx = q_elem->
eo_ctx;
830 if (check_local_qs) {
831 for (
int i = 0; i < num_events; i++) {
833 call_eo_rcv_fn__no_cb(eo_rcv_fn,
834 ev_tbl[i], ev_hdr_tbl[i],
835 queue, queue_ctx, eo_ctx);
836 check_local_queues();
839 for (
int i = 0; i < num_events; i++)
840 call_eo_rcv_fn__no_cb(eo_rcv_fn,
841 ev_tbl[i], ev_hdr_tbl[i],
842 queue, queue_ctx, eo_ctx);
856dispatch_event_single_prepare(odp_event_t odp_event,
queue_elem_t *
const q_elem)
860 em_event_t
event = event_init_odp(odp_event,
true, q_elem, &ev_hdr);
867 dispatch_eo_multircv_single(event, ev_hdr, q_elem,
true);
869 dispatch_eo_rcv_single(event, ev_hdr, q_elem,
true);
879dispatch_event_burst_prepare(odp_event_t odp_evtbl[],
const int num_events,
884 em_event_t ev_tbl[DISPATCH_MULTI_MAX_BURST];
887 event_init_odp_multi(odp_evtbl, ev_tbl, evhdr_tbl,
888 num_events,
true, q_elem);
894 dispatch_eo_multircv_burst(ev_tbl, evhdr_tbl, num_events,
897 dispatch_eo_rcv_burst(ev_tbl, evhdr_tbl, num_events,
928dispatch_events(odp_event_t odp_evtbl[],
const int num_events,
946 dispatch_event_single_prepare(odp_evtbl[0], q_elem);
948 dispatch_event_burst_prepare(odp_evtbl, num_events, q_elem);
959 output_queue_buffering_drain();
967dispatch_poll_ctrl_queue(
void)
969 const unsigned int poll_interval =
em_shm->
opt.dispatch.poll_ctrl_interval;
975 if (poll_interval > 1) {
983 odp_time_t now = odp_time_local();
987 if (odp_time_cmp(period, poll_period) < 0)
1007 uint64_t to_idle_delay_ns = 0;
1010 to_idle_delay_ns = debug_timestamp() -
1011 locm->
debug_ts[EM_DEBUG_TSP_SCHED_ENTRY];
1013 to_idle_delay_ns = opt ? opt->
wait_ns :
1016 to_idle_delay_ns = opt->
wait_ns;
1019 call_idle_hooks_to_idle(to_idle_delay_ns);
1022 call_idle_hooks_while_idle();
1039 call_idle_hooks_to_active();
1049dispatch_schedule(odp_queue_t *odp_queue , uint64_t sched_wait,
1050 odp_event_t odp_evtbl[],
int num)
1057 ret = odp_schedule_multi(odp_queue, sched_wait, odp_evtbl, num);
1074 "Drop event(s) from non-EM Q");
1077 "Drop event(s) from Q:%" PRI_QUEUE ": not ready, state=%d",
1086free_invalid_events(odp_event_t odp_evtbl[],
int num)
1091 event_init_odp_multi(odp_evtbl, ev_tbl, ev_hdr_tbl,
1100dispatch_round(uint64_t sched_wait, uint16_t burst_size,
1103 odp_queue_t odp_queue;
1107 dispatch_poll_ctrl_queue();
1117 num = dispatch_schedule(&odp_queue, sched_wait,
1118 odp_evtbl, num_req);
1119 if (unlikely(num <= 0)) {
1131 check_local_queues();
1136 queue_elem_t *
const q_elem = odp_queue_context(odp_queue);
1138 if (unlikely(is_invalid_queue(q_elem))) {
1140 free_invalid_events(odp_evtbl, num);
1151 atomic_group_dispatch(odp_evtbl, num, q_elem);
1154 dispatch_events(odp_evtbl, num, q_elem);
1166check_poll_drain_round(
unsigned int interval, odp_time_t poll_drain_period)
1173 odp_time_t now = odp_time_local();
1179 if (odp_time_cmp(poll_drain_period, period) < 0) {
1194static inline uint64_t
1195dispatch_with_userfn(
const uint64_t rounds,
1199 const bool do_forever = rounds == 0 ? true :
false;
1200 const unsigned int poll_interval =
em_shm->
opt.dispatch.poll_drain_interval;
1205 uint64_t events = 0;
1206 int dispatched_events;
1208 bool do_poll_drain_round;
1210 for (uint64_t i = 0; do_forever || i < rounds;) {
1211 dispatched_events = 0;
1213 do_poll_drain_round = check_poll_drain_round(poll_interval, poll_period);
1215 if (input_poll_fn && do_poll_drain_round)
1216 rx_events = input_poll_fn();
1220 dispatched_events += round_events;
1222 }
while (dispatched_events < rx_events &&
1223 round_events > 0 && (do_forever || i < rounds));
1225 events += dispatched_events;
1226 if (output_drain_fn && do_poll_drain_round)
1227 (void)output_drain_fn();
1236static inline uint64_t
1237dispatch_no_userfn(uint64_t rounds)
1239 const bool do_forever = rounds == 0 ? true :
false;
1242 uint64_t events = 0;
1248 for (uint64_t i = 0; i < rounds; i++)
1259static inline uint64_t
1266 const unsigned int poll_interval =
em_shm->
opt.dispatch.poll_drain_interval;
1268 const uint64_t sched_wait = opt->
wait_ns == 0 ? ODP_SCHED_NO_WAIT :
1269 odp_schedule_wait_time(opt->
wait_ns);
1271 bool do_poll_drain_round =
false;
1274 const bool duration_forever =
1276 const bool duration_rounds =
1278 const bool duration_ns =
1280 const bool duration_events =
1282 const bool duration_noev_rounds =
1284 const bool duration_noev_ns =
1287 if (unlikely(duration_forever)) {
1290 do_poll_drain_round = check_poll_drain_round(poll_interval, poll_period);
1292 if (input_poll_fn && do_poll_drain_round)
1293 (void)input_poll_fn();
1296 (void)dispatch_round(sched_wait, burst_size, opt);
1298 if (output_drain_fn && do_poll_drain_round)
1299 (void)output_drain_fn();
1304 uint64_t events = 0;
1305 uint64_t rounds = 0;
1306 uint64_t noev_rounds = 0;
1308 uint64_t start_ns = 0;
1309 uint64_t stop_ns = 0;
1310 uint64_t noev_stop_ns = 0;
1311 uint64_t time_ns = 0;
1313 if (duration_ns || duration_noev_ns) {
1314 start_ns = odp_time_local_ns();
1315 stop_ns = start_ns + duration->
ns;
1316 noev_stop_ns = start_ns + duration->no_events.
ns;
1320 while ((!duration_rounds || rounds < duration->rounds) &&
1321 (!duration_ns || time_ns < stop_ns) &&
1323 (!duration_noev_rounds || noev_rounds < duration->no_events.rounds) &&
1324 (!duration_noev_ns || time_ns < noev_stop_ns)) {
1326 do_poll_drain_round = check_poll_drain_round(poll_interval, poll_period);
1328 if (input_poll_fn && do_poll_drain_round)
1329 (void)input_poll_fn();
1332 int round_events = dispatch_round(sched_wait, burst_size, opt);
1334 events += round_events;
1337 if (output_drain_fn && do_poll_drain_round)
1338 (void)output_drain_fn();
1340 if (duration_noev_rounds) {
1341 if (round_events == 0)
1347 if (duration_ns || duration_noev_ns) {
1348 time_ns = odp_time_local_ns();
1350 if (duration_noev_ns && round_events > 0)
1351 noev_stop_ns = time_ns + duration->no_events.
ns;
1356 results->
rounds = rounds;
1357 if (duration_ns || duration_noev_ns)
1358 results->
ns = time_ns - start_ns;
1361 results->
events = events;
1367static inline uint64_t
1372 const uint64_t sched_wait = opt->
wait_ns == 0 ? ODP_SCHED_NO_WAIT :
1373 odp_schedule_wait_time(opt->
wait_ns);
1377 const bool duration_forever =
1379 const bool duration_rounds =
1381 const bool duration_ns =
1383 const bool duration_events =
1385 const bool duration_noev_rounds =
1387 const bool duration_noev_ns =
1390 if (unlikely(duration_forever)) {
1392 (
void)dispatch_round(sched_wait, burst_size, opt);
1396 uint64_t events = 0;
1397 uint64_t rounds = 0;
1398 uint64_t noev_rounds = 0;
1400 uint64_t start_ns = 0;
1401 uint64_t stop_ns = 0;
1402 uint64_t noev_stop_ns = 0;
1403 uint64_t time_ns = 0;
1405 if (duration_ns || duration_noev_ns) {
1406 start_ns = odp_time_local_ns();
1407 stop_ns = start_ns + duration->
ns;
1408 noev_stop_ns = start_ns + duration->no_events.
ns;
1412 while ((!duration_rounds || rounds < duration->rounds) &&
1413 (!duration_ns || time_ns < stop_ns) &&
1415 (!duration_noev_rounds || noev_rounds < duration->no_events.rounds) &&
1416 (!duration_noev_ns || time_ns < noev_stop_ns)) {
1418 int round_events = dispatch_round(sched_wait, burst_size, opt);
1420 events += round_events;
1423 if (duration_noev_rounds) {
1424 if (round_events == 0)
1430 if (duration_ns || duration_noev_ns) {
1431 time_ns = odp_time_local_ns();
1432 if (duration_noev_ns && round_events > 0)
1433 noev_stop_ns = time_ns + duration->no_events.
ns;
1438 results->
rounds = rounds;
1439 if (duration_ns || duration_noev_ns)
1440 results->
ns = time_ns - start_ns;
1443 results->
events = events;
__attribute__((always_inline)) static inline void call_eo_rcv_fn__no_cb(const em_receive_func_t eo_receive_func
#define INTERNAL_ERROR(error, escope, fmt,...)
void poll_unsched_ctrl_queue(void)
Poll EM's internal unscheduled control queues during dispatch.
ENV_LOCAL em_locm_t em_locm
#define EM_DEBUG_TIMESTAMP_ENABLE
#define EM_QUEUE_LOCAL_MULTI_MAX_BURST
#define EM_OUTPUT_QUEUE_IMMEDIATE
#define EM_SCHED_MULTI_MAX_BURST
#define EM_IDLE_HOOKS_ENABLE
#define EM_SCHED_WAIT_ENABLE
#define EM_EVENT_GROUP_UNDEF
void(* em_dispatch_enter_func_t)(em_eo_t eo, void **eo_ctx, em_event_t events[], int num, em_queue_t *queue, void **q_ctx)
void(* em_dispatch_exit_func_t)(em_eo_t eo)
@ EM_DISPATCH_DURATION_ROUNDS
@ EM_DISPATCH_DURATION_NO_EVENTS_NS
@ EM_DISPATCH_DURATION_EVENTS
@ EM_DISPATCH_DURATION_NS
@ EM_DISPATCH_DURATION_FOREVER
@ EM_DISPATCH_DURATION_NO_EVENTS_ROUNDS
void(* em_receive_func_t)(void *eo_ctx, em_event_t event, em_event_type_t type, em_queue_t queue, void *q_ctx)
void(* em_receive_multi_func_t)(void *eo_ctx, em_event_t events[], int num, em_queue_t queue, void *q_ctx)
void em_free_multi(em_event_t events[], int num)
void em_free(em_event_t event)
@ EM_SCHED_CONTEXT_TYPE_ORDERED
@ EM_SCHED_CONTEXT_TYPE_NONE
@ EM_SCHED_CONTEXT_TYPE_ATOMIC
int(* em_input_poll_func_t)(void)
int(* em_output_drain_func_t)(void)
em_sched_context_type_t sched_context_type
event_group_elem_t * egrp_elem
queue_elem_t * sched_q_elem
em_dispatch_duration_select_t select
em_locm_current_t current
local_queues_t local_queues
unsigned int dispatch_cnt
unsigned int poll_drain_dispatch_cnt
odp_time_t poll_ctrl_interval_time
uint64_t debug_ts[EM_DEBUG_TSP_LAST]
odp_time_t dispatch_last_run
output_queue_track_t output_queue_track
odp_time_t poll_drain_dispatch_last_run
odp_time_t poll_drain_interval_time
cfgfile_opt_cache_t opt_cache
hook_tbl_t * dispatch_exit_cb_tbl
em_event_type_t event_type
em_receive_multi_func_t receive_multi_func
em_receive_func_t receive_func