62#include "em_libconfig.h"
72#define EM_Q_BASENAME "EM_Q_"
74static int queue_init_prio_map(
int minp,
int maxp,
int nump);
75static void queue_init_prio_legacy(
int minp,
int maxp);
76static void queue_init_prio_adaptive(
int minp,
int maxp,
int nump);
77static int queue_init_prio_custom(
int minp,
int maxp);
80queue_create_check_sched(
const em_queue_param_t *param,
const char **err_str);
84 const char **err_str );
86 odp_queue_param_t *odp_queue_param );
89 const char **err_str );
92 const char **err_str );
95 const char **err_str );
98 const char **err_str );
114static int read_num_aggr_config(
void)
116 const unsigned int max_config_queues = UINT16_MAX - MAX_INTERNAL_QUEUES;
117 const char *conf_str;
121 if (
em_shm->
opt.vector.backend == EM_VECTOR_BACKEND_EVENT) {
122 conf_str =
"queue.num_aggr";
123 ret = em_libconfig_lookup_int(&
em_shm->libconfig, conf_str, &val);
124 if (unlikely(!ret)) {
125 EM_LOG(EM_LOG_ERR,
"Config option '%s' not found.\n", conf_str);
128 if (val < 0 || (
unsigned int)val > max_config_queues) {
129 EM_LOG(EM_LOG_ERR,
"Bad config value '%s = %d', value must be\n"
130 ">= 0 and <= %u\n", conf_str, val, max_config_queues);
133 em_shm->
opt.queue.num_aggr = (
unsigned int)val;
134 EM_PRINT(
" %s: %d\n", conf_str, val);
135 }
else if (
em_shm->
opt.vector.backend == EM_VECTOR_BACKEND_PACKET) {
139 EM_LOG(EM_LOG_ERR,
"Invalid vector backend %d\n",
em_shm->
opt.vector.backend);
146static int read_config_file(
void)
148 const char *conf_str;
151 unsigned int max_queues;
152 const unsigned int max_config_queues = UINT16_MAX - MAX_INTERNAL_QUEUES;
154 EM_PRINT(
"EM queue config:\n");
159 conf_str =
"queue.num_static";
160 ret = em_libconfig_lookup_int(&
em_shm->libconfig, conf_str, &val);
161 if (unlikely(!ret)) {
162 EM_LOG(EM_LOG_ERR,
"Config option '%s' not found.\n", conf_str);
166 if (val < 0 || (
unsigned int)val > max_config_queues) {
167 EM_LOG(EM_LOG_ERR,
"Bad config value '%s = %d', value must be\n"
168 ">= 0 and <= %u\n", conf_str, val, max_config_queues);
171 em_shm->
opt.queue.num_static = (
unsigned int)val;
172 EM_PRINT(
" %s: %d\n", conf_str, val);
177 conf_str =
"queue.num_dynamic";
178 ret = em_libconfig_lookup_int(&
em_shm->libconfig, conf_str, &val);
179 if (unlikely(!ret)) {
180 EM_LOG(EM_LOG_ERR,
"Config option '%s' not found.\n", conf_str);
184 if (val < 0 || (
unsigned int)val > max_config_queues) {
185 EM_LOG(EM_LOG_ERR,
"Bad config value '%s = %d', value must be\n"
186 ">= 0 and <= %u\n", conf_str, val, max_config_queues);
189 em_shm->
opt.queue.num_dynamic = (
unsigned int)val;
190 EM_PRINT(
" %s: %d\n", conf_str, val);
193 EM_LOG(EM_LOG_ERR,
"At least one of num_static or num_dynamic must be > 0\n");
203 if (read_num_aggr_config() != 0)
206 max_queues =
em_shm->
opt.queue.num_static +
208 em_shm->
opt.queue.num_aggr + MAX_INTERNAL_QUEUES;
210 if (max_queues > UINT16_MAX) {
212 "Bad config value: num_static(%u) + num_dynamic(%u) +\n"
213 "num_aggr(%u) + MAX_INTERNAL_QUEUES(%u) = %u > UINT16_MAX(%u)\n",
215 em_shm->
opt.queue.num_aggr, MAX_INTERNAL_QUEUES, max_queues, UINT16_MAX);
219 if (max_queues >
em_shm->queue_tbl.odp_queue_capability.max_queues) {
221 "Bad config values: num_static(%u) + num_dynamic(%u) +\n"
222 "num_aggr(%u) + MAX_INTERNAL_QUEUES(%u) = %u > odp-max-queues:%u\n",
224 em_shm->
opt.queue.num_aggr, MAX_INTERNAL_QUEUES, max_queues,
225 em_shm->queue_tbl.odp_queue_capability.max_queues);
230 em_shm->queue_tbl.max_queue_num = (uint16_t)max_queues;
235 conf_str =
"queue.min_events_default";
236 ret = em_libconfig_lookup_int(&
em_shm->libconfig, conf_str, &val);
237 if (unlikely(!ret)) {
238 EM_LOG(EM_LOG_ERR,
"Config option '%s' not found.\n", conf_str);
242 EM_LOG(EM_LOG_ERR,
"Bad config value '%s = %d'\n",
247 em_shm->
opt.queue.min_events_default = val;
248 EM_PRINT(
" %s: %d\n", conf_str, val);
253 conf_str =
"queue.priority.map_mode";
254 ret = em_libconfig_lookup_int(&
em_shm->libconfig, conf_str, &val);
255 if (unlikely(!ret)) {
256 EM_LOG(EM_LOG_ERR,
"Config option '%s' not found\n", conf_str);
259 if (val < 0 || val > 2) {
260 EM_LOG(EM_LOG_ERR,
"Bad config value '%s = %d'\n", conf_str, val);
263 em_shm->
opt.queue.priority.map_mode = val;
264 EM_PRINT(
" %s: %d\n", conf_str, val);
267 conf_str =
"queue.priority.custom_map";
268 ret = em_libconfig_lookup_array(&
em_shm->libconfig, conf_str,
271 if (unlikely(!ret)) {
272 EM_LOG(EM_LOG_ERR,
"Config option '%s' not found or invalid\n", conf_str);
275 EM_PRINT(
" %s: [", conf_str);
277 EM_PRINT(
"%d",
em_shm->
opt.queue.priority.custom_map[i]);
289static int queue_pool_init(
queue_pool_t *
const queue_pool)
293 if (objpool_init(&queue_pool->objpool, num_subpools) != 0)
302static int queue_pool_populate(
queue_tbl_t *
const queue_tbl,
304 int min_qidx,
int max_qidx)
306 const uint32_t num_subpools = objpool_subpools(&queue_pool->objpool);
307 const int qs_per_pool = (max_qidx - min_qidx + 1);
308 int qs_per_subpool = qs_per_pool / num_subpools;
309 int qs_leftover = qs_per_pool % num_subpools;
310 uint32_t subpool_idx = 0;
313 for (
int i = min_qidx; i <= max_qidx; i++) {
314 objpool_add(&queue_pool->objpool, subpool_idx,
315 &queue_tbl->queue_elem[i].queue_pool_elem);
317 if (add_cnt == qs_per_subpool + qs_leftover) {
335 odp_queue_capability_t *
const odp_queue_capa =
337 odp_schedule_capability_t *
const odp_sched_capa =
348 odp_atomic_init_u32(&queue_tbl->output_queue_count, 0);
351 if (queue_pool_init(queue_pool) ||
352 queue_pool_init(queue_pool_static) ||
353 queue_pool_init(queue_pool_aggr))
357 ret = odp_queue_capability(odp_queue_capa);
359 "odp_queue_capability():%d failed", ret);
362 ret = odp_schedule_capability(odp_sched_capa);
364 "odp_schedule_capability():%d failed", ret);
366 if (read_config_file())
369 const unsigned int max_queues =
em_shm->queue_tbl.max_queue_num;
374 (uint16_t)
em_shm->
opt.queue.num_static - 1;
383 MAX_INTERNAL_QUEUES - 1;
389 (uint16_t)
em_shm->
opt.queue.num_dynamic - 1;
399 (uint16_t)
em_shm->
opt.queue.num_aggr - 1;
403 (uint16_t)
em_shm->
opt.queue.num_aggr - 1;
410 size_t qelem_tbl_sz =
sizeof(
queue_elem_t) * max_queues;
412 size_t shm_sz = qelem_tbl_sz + qname_tbl_sz;
414 void *shm_tbl = env_shared_reserve(
"EM q_elem tbl and names", shm_sz);
417 "env_shared_reserve() failed when reserving \"EM q_elem tbl and names\"");
418 memset(shm_tbl, 0, shm_sz);
421 queue_tbl->queue_elem = shm_tbl;
425 for (
unsigned int i = 0; i < max_queues; i++)
426 queue_tbl->queue_elem[i].queue = (uint32_t)(uintptr_t)queue_idx2hdl(i);
435 if (queue_pool_populate(queue_tbl, queue_pool_static, min, max) != 0)
442 if (queue_pool_populate(queue_tbl, queue_pool, min, max) != 0)
450 if (queue_pool_populate(queue_tbl, queue_pool_aggr, min, max) != 0)
455 min = odp_schedule_min_prio();
456 max = odp_schedule_max_prio();
460 "mapping odp priorities failed: %d", ret);
477 odp_stash_capability_t stash_capa;
478 odp_stash_param_t stash_param;
479 unsigned int num_obj = 0;
481 char name[ODP_STASH_NAME_LEN];
483 int ret = odp_stash_capability(&stash_capa, ODP_STASH_TYPE_FIFO);
488 odp_stash_param_init(&stash_param);
490 stash_param.type = ODP_STASH_TYPE_FIFO;
496 stash_param.put_mode = ODP_STASH_OP_LOCAL;
497 stash_param.get_mode = ODP_STASH_OP_LOCAL;
500 num_obj =
em_shm->
opt.queue.min_events_default;
502 stash_param.num_obj = num_obj;
505 stash_param.obj_size =
sizeof(uint64_t);
506 if (stash_param.num_obj > stash_capa.max_num.u64) {
508 "%s(): req stash.num_obj(%" PRIu64
") > capa.max_num.u64(%" PRIu64
").\n"
509 " ==> using max value:%" PRIu64
"\n", __func__,
510 stash_param.num_obj, stash_capa.max_num.u64, stash_capa.max_num.u64);
511 stash_param.num_obj = stash_capa.max_num.u64;
514 stash_param.cache_size = 0;
519 snprintf(name,
sizeof(name),
520 "local-q:c%02d:prio%d", core, prio);
521 name[
sizeof(name) - 1] =
'\0';
525 odp_stash_create(name, &stash_param);
550 int num = next_local_queue_events(entry_tbl ,
555 for (
int i = 0; i < num; i++)
556 ev_tbl[i] = (em_event_t)(uintptr_t)entry_tbl[i].evptr;
558 event_to_hdr_multi(ev_tbl, ev_hdr_tbl, num);
561 evstate_em2usr_multi(ev_tbl, ev_hdr_tbl, num,
562 EVSTATE__TERM_CORE__QUEUE_LOCAL);
569 if (unlikely(ret != 0))
576static inline bool id_in_queue_pool_static(uint16_t qid)
579 return qid >=
em_shm->queue_tbl.first_internal_queue_id &&
580 qid <=
em_shm->queue_tbl.last_internal_queue_id;
582 return qid >=
em_shm->queue_tbl.first_static_queue_id &&
583 qid <=
em_shm->queue_tbl.last_internal_queue_id;
598em_queue_t queue_alloc(em_queue_t queue,
const char **err_str )
607 queue_pool_elem = objpool_rem(&
em_shm->queue_pool.objpool,
609 if (unlikely(queue_pool_elem == NULL)) {
610 *err_str =
"queue pool element alloc failed!";
613 queue_elem = queue_poolelem2queue(queue_pool_elem);
622 !id_in_queue_pool_static(iq.queue_id)) {
623 *err_str =
"Invalid queue requested or handle not from static range!";
627 queue_elem = queue_elem_get(queue);
628 if (unlikely(queue_elem == NULL)) {
629 *err_str =
"queue_elem ptr NULL!";
633 if (queue_allocated(queue_elem)) {
634 *err_str =
"queue already allocated!";
638 int ret = objpool_rem_elem(&
em_shm->queue_pool_static.objpool,
640 if (unlikely(ret != 0)) {
641 *err_str =
"static queue pool element alloc failed!";
647 return (em_queue_t)(uintptr_t)queue_elem->
queue;
658 if (unlikely(queue_elem == NULL))
661 if (id_in_queue_pool_static(iq.queue_id))
662 objpool = &
em_shm->queue_pool_static.objpool;
664 objpool = &
em_shm->queue_pool.objpool;
676static em_queue_t queue_aggr_alloc(
const char **err_str )
684 queue_pool_elem = objpool_rem(&
em_shm->queue_pool_aggr.objpool,
686 if (unlikely(queue_pool_elem == NULL)) {
687 *err_str =
"aggregator queue pool element alloc failed!";
690 queue_elem = queue_poolelem2queue(queue_pool_elem);
693 return (em_queue_t)(uintptr_t)queue_elem->
queue;
715 em_queue_t queue = (em_queue_t)(uintptr_t)q_elem->
queue;
716 uint32_t num_aggr = q_elem->aggr_parent.
num_aggr;
718 bool err_occurred =
false;
720 for (uint32_t i = 0; i < num_aggr; i++) {
721 em_queue_t aggr_queue =
722 (em_queue_t)(uintptr_t)q_elem->aggr_parent.
aggr_queues[i];
727 if (unlikely(!aggr_qelem || !queue_allocated(aggr_qelem))) {
731 queue, aggr_queue, i);
740 "aggr-Q:{type=%u, parent-Q=%" PRI_QUEUE "}\n",
741 queue, aggr_queue, i,
747 queue_aggr_free(aggr_qelem);
753 if (unlikely(err_occurred))
760 const odp_event_aggr_capability_t *odp_aggr_capa,
761 const char **err_str)
767 if (unlikely(
em_shm->
opt.vector.backend == EM_VECTOR_BACKEND_PACKET)) {
768 *err_str =
"Event aggregation not supported with packet vector backend!";
773 if (unlikely(param->
num_aggr > MIN(odp_aggr_capa->max_num,
774 odp_aggr_capa->max_num_per_queue) ||
776 *err_str =
"Invalid number of event aggregators, check limits!";
781 *err_str =
"Event aggregator config missing!";
785 for (uint32_t i = 0; i < param->
num_aggr; i++) {
789 *err_str =
"Use em_queue_aggr_conf_init() before create";
794 *err_str =
"Event aggregator pool not defined!";
800 if (unlikely(!pool_elem || !pool_allocated(pool_elem) ||
802 *err_str =
"Invalid pool for event aggregator!";
807 if (unlikely(aggr_conf->
max_size > odp_aggr_capa->max_size ||
808 aggr_conf->
max_size < odp_aggr_capa->min_size)) {
809 *err_str =
"Invalid max_size for event aggregator!";
815 (aggr_conf->
max_tmo_ns > odp_aggr_capa->max_tmo_ns ||
816 aggr_conf->
max_tmo_ns < odp_aggr_capa->min_tmo_ns)) {
817 *err_str =
"Invalid max_tmo_ns for event aggregator!";
826 odp_event_aggr_config_t odp_aggr_config[],
827 uint32_t num_aggr,
const char **err_str)
833 for (uint32_t i = 0; i < num_aggr; i++) {
834 const mpool_elem_t *pool_elem = pool_elem_get(aggr_conf[i].pool);
836 if (unlikely(!pool_elem || !pool_allocated(pool_elem) ||
838 *err_str =
"Invalid pool for event aggregator!";
842 int subpool = pool_find_subpool(pool_elem, aggr_conf[i].max_size);
844 if (unlikely(subpool < 0)) {
845 *err_str =
"No suitable subpool found for event aggregator!";
849 odp_aggr_config[i].pool = pool_elem->
odp_pool[subpool];
850 odp_aggr_config[i].max_tmo_ns = aggr_conf[i].
max_tmo_ns;
851 odp_aggr_config[i].max_size = aggr_conf[i].
max_size;
854 em_event_type_t evtype_major = em_event_type_major(aggr_conf[i].event_type);
856 switch (evtype_major) {
858 odp_aggr_config[i].event_type = ODP_EVENT_BUFFER;
861 odp_aggr_config[i].event_type = ODP_EVENT_PACKET;
864 odp_aggr_config[i].event_type = ODP_EVENT_TIMEOUT;
870 odp_aggr_config[i].event_type = ODP_EVENT_ANY;
874 *err_str =
"Unsupported event type for event aggregator!";
882static int queue_create_check_sched(
const em_queue_param_t *param,
const char **err_str)
887 if (unlikely(queue_group_elem == NULL || !queue_group_allocated(queue_group_elem))) {
888 *err_str =
"Invalid queue group!";
895 if (unlikely(!ag_elem || !atomic_group_allocated(ag_elem))) {
896 *err_str =
"Invalid atomic group!";
902 *err_str =
"Invalid queue priority!";
906 const odp_event_aggr_capability_t *odp_aggr_capa =
907 &
em_shm->queue_tbl.odp_schedule_capability.aggr;
909 int err = queue_create_check_aggr(param, odp_aggr_capa, err_str );
917static int queue_create_check_unsched(
const em_queue_param_t *param,
const char **err_str)
921 *err_str =
"Invalid priority for unsched queue!";
925 *err_str =
"Queue group not used with unsched queues!";
929 *err_str =
"Atomic group not used with unsched queues!";
933 const odp_event_aggr_capability_t *odp_aggr_capa =
934 &
em_shm->queue_tbl.odp_queue_capability.plain.aggr;
936 int err = queue_create_check_aggr(param, odp_aggr_capa, err_str );
944static int queue_create_check_local(
const em_queue_param_t *param,
const char **err_str)
948 *err_str =
"Queue group not used with local queues!";
952 *err_str =
"Atomic group not used with local queues!";
956 *err_str =
"Invalid queue priority!";
959 if (unlikely(param->
num_aggr > 0)) {
960 *err_str =
"Event aggregation not supported with local queues!";
967static int queue_create_check_output(
const em_queue_param_t *param,
const char **err_str)
971 *err_str =
"Queue group not used with output queues!";
975 *err_str =
"Atomic group not used with output queues!";
978 if (unlikely(param->
num_aggr > 0)) {
979 *err_str =
"Event aggregation not supported with output queues!";
983 *err_str =
"Invalid output queue conf: output function missing!";
990static int queue_create_check_args(
const em_queue_param_t *param,
const char **err_str)
994 *err_str =
"Atomic group can only be used with atomic queues!";
1002 return queue_create_check_sched(param, err_str);
1005 switch (param->
type) {
1007 return queue_create_check_unsched(param, err_str);
1009 return queue_create_check_local(param, err_str);
1011 return queue_create_check_output(param, err_str);
1013 *err_str =
"Unknown queue type";
1035em_queue_t queue_create_param(
const char *name,
const em_queue_param_t *param,
1036 const char **err_str )
1038 int err = queue_create_check_args(param, err_str );
1046 em_queue_t queue_req = param->
queue;
1047 em_queue_t queue = queue_alloc(queue_req, err_str );
1053 if (unlikely(queue_req !=
EM_QUEUE_UNDEF && queue_req != queue)) {
1055 *err_str =
"Failed to allocate the requested queue!";
1061 if (unlikely(!queue_elem)) {
1063 *err_str =
"Queue elem NULL!";
1070 err = queue_setup(name, param, queue_elem, err_str);
1071 if (unlikely(err)) {
1085 em_queue_t queue = (em_queue_t)(uintptr_t)queue_elem->
queue;
1088 if (unlikely(!queue_allocated(queue_elem))) {
1089 *err_str =
"Invalid queue (not allocated)";
1097 *err_str =
"Cannot delete aggregator queue, delete parent queue instead";
1101 old_state = queue_elem->
state;
1107 ret = queue_state_change__check(old_state, new_state,
1109 if (unlikely(ret !=
EM_OK)) {
1110 *err_str =
"Invalid queue state transition for delete";
1121 if (unlikely(queue_group_elem == NULL ||
1122 !queue_group_allocated(queue_group_elem))) {
1123 *err_str =
"Invalid queue group";
1128 queue_group_rem_queue_list(queue_group_elem, queue_elem);
1132 odp_ticketlock_t *
const lock = &queue_elem->output.
lock;
1135 odp_ticketlock_lock(lock);
1137 output_queue_drain(queue_elem);
1138 odp_ticketlock_unlock(lock);
1146 odp_ticketlock_lock(&
em_shm->queue_tbl.output_queue_lock);
1147 em_shm->queue_tbl.output_queue_idx_free[q_out->
idx] =
true;
1148 odp_atomic_dec_u32(&
em_shm->queue_tbl.output_queue_count);
1149 odp_ticketlock_unlock(&
em_shm->queue_tbl.output_queue_lock);
1152 if (queue_elem->
odp_queue != ODP_QUEUE_INVALID &&
1159 int err = odp_queue_destroy(queue_elem->
odp_queue);
1161 if (unlikely(err)) {
1162 *err_str =
"odp_queue_destroy() failed";
1167 queue_elem->
odp_queue = ODP_QUEUE_INVALID;
1171 int err = queue_free_aggr_all(queue_elem);
1173 if (unlikely(err)) {
1176 "Failed to free aggregator queues of EM-Q:%" PRI_QUEUE " err:%d",
1182 em_shm->queue_tbl.name[queue_hdl2idx(queue)][0] =
'\0';
1185 atomic_group_remove_queue(queue_elem);
1187 ret = queue_free(queue);
1188 if (unlikely(ret !=
EM_OK)) {
1189 *err_str =
"queue_free() failed";
1201 const char **err_str )
1206 queue_setup_common(name, param, q_elem);
1208 switch (param->
type) {
1212 ret = queue_setup_scheduled(param, q_elem, err_str);
1215 ret = queue_setup_unscheduled(param, q_elem, err_str);
1218 ret = queue_setup_local(param, q_elem, err_str);
1221 ret = queue_setup_output(param, q_elem, err_str);
1224 *err_str =
"Queue setup: unknown queue type";
1244 const em_queue_t queue = (em_queue_t)(uintptr_t)q_elem->
queue;
1245 char *
const qname = &
em_shm->queue_tbl.name[queue_hdl2idx(queue)][0];
1255 "%s%" PRI_QUEUE "", EM_Q_BASENAME, queue);
1260 q_elem->
type = (uint8_t)param->
type;
1292 odp_queue_param_t *odp_queue_param )
1301 odp_queue_param->nonblocking = ODP_NONBLOCKING_WF;
1303 odp_queue_param->nonblocking = ODP_NONBLOCKING_LF;
1306 odp_queue_param->enq_mode = ODP_QUEUE_OP_MT_UNSAFE;
1308 odp_queue_param->deq_mode = ODP_QUEUE_OP_MT_UNSAFE;
1316 unsigned int size =
em_shm->
opt.queue.min_events_default;
1319 odp_queue_param->size = size;
1331 const odp_queue_param_t *odp_queue_param)
1333 char odp_name[ODP_QUEUE_NAME_LEN];
1334 odp_queue_t odp_queue;
1336 (void)queue_name(q_elem, odp_name,
sizeof(odp_name));
1338 odp_queue = odp_queue_create(odp_name, odp_queue_param);
1339 if (unlikely(odp_queue == ODP_QUEUE_INVALID))
1363 uint32_t num_aggr,
const char **err_str )
1365 odp_queue_t odp_aggr_queues[num_aggr];
1366 em_queue_t aggr_queues[num_aggr];
1369 em_queue_t queue = (em_queue_t)(uintptr_t)q_elem->
queue;
1370 char *
const qname = &
em_shm->queue_tbl.name[queue_hdl2idx(queue)][0];
1373 for (uint32_t i = 0; i < num_aggr; i++) {
1374 odp_aggr_queues[i] = odp_queue_aggr(q_elem->
odp_queue, i);
1375 if (unlikely(odp_aggr_queues[i] == ODP_QUEUE_INVALID)) {
1376 *err_str =
"Q-setup-aggr: failed to get ODP event aggregator!";
1382 for (uint32_t i = 0; i < num_aggr; i++) {
1383 aggr_queues[i] = queue_aggr_alloc(err_str );
1384 aggr_qelems[i] = queue_elem_get(aggr_queues[i]);
1387 aggr_qelems[i] == NULL)) {
1388 *err_str =
"Q-setup-aggr: failed to allocate aggregator queue!";
1389 for (uint32_t j = 0; j < i; j++)
1390 queue_aggr_free(aggr_qelems[j]);
1396 q_elem->aggr_parent.
num_aggr = num_aggr;
1399 for (uint32_t i = 0; i < num_aggr; i++) {
1400 const em_queue_t aggr_queue = aggr_queues[i];
1402 int aggr_idx = queue_hdl2idx(aggr_queue);
1403 char *
const aggr_name = &
em_shm->queue_tbl.name[aggr_idx][0];
1415 aggr_name_maxlen, qname);
1423 aggr_qelem->
odp_queue = odp_aggr_queues[i];
1435 aggr_qelem->
eo_ctx = NULL;
1441 aggr_qelem->aggr.
pool = aggr_conf[i].
pool;
1448 for (uint32_t i = 0; i < num_aggr; i++)
1449 q_elem->aggr_parent.
aggr_queues[i] = (uint32_t)(uintptr_t)aggr_queues[i];
1461 const char **err_str )
1467 if (unlikely(qgrp_elem == NULL)) {
1468 *err_str =
"Q-setup-sched: invalid queue group!";
1479 odp_queue_param_t odp_queue_param;
1481 odp_schedule_sync_t odp_schedule_sync = ODP_SCHED_SYNC_PARALLEL;
1482 odp_schedule_prio_t odp_prio = odp_schedule_min_prio();
1485 odp_queue_param_init(&odp_queue_param);
1487 queue_setup_odp_common(param, &odp_queue_param );
1489 err = scheduled_queue_type_em2odp(param->
type, &odp_schedule_sync );
1490 if (unlikely(err)) {
1491 *err_str =
"Q-setup-sched: invalid queue type!";
1495 err = prio_em2odp(param->
prio, &odp_prio );
1496 if (unlikely(err)) {
1497 *err_str =
"Q-setup-sched: invalid queue priority!";
1501 odp_queue_param.type = ODP_QUEUE_TYPE_SCHED;
1502 odp_queue_param.sched.prio = odp_prio;
1503 odp_queue_param.sched.sync = odp_schedule_sync;
1507 const odp_schedule_capability_t *odp_sched_capa =
1508 &
em_shm->queue_tbl.odp_schedule_capability;
1514 if (odp_queue_param.nonblocking == ODP_NONBLOCKING_LF &&
1515 odp_sched_capa->lockfree_queues == ODP_SUPPORT_NO) {
1516 *err_str =
"Q-setup-sched: non-blocking, lock-free sched queues unavailable";
1519 if (odp_queue_param.nonblocking == ODP_NONBLOCKING_WF &&
1520 odp_sched_capa->waitfree_queues == ODP_SUPPORT_NO) {
1521 *err_str =
"Q-setup-sched: non-blocking, wait-free sched queues unavailable";
1524 if (odp_queue_param.enq_mode != ODP_QUEUE_OP_MT ||
1525 odp_queue_param.deq_mode != ODP_QUEUE_OP_MT) {
1526 *err_str =
"Q-setup-sched: invalid flag: scheduled queues must be MT-safe";
1537 odp_queue_param.context = q_elem;
1543 odp_queue_param.context_len =
sizeof(*q_elem);
1553 err = queue_setup_odp_aggr(param->
aggr_conf ,
1555 num_aggr, err_str );
1558 odp_queue_param.num_aggr = num_aggr;
1559 odp_queue_param.aggr = &odp_aggr_config[0];
1563 err = create_odp_queue(q_elem, &odp_queue_param);
1564 if (unlikely(err)) {
1565 *err_str =
"Q-setup-sched: scheduled odp queue creation failed!";
1570 err = queue_setup_aggr(q_elem, param->
aggr_conf, num_aggr, err_str );
1571 if (unlikely(err)) {
1572 err = odp_queue_destroy(q_elem->
odp_queue);
1574 EM_LOG(EM_LOG_ERR,
"ODP queue destroy failed:%d", err);
1583 queue_group_add_queue_list(qgrp_elem, q_elem);
1595 const char **err_str )
1604 q_elem->
state = EM_QUEUE_STATE_UNSCHEDULED;
1609 odp_queue_param_t odp_queue_param;
1611 const odp_queue_capability_t *odp_queue_capa =
1612 &
em_shm->queue_tbl.odp_queue_capability;
1615 odp_queue_param_init(&odp_queue_param);
1617 queue_setup_odp_common(param, &odp_queue_param);
1619 odp_queue_param.type = ODP_QUEUE_TYPE_PLAIN;
1621 odp_queue_param.order = ODP_QUEUE_ORDER_IGNORE;
1627 if (odp_queue_param.nonblocking == ODP_NONBLOCKING_LF &&
1628 odp_queue_capa->plain.lockfree.max_num == 0) {
1629 *err_str =
"Q-setup-unsched: non-blocking, lock-free unsched queues unavailable";
1632 if (odp_queue_param.nonblocking == ODP_NONBLOCKING_WF &&
1633 odp_queue_capa->plain.waitfree.max_num == 0) {
1634 *err_str =
"Q-setup-unsched: non-blocking, wait-free unsched queues unavailable";
1644 odp_queue_param.context = q_elem;
1650 odp_queue_param.context_len =
sizeof(*q_elem);
1660 err = queue_setup_odp_aggr(param->
aggr_conf ,
1662 num_aggr, err_str );
1665 odp_queue_param.num_aggr = num_aggr;
1666 odp_queue_param.aggr = &odp_aggr_config[0];
1670 err = create_odp_queue(q_elem, &odp_queue_param);
1671 if (unlikely(err)) {
1672 *err_str =
"Q-setup-unsched: plain odp queue creation failed!";
1677 err = queue_setup_aggr(q_elem, param->
aggr_conf, num_aggr, err_str );
1678 if (unlikely(err)) {
1679 err = odp_queue_destroy(q_elem->
odp_queue);
1681 EM_LOG(EM_LOG_ERR,
"ODP queue destroy failed:%d", err);
1697 const char **err_str )
1718 const char **err_str )
1722 uint32_t nbr_output_queues;
1725 nbr_output_queues = odp_atomic_fetch_add_u32(&queue_tbl->output_queue_count, 1) + 1;
1728 *err_str =
"Q-setup-output: too many output queues";
1738 q_elem->
state = EM_QUEUE_STATE_UNSCHEDULED;
1740 if (unlikely(output_conf->
output_fn == NULL)) {
1741 *err_str =
"Q-setup-output: invalid output function";
1745 odp_ticketlock_lock(&
em_shm->queue_tbl.output_queue_lock);
1747 if (
em_shm->queue_tbl.output_queue_idx_free[i]) {
1748 em_shm->queue_tbl.output_queue_idx_free[i] =
false;
1749 q_elem->output.
idx = i;
1753 odp_ticketlock_unlock(&
em_shm->queue_tbl.output_queue_lock);
1762 em_event_t args_event;
1769 *err_str =
"Q-setup-output: alloc output_fn_args fails";
1780 odp_ticketlock_init(&q_elem->output.
lock);
1788 odp_queue_param_t odp_queue_param;
1790 const odp_queue_capability_t *odp_queue_capa =
1791 &
em_shm->queue_tbl.odp_queue_capability;
1794 odp_queue_param_init(&odp_queue_param);
1796 queue_setup_odp_common(param, &odp_queue_param);
1798 odp_queue_param.type = ODP_QUEUE_TYPE_PLAIN;
1799 odp_queue_param.order = ODP_QUEUE_ORDER_KEEP;
1802 if (odp_queue_param.nonblocking == ODP_NONBLOCKING_LF &&
1803 odp_queue_capa->plain.lockfree.max_num == 0) {
1804 *err_str =
"Q-setup-output: non-blocking, lock-free unsched queues unavailable";
1807 if (odp_queue_param.nonblocking == ODP_NONBLOCKING_WF &&
1808 odp_queue_capa->plain.waitfree.max_num == 0) {
1809 *err_str =
"Q-setup-output: non-blocking, wait-free unsched queues unavailable";
1814 odp_queue_param.deq_mode = ODP_QUEUE_OP_MT_UNSAFE;
1817 odp_queue_param.context = NULL;
1819 int err = create_odp_queue(q_elem, &odp_queue_param);
1821 if (unlikely(err)) {
1822 *err_str =
"Q-setup-output: plain odp queue creation failed!";
1833 odp_atomic_dec_u32(&queue_tbl->output_queue_count);
1857 uint32_t state_diff;
1860 state_diff = new_state - old_state;
1862 state_diff = old_state - new_state;
1875 if (new_state == old_state &&
1880 err = queue_state_change__check(old_state, new_state, is_setup);
1881 if (unlikely(err !=
EM_OK))
1884 q_elem->
state = new_state;
1888 uint32_t num = q_elem->aggr_parent.
num_aggr;
1890 for (uint32_t i = 0; i < num; i++) {
1891 em_queue_t aq = (em_queue_t)(uintptr_t)q_elem->aggr_parent.
aggr_queues[i];
1894 if (likely(aggr_qelem != NULL))
1895 aggr_qelem->
state = new_state;
1907 em_status_t err = queue_state_set(q_elem, new_state);
1910 "EM-Q:%" PRI_QUEUE " inv. state: %d=>%d",
1927 odp_ticketlock_lock(&eo_elem->
lock);
1929 list_for_each(&eo_elem->
queue_list, list_node) {
1930 q_elem = eo_queue_node_to_queue_elem(list_node);
1931 err = queue_state_set(q_elem, new_state);
1932 if (unlikely(err !=
EM_OK))
1936 odp_ticketlock_unlock(&eo_elem->
lock);
1938 if (unlikely(err !=
EM_OK)) {
1939 uint32_t queue_u32 = q_elem ? q_elem->
queue : 0;
1943 "EM-Q:%" PRIx32
" inv. state: %d=>%d",
1944 queue_u32, state, new_state);
1964 "queue_state_change()->READY fails EM-Q:%" PRI_QUEUE "",
1983 "queue_state_change_all()->READY fails EO:%" PRI_EO "",
2003 "queue_state_change()->BIND fails, Q:%" PRI_QUEUE "",
2022 "queue_state_change_all()->BIND: EO:%" PRI_EO "",
2028void print_queue_elem_info(
void)
2030 EM_PRINT(
"queue-elem size: %zu B\n",
2033 DBG_PRINT(
"\t\t\toffset\tsize\n"
2034 "\t\t\t------\t----\n"
2035 "valid_check:\t\t%3zu B\t%2zu B\n"
2036 "flags:\t\t\t%3zu B\t%2zu B\n"
2037 "state:\t\t\t%3zu B\t%2zu B\n"
2038 "priority:\t\t%3zu B\t%2zu B\n"
2039 "type:\t\t\t%3zu B\t%2zu B\n"
2040 "max_events:\t\t%3zu B\t%2zu B\n"
2041 "eo:\t\t\t%3zu B\t%2zu B\n"
2042 "queue:\t\t\t%3zu B\t%2zu B\n"
2043 "odp_queue:\t\t%3zu B\t%2zu B\n"
2044 "context:\t\t%3zu B\t%2zu B\n"
2046 " rcv_fn:\t\t%3zu B\t%2zu B\n"
2047 " rcv_multi_fn:\t\t%3zu B\t%2zu B\n"
2049 "eo_ctx:\t\t\t%3zu B\t%2zu B\n"
2050 "agrp {\t\t\t%3zu B\t%2zu B\n"
2051 " .atomic_grp:\t\t%3zu B\t%2zu B\n"
2052 " .agrp_node:\t\t%3zu B\t%2zu B\n"
2055 " aggr_parent {\t\t%3zu B\t%2zu B\n"
2056 " .num_aggr:\t\t%3zu B\t%2zu B\n"
2057 " .aggr_queues[]:\t%3zu B\t%2zu B\n"
2059 " aggr {\t\t%3zu B\t%2zu B\n"
2060 " .parent_queue:\t%3zu B\t%2zu B\n"
2061 " .pool:\t\t%3zu B\t%2zu B\n"
2062 " .max_tmo_ns:\t%3zu B\t%2zu B\n"
2063 " .max_size:\t\t%3zu B\t%2zu B\n"
2064 " .event_type:\t%3zu B\t%2zu B\n"
2066 " output {\t\t%3zu B\t%2zu B\n"
2067 " .conf:\t\t%3zu B\t%2zu B\n"
2068 " .args_event:\t%3zu B\t%2zu B\n"
2069 " .idx:\t\t%3zu B\t%2zu B\n"
2070 " .lock:\t\t%3zu B\t%2zu B\n"
2073 "eo_elem:\t\t%3zu B\t%2zu B\n"
2074 "queue_group:\t\t%3zu B\t%2zu B\n"
2075 "eo_queue_node:\t\t%3zu B\t%2zu B\n"
2076 "qgrp_node:\t\t%3zu B\t%2zu B\n"
2077 "queue_pool_elem:\t%3zu B\t%2zu B\n"
2078 " <pad>\t\t\t%3zu B\n"
2079 "end:\t\t\t%3zu B\t%2zu B\n",
2123 sizeof_field(
queue_elem_t, output.output_fn_args_event),
2146format_qid_range(
unsigned int num_queues, uint16_t first_id, uint16_t last_id,
2147 char first_dec[24],
char last_dec[24],
2148 char first_hex[24],
char last_hex[24])
2152 if (first_id != INVALID_QUEUE_ID) {
2153 snprintf(first_dec, 24,
"%u", first_id);
2154 snprintf(first_hex, 24,
"0x%x", first_id);
2156 if (last_id != INVALID_QUEUE_ID) {
2157 snprintf(last_dec, 24,
"%u", last_id);
2158 snprintf(last_hex, 24,
"0x%x", last_id);
2162void print_queue_capa(
void)
2164 const odp_queue_capability_t *queue_capa =
2165 &
em_shm->queue_tbl.odp_queue_capability;
2166 const odp_schedule_capability_t *sched_capa =
2167 &
em_shm->queue_tbl.odp_schedule_capability;
2169 char plain_sz[24] =
"n/a";
2170 char plain_lf_sz[24] =
"n/a";
2171 char plain_wf_sz[24] =
"n/a";
2172 char sched_sz[24] =
"nolimit";
2174 char first_static_qid[24] =
"n/a";
2175 char last_static_qid[24] =
"n/a";
2176 char first_dyn_qid[24] =
"n/a";
2177 char last_dyn_qid[24] =
"n/a";
2178 char first_aggr_qid[24] =
"n/a";
2179 char last_aggr_qid[24] =
"n/a";
2180 char first_static_qid_hex[24] =
"n/a";
2181 char last_static_qid_hex[24] =
"n/a";
2182 char first_dyn_qid_hex[24] =
"n/a";
2183 char last_dyn_qid_hex[24] =
"n/a";
2184 char first_aggr_qid_hex[24] =
"n/a";
2185 char last_aggr_qid_hex[24] =
"n/a";
2187 const unsigned int max_queues =
em_shm->queue_tbl.max_queue_num;
2189 if (queue_capa->plain.max_size > 0)
2190 snprintf(plain_sz,
sizeof(plain_sz),
"%u",
2191 queue_capa->plain.max_size);
2192 if (queue_capa->plain.lockfree.max_size > 0)
2193 snprintf(plain_lf_sz,
sizeof(plain_lf_sz),
"%u",
2194 queue_capa->plain.lockfree.max_size);
2195 if (queue_capa->plain.waitfree.max_size > 0)
2196 snprintf(plain_wf_sz,
sizeof(plain_wf_sz),
"%u",
2197 queue_capa->plain.waitfree.max_size);
2199 if (sched_capa->max_queue_size > 0)
2200 snprintf(sched_sz,
sizeof(sched_sz),
"%u",
2201 sched_capa->max_queue_size);
2203 format_qid_range(
em_shm->
opt.queue.num_static,
2206 first_static_qid, last_static_qid,
2207 first_static_qid_hex, last_static_qid_hex);
2209 format_qid_range(
em_shm->
opt.queue.num_dynamic,
2212 first_dyn_qid, last_dyn_qid,
2213 first_dyn_qid_hex, last_dyn_qid_hex);
2215 format_qid_range(
em_shm->
opt.queue.num_aggr,
2218 first_aggr_qid, last_aggr_qid,
2219 first_aggr_qid_hex, last_aggr_qid_hex);
2223 uint16_t queue_range_first =
em_shm->
opt.queue.num_static ?
2235 EM_PRINT(
"ODP Queue Capabilities\n"
2236 "----------------------\n"
2237 " Max number of ODP queues: %u\n"
2238 " Max number of ODP ordered locks per queue: %u\n"
2239 " Max number of ODP scheduling groups: %u\n"
2240 " Max number of ODP scheduling priorities: %u\n"
2242 " blocking: count: %6u size: %6s\n"
2243 " nonblocking-lf: count: %6u size: %6s\n"
2244 " nonblocking-wf: count: %6u size: %6s\n"
2246 " blocking: count: %6u size: %6s\n"
2247 " nonblocking-lf: %ssupported\n"
2248 " nonblocking-wf: %ssupported\n\n",
2249 queue_capa->max_queues, sched_capa->max_ordered_locks,
2250 sched_capa->max_groups, sched_capa->max_prios,
2251 queue_capa->plain.max_num, plain_sz,
2252 queue_capa->plain.lockfree.max_num, plain_lf_sz,
2253 queue_capa->plain.waitfree.max_num, plain_wf_sz,
2254 sched_capa->max_queues, sched_sz,
2255 sched_capa->lockfree_queues == ODP_SUPPORT_NO ?
"not " :
"",
2256 sched_capa->waitfree_queues == ODP_SUPPORT_NO ?
"not " :
"");
2258 EM_PRINT(
"EM Queues\n"
2260 " Max number of EM queues: %d (0x%x)\n"
2261 " EM queue handle offset: %d (0x%x)\n"
2262 " EM queue range: [%u - %u] ([0x%x - 0x%x])\n"
2263 " static range: [%s - %s] ([%s - %s])\n"
2264 " internal range: [%d - %d] ([0x%x - 0x%x])\n"
2265 " dynamic range: [%s - %s] ([%s - %s])\n"
2266 " aggreg. range: [%s - %s] ([%s - %s])\n"
2268 max_queues, max_queues,
2270 queue_range_first, queue_range_last,
2271 queue_range_first, queue_range_last,
2272 first_static_qid, last_static_qid,
2273 first_static_qid_hex, last_static_qid_hex,
2276 first_dyn_qid, last_dyn_qid,
2277 first_dyn_qid_hex, last_dyn_qid_hex,
2278 first_aggr_qid, last_aggr_qid,
2279 first_aggr_qid_hex, last_aggr_qid_hex);
2282void print_queue_prio_info(
void)
2284 #define MAXPRIOBUF 128
2285 char buf[MAXPRIOBUF];
2290 int num = snprintf(&buf[pos], MAXPRIOBUF - pos,
"%d%c",
2293 if (num < 0 || num >= (MAXPRIOBUF - pos))
2298 buf[MAXPRIOBUF - 1] = 0;
2299 EM_PRINT(
" Current queue priority map: [%s]\n", buf);
2302unsigned int queue_count(
void)
2308 char name[],
const size_t maxlen)
2310 em_queue_t queue = (em_queue_t)(uintptr_t)q_elem->
queue;
2311 const char *queue_name = &
em_shm->queue_tbl.name[queue_hdl2idx(queue)][0];
2314 if (maxlen - 1 < len)
2318 memcpy(name, queue_name, len);
2324static void queue_init_prio_legacy(
int minp,
int maxp)
2328 int def = odp_schedule_default_prio();
2332 "queue_prio_e values / EM_QUEUE_PRIO_NUM mismatch!\n");
2347static void queue_init_prio_adaptive(
int minp,
int maxp,
int nump)
2350 double cur = (double)minp;
2364static int queue_init_prio_custom(
int minp,
int maxp)
2376static int queue_init_prio_map(
int minp,
int maxp,
int nump)
2382 switch (
em_shm->
opt.queue.priority.map_mode) {
2384 queue_init_prio_legacy(minp, maxp);
2387 queue_init_prio_adaptive(minp, maxp, nump);
2390 if (queue_init_prio_custom(minp, maxp) != 0)
2394 EM_PRINT(
"Unknown map_mode %d!\n",
em_shm->
opt.queue.priority.map_mode);
2398 EM_PRINT(
" EM uses %d priorities, runtime %d (%d-%d)\n",
2400 print_queue_prio_info();
2421 case EM_QUEUE_STATE_UNSCHEDULED:
2434 const char *type_str;
2441 type_str =
"ATOMIC";
2444 type_str =
"PARALLEL";
2447 type_str =
"ORDERED";
2456 type_str =
"OUTPUT";
2459 type_str =
"UNKNOWN";
2466#define QUEUE_INFO_HDR_STR \
2467"Number of queues: %d\n\n" \
2468"Handle Name Priority Type State Qgrp" \
2469" Agrp EO Multi-rcv Max-events Ctx\n" \
2470"---------------------------------------------------------------------------" \
2471"----------------------------------------------------\n" \
2474#define QUEUE_INFO_LEN 128
2476#define QUEUE_INFO_FMT \
2477"%-10" PRI_QUEUE "%-32s%-10" PRI_QPRIO "%-10s%-9s%-10" PRI_QGRP "%-10" PRI_AGRP \
2478"%-10" PRI_EO "%-11c%-12d%-3c\n"
2480void print_queue_info(
void)
2496 const int q_info_buf_len = (q_num + 10) * QUEUE_INFO_LEN + 1;
2497 char q_info_buf[q_info_buf_len];
2500 q_elem = queue_elem_get(q);
2502 if (unlikely(q_elem == NULL || !queue_allocated(q_elem))) {
2508 em_eo_t eo = (em_eo_t)(uintptr_t)q_elem->
eo;
2514 n_print = snprintf(q_info_buf + len,
2515 q_info_buf_len - len,
2518 queue_type_str(q_elem->
type),
2519 queue_state_str(q_elem->
state),
2526 if (n_print >= q_info_buf_len - len)
2535 EM_PRINT(
"No EM queue!\n");
2543 q_info_buf[len] =
'\0';
2544 EM_PRINT(QUEUE_INFO_HDR_STR, q_num, q_info_buf);
#define INTERNAL_ERROR(error, escope, fmt,...)
#define RETURN_ERROR_IF(cond, error, escope, fmt,...)
#define EM_CHECK_INIT_CALLED
ENV_LOCAL em_locm_t em_locm
#define EM_QUEUE_LOCAL_MULTI_MAX_BURST
#define EM_QUEUE_MAX_AGGR
#define EM_QUEUE_PRIO_NUM
#define EM_QUEUE_NAME_LEN
#define EM_MAX_OUTPUT_QUEUES
#define EM_QUEUE_RANGE_OFFSET
#define EM_QUEUE_GROUP_UNDEF
#define EM_ATOMIC_GROUP_UNDEF
em_event_t em_alloc(uint32_t size, em_event_type_t type, em_pool_t pool)
void em_free_multi(em_event_t events[], int num)
void em_free(em_event_t event)
void * em_event_pointer(em_event_t event)
@ EM_EVENT_TYPE_TIMER_IND
#define EM_QUEUE_FLAG_ENQ_NOT_MTSAFE
#define EM_QUEUE_PRIO_UNDEF
#define EM_QUEUE_FLAG_MASK
#define EM_QUEUE_FLAG_NONBLOCKING_WF
#define EM_QUEUE_FLAG_DEFAULT
#define EM_QUEUE_FLAG_DEQ_NOT_MTSAFE
#define EM_QUEUE_FLAG_NONBLOCKING_LF
em_queue_t em_queue_first(unsigned int *num)
em_queue_t em_queue_next(void)
@ EM_QUEUE_TYPE_UNSCHEDULED
local_queues_t local_queues
output_queue_track_t output_queue_track
em_output_func_t output_fn
em_event_type_t event_type
uint32_t __internal_check
em_queue_aggr_conf_t * aggr_conf
em_output_queue_conf_t output_conf
em_atomic_group_t atomic_group
em_queue_group_t queue_group
struct em_shm_t::@53 queue_prio
int map[EM_QUEUE_PRIO_NUM]
odp_atomic_u32_t queue_count
odp_pool_t odp_pool[EM_MAX_SUBPOOLS]
em_event_type_t event_type
em_event_type_t event_type
uint32_t aggr_queues[EM_QUEUE_MAX_AGGR]
em_atomic_group_t atomic_group
em_output_queue_conf_t output_conf
em_event_t output_fn_args_event
q_elem_atomic_group_t agrp
objpool_elem_t queue_pool_elem
em_receive_multi_func_t receive_multi_func
em_queue_group_t queue_group
em_receive_func_t receive_func
odp_schedule_group_t odp_sched_group
uint16_t last_internal_queue_id
uint16_t shared_internal_queue_id
odp_schedule_capability_t odp_schedule_capability
odp_queue_capability_t odp_queue_capability
uint16_t first_aggr_queue_id
uint16_t first_internal_queue_id
char(* name)[EM_QUEUE_NAME_LEN]
bool output_queue_idx_free[EM_MAX_OUTPUT_QUEUES]
uint16_t last_static_queue_id
uint16_t first_dyn_queue_id
uint16_t last_aggr_queue_id
uint16_t first_static_queue_id
uint16_t last_dyn_queue_id