23#include <odp/helper/odph_api.h>
44#include "em_libconfig.h"
53bool is_core_initialized(
void)
118 shm = odp_shm_lookup(
"em_shm");
121 "Shared memory lookup failed!");
123 shm_addr = odp_shm_addr(shm);
125 "Shared memory ptr NULL");
131 "Shared memory init fails: em_shm:%p != shm_addr:%p",
136 "emcli_init_local() fails: %" PRIxSTAT
"", stat);
150 int thr = odp_thread_id();
151 em_queue_t unsched_queue;
154 unsched_queue = queue_id2hdl(
em_shm->queue_tbl.first_internal_queue_id + (uint16_t)thr);
157 q_elem = queue_elem_get(unsched_queue);
158 if (unlikely(!q_elem))
164 unsched_queue = queue_id2hdl(
em_shm->queue_tbl.shared_internal_queue_id);
167 q_elem = queue_elem_get(unsched_queue);
168 if (unlikely(!q_elem))
186 *locm = locm_init_values;
190 shm = odp_shm_lookup(
"em_shm");
191 if (unlikely(shm == ODP_SHM_INVALID)) {
192 EM_LOG(EM_LOG_ERR,
"Shared memory lookup failed!");
196 shm_addr = odp_shm_addr(shm);
197 if (unlikely(shm_addr == NULL)) {
198 EM_LOG(EM_LOG_ERR,
"Shared memory ptr NULL");
206 if (unlikely(shm_addr !=
em_shm)) {
207 EM_LOG(EM_LOG_ERR,
"Shared memory init fails: em_shm:%p != shm_addr:%p",
219 stat = init_thr_mem();
221 "init_thr_mem() failed:%" PRIxSTAT
"", stat);
239 "create_ctrl_queue() failed:%" PRIxSTAT
"", stat);
242 stat = core_map_init_local(&
em_shm->core_map, conf_local);
244 "core_map_init_local() failed:%" PRIxSTAT
"", stat);
246 stat = queue_group_init_local();
248 "queue_group_init_local() failed:%" PRIxSTAT
"", stat);
250 stat = dispatch_init_local();
252 "dispatch_init_local() failed:%" PRIxSTAT
"", stat);
255 stat = input_poll_init_local(conf_local);
257 "input_poll_init_local() failed:%" PRIxSTAT
"", stat);
260 stat = output_drain_init_local(conf_local);
262 "output_drain_init_local() failed:%" PRIxSTAT
"", stat);
264 stat = queue_init_local();
266 "queue_init_local() failed:%" PRIxSTAT
"", stat);
272 stat = timer_init_local();
274 "timer_init_local() failed:%" PRIxSTAT
"", stat);
276 stat = sync_api_init_local();
278 "sync_api_init_local() failed:%" PRIxSTAT
"", stat);
283 "emcli_init_local() failed:%" PRIxSTAT
"", stat);
287 for (
int i = 0; i < EM_DEBUG_TSP_LAST; i++)
299 eo_start_local_fn_at_init();
308 stat = init_thr_mem();
310 "init_thr_mem() failed:%" PRIxSTAT
"", stat);
319 "create_ctrl_queue() failed:%" PRIxSTAT
"", stat);
321 stat = core_map_init_extthr(&
em_shm->core_map);
323 "core_map_init_extthr() failed:%" PRIxSTAT
"", stat);
325 stat = sync_api_init_local();
327 "sync_api_init_local() failed:%" PRIxSTAT
"", stat);
332 "emcli_init_local() failed:%" PRIxSTAT
"", stat);
341void flush_scheduler_events(
void)
356 event_init_odp_multi(odp_ev_tbl, em_ev_tbl, ev_hdr_tbl,
360 }
while (num_events > 0);
368 const int thr = odp_thread_id();
371 eo_stop_local_fn_at_term();
375 int current_core_count = core_map_term_local(&
em_shm->core_map, escope);
378 "core_map_term_local(): current_core_count=%d", current_core_count);
389 cnt = odp_atomic_load_u32(&
em_shm->core_map.ongoing_term_reqs[thr]);
391 "%s(): ongoing_term_reqs[%02d]=%d", __func__, thr, cnt);
399 odp_schedule_pause();
401 flush_scheduler_events();
404 stat = timer_term_local();
408 "timer_term_local() fails: %" PRIxSTAT
"", stat);
416 "emcli_term_local() fails: %" PRIxSTAT
"", stat);
420 stat = queue_term_local();
424 "queue_term_local() fails: %" PRIxSTAT
"", stat);
427 bool flush_orphan_qgrps =
em_shm->
opt.queue_group.term_local_flush_orphans;
429 queue_group_leave_all(flush_orphan_qgrps);
443 int current_core_count = core_map_term_extthr(&
em_shm->core_map, escope);
446 "core_map_term_extthr(): current_core_count=%d", current_core_count);
461 "emcli_term_local() fails: %" PRIxSTAT
"", stat);
470static void fill_startup_pools_str(
char *startup_pools_str,
471 size_t startup_pools_str_size,
472 uint32_t num_startup_pools)
476 for (uint32_t i = 0; i < num_startup_pools; i++) {
480 const char *event_type_str =
"UNKNOWN";
483 event_type_str =
"EM_EVENT_TYPE_SW";
485 event_type_str =
"EM_EVENT_TYPE_PACKET";
487 event_type_str =
"EM_EVENT_TYPE_VECTOR";
489 offset += snprintf(startup_pools_str + offset,
490 startup_pools_str_size - offset,
494 " pool_cfg.event_type: %s\n"
495 " pool_cfg.align_offset.in_use: %s\n"
496 " pool_cfg.align_offset.value: %u\n"
497 " pool_cfg.user_area.in_use: %s\n"
498 " pool_cfg.user_area.size: %zu\n"
499 " pool_cfg.pkt.headroom.in_use: %s\n"
500 " pool_cfg.pkt.headroom.value: %u\n"
501 " pool_cfg.num_subpools: %u\n", i,
502 conf->name[0] ? conf->name :
"(not set)",
503 conf->pool, event_type_str,
504 conf->cfg.align_offset.in_use ?
"true" :
"false",
505 conf->cfg.align_offset.value,
506 conf->cfg.user_area.in_use ?
"true" :
"false",
507 conf->cfg.user_area.size,
508 conf->cfg.pkt.headroom.in_use ?
"true" :
"false",
509 conf->cfg.pkt.headroom.value,
510 conf->cfg.num_subpools);
513 offset += snprintf(startup_pools_str + offset,
514 startup_pools_str_size - offset,
515 " pool_cfg.subpool[%d].size: %u\n"
516 " pool_cfg.subpool[%d].num: %u\n"
517 " pool_cfg.subpool[%d].cache_size: %u\n",
525void cfgfile_opts_print(
void)
528 char *startup_pools_str = NULL;
529 const uint32_t custom_map_size = 64;
530 char queue_priority_custom_map[custom_map_size];
531 uint32_t num_startup_pools =
em_shm->
opt.startup_pools.num;
532 size_t startup_pools_str_size = 1000 * num_startup_pools;
535 if (num_startup_pools) {
536 startup_pools_str = malloc(startup_pools_str_size);
537 if (!startup_pools_str) {
538 EM_LOG(EM_LOG_ERR,
"Failed to malloc(%zu) for startup_pools_str\n",
539 startup_pools_str_size);
542 fill_startup_pools_str(startup_pools_str, startup_pools_str_size,
546 if (
em_shm->
opt.queue.priority.map_mode != 2) {
547 queue_priority_custom_map[0] =
'\0';
549 offset += snprintf(queue_priority_custom_map + offset,
550 custom_map_size - offset,
551 " priority.custom_map: [");
554 offset += snprintf(queue_priority_custom_map + offset,
555 custom_map_size - offset,
"%d, ",
556 em_shm->
opt.queue.priority.custom_map[i]);
559 snprintf(queue_priority_custom_map + offset,
560 custom_map_size - offset,
"%d]\n",
565 "======================\n"
566 "EM Config File Options\n"
567 "======================\n"
573 " poll_ctrl_interval: %u\n"
574 " poll_ctrl_interval_ns: %" PRIu64
" ns\n"
575 " poll_drain_interval: %u\n"
576 " poll_drain_interval_ns: %" PRIu64
" ns\n"
577 " sched_wait_ns: %" PRIu64
" ns\n"
580 " start_local_fn_at_init: %s\n"
581 " stop_local_fn_at_term: %s\n"
585 " store_payload_first_u32: %s\n"
586 " prealloc_pools: %s\n"
587 "\nevent_chaining:\n"
589 " num_order_queues: %u\n"
591 " statistics.available: %u\n"
592 " statistics.alloc_ops: %u\n"
593 " statistics.alloc_fails: %u\n"
594 " statistics.free_ops: %u\n"
595 " statistics.total_ops: %u\n"
596 " statistics.cache_available: %u\n"
597 " statistics.cache_alloc_ops: %u\n"
598 " statistics.cache_free_ops: %u\n"
599 " statistics.core_cache_available: %u\n"
600 " align_offset: %u bytes\n"
601 " user_area_size: %zu bytes\n"
602 " pkt_headroom: %u bytes\n"
606 " min_events_default: %u\n"
607 " priority.map_mode: %d\n%s\n"
609 " create_core_queue_groups: %s\n"
610 " term_local_flush_orphans: %s\n"
612 " shared_tmo_pool_enable: %s\n"
613 " shared_tmo_pool_size: %u\n"
614 " tmo_pool_cache: %u\n"
615 " ring.timer_event_pool_size: %u\n"
616 " ring.timer_event_pool_cache: %u\n"
621 em_shm->
opt.cli.enable ?
"true" :
"false",
622 em_shm->opt.cli.ip_addr ?
em_shm->opt.cli.ip_addr :
"(null)",
624 em_shm->opt.dispatch.poll_ctrl_interval,
625 em_shm->opt.dispatch.poll_ctrl_interval_ns,
626 em_shm->opt.dispatch.poll_drain_interval,
627 em_shm->opt.dispatch.poll_drain_interval_ns,
628 em_shm->opt.dispatch.sched_wait_ns,
629 em_shm->opt.dispatch.sched_pause ?
"true" :
"false",
630 em_shm->opt.eo.start_local_fn_at_init ?
"true" :
"false",
631 em_shm->opt.eo.stop_local_fn_at_term ?
"true" :
"false",
632 em_shm->opt.esv.enable ?
"true" :
"false",
633 em_shm->opt.esv.store_state ?
"true" :
"false",
634 em_shm->opt.esv.store_first_u32 ?
"true" :
"false",
635 em_shm->opt.esv.prealloc_pools ?
"true" :
"false",
636 em_shm->opt.event_chaining.order_keep ?
"true" :
"false",
637 em_shm->opt.event_chaining.num_order_queues,
638 em_shm->opt.pool.statistics.available,
639 em_shm->opt.pool.statistics.alloc_ops,
640 em_shm->opt.pool.statistics.alloc_fails,
641 em_shm->opt.pool.statistics.free_ops,
642 em_shm->opt.pool.statistics.total_ops,
643 em_shm->opt.pool.statistics.cache_available,
644 em_shm->opt.pool.statistics.cache_alloc_ops,
645 em_shm->opt.pool.statistics.cache_free_ops,
646 em_shm->opt.pool.statistics.core_cache_available,
647 em_shm->opt.pool.align_offset,
648 em_shm->opt.pool.user_area_size,
649 em_shm->opt.pool.pkt_headroom,
650 em_shm->opt.queue.num_static,
651 em_shm->opt.queue.num_dynamic,
652 em_shm->opt.queue.min_events_default,
653 em_shm->opt.queue.priority.map_mode,
654 queue_priority_custom_map,
655 em_shm->opt.queue_group.create_core_queue_groups ?
"true" :
"false",
656 em_shm->opt.queue_group.term_local_flush_orphans ?
"true" :
"false",
657 em_shm->opt.timer.shared_tmo_pool_enable ?
"true" :
"false",
658 em_shm->opt.timer.shared_tmo_pool_size,
659 em_shm->opt.timer.tmo_pool_cache,
660 em_shm->opt.timer.ring.timer_event_pool_size,
661 em_shm->opt.timer.ring.timer_event_pool_cache,
662 em_shm->opt.vector.backend_str,
664 startup_pools_str ? startup_pools_str :
"");
666 if (startup_pools_str)
667 free(startup_pools_str);
670void conf_local_opts_print(
void)
672 const char *core_type_str;
679 core_type_str =
"EM_CORE_TYPE_WORKER";
682 core_type_str =
"EM_CORE_TYPE_CONTROL";
685 core_type_str =
"EM_CORE_TYPE_EXTERNAL";
688 core_type_str =
"UNKNOWN";
693 "============================================\n"
694 "EM core-local config given to em_init_local()\n"
695 "or used by em_init_core()\n"
696 "============================================\n"
699 "input_poll_fn: %s\n"
700 "output_drain_fn: %s\n"
705 conf_local->output_drain_fn ?
"(set)" :
"(not set)");
708void conf_opts_print(
void)
712 char default_pool_str[1024];
720 const char *event_type_str =
"UNKNOWN";
723 event_type_str =
"EM_EVENT_TYPE_SW";
725 event_type_str =
"EM_EVENT_TYPE_PACKET";
727 event_type_str =
"EM_EVENT_TYPE_VECTOR";
729 offset += snprintf(default_pool_str + offset,
730 sizeof(default_pool_str) - offset,
732 " align_offset.in_use: %s\n"
733 " align_offset.value: %u\n"
734 " user_area.in_use: %s\n"
735 " user_area.size: %zu\n"
736 " pkt.headroom.in_use: %s\n"
737 " pkt.headroom.value: %u\n"
738 " num_subpools: %u\n",
741 pool_cfg->align_offset.value,
742 pool_cfg->user_area.in_use ?
"true" :
"false",
743 pool_cfg->user_area.size,
744 pool_cfg->pkt.headroom.in_use ?
"true" :
"false",
745 pool_cfg->pkt.headroom.value,
746 pool_cfg->num_subpools);
749 offset += snprintf(default_pool_str + offset,
750 sizeof(default_pool_str) - offset,
751 " subpool[%d].size: %u\n"
752 " subpool[%d].num: %u\n"
753 " subpool[%d].cache_size: %u\n",
760 "====================================\n"
761 "EM runtime config given to em_init()\n"
762 "====================================\n"
765 "thread_per_core: %s\n"
766 "process_per_core: %s\n"
769 "\ndefault_pool_cfg:\n%s\n"
772 "\napi_hooks.alloc_hook: %s\n"
773 "api_hooks.free_hook: %s\n"
774 "api_hooks.send_hook: %s\n"
775 "\nidle_hooks.to_idle_hook: %s\n"
776 "idle_hooks.to_active_hook: %s\n"
777 "idle_hooks.while_idle_hook: %s\n"
781 conf->thread_per_core ?
"true" :
"false",
782 conf->process_per_core ?
"true" :
"false",
786 conf->log.log_fn ?
"(set)" :
"(not set)",
787 conf->log.vlog_fn ?
"(set)" :
"(not set)",
788 conf->api_hooks.alloc_hook ?
"(set)" :
"(not set)",
789 conf->api_hooks.free_hook ?
"(set)" :
"(not set)",
790 conf->api_hooks.send_hook ?
"(set)" :
"(not set)",
791 conf->idle_hooks.to_idle_hook ?
"(set)" :
"(not set)",
792 conf->idle_hooks.to_active_hook ?
"(set)" :
"(not set)",
793 conf->idle_hooks.while_idle_hook ?
"(set)" :
"(not set)");
#define INTERNAL_ERROR(error, escope, fmt,...)
#define RETURN_ERROR_IF(cond, error, escope, fmt,...)
#define EM_LOCM_INIT_VALUES
em_status_t create_ctrl_queue(void)
Create EM's internal unscheduled control queues at startup - one per core.
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_PRIO_NUM
#define EM_SCHED_MULTI_MAX_BURST
void em_core_mask_tostr(char *mask_str, int len, const em_core_mask_t *mask)
#define EM_CORE_MASK_STRLEN
em_status_t emcli_init_local(void)
Initialize the EM CLI locally on an EM core (if enabled)
em_status_t emcli_term_local(void)
Terminate the EM CLI locally on an EM core (if enabled)
int(* em_log_func_t)(em_log_level_t level, const char *fmt,...) __attribute__((format(printf
int(*) typedef int(* em_vlog_func_t)(em_log_level_t level, const char *fmt, va_list args)
void em_free_multi(em_event_t events[], int num)
em_input_poll_func_t input_poll_fn
em_output_drain_func_t output_drain_fn
em_pool_cfg_t default_pool_cfg
bool is_core_local_inited
em_output_drain_func_t output_drain_fn
em_input_poll_func_t input_poll_fn
uint64_t debug_ts[EM_DEBUG_TSP_LAST]
em_conf_local_t conf_local
struct em_pool_cfg_t::@23 subpool[EM_MAX_SUBPOOLS]
em_event_type_t event_type
struct em_pool_cfg_t::@20 align_offset
ev_hdr_user_area_t user_area
em_event_type_t event_type
em_queue_t shared_unsched_queue
em_queue_t thr_unsched_queue
odp_queue_t thr_odp_plain_queue
queue_elem_t * thr_unsched_qelem
odp_queue_t shared_odp_plain_queue
queue_elem_t * shared_unsched_qelem