42 void (*f_done_callback)(
void *arg_ptr);
45 int exclude_current_core;
58 eo_start_done_callback(
void *args);
60 eo_start_sync_done_callback(
void *args);
63 eo_stop_done_callback(
void *args);
65 eo_stop_sync_done_callback(
void *args);
70 eo_remove_queue_done_callback(
void *args);
73 eo_remove_queue_sync_local(
const eo_elem_t *eo_elem,
76 eo_remove_queue_sync_done_callback(
void *args);
79 eo_remove_queue_all_local(
const eo_elem_t *eo_elem,
int delete_queues);
81 eo_remove_queue_all_done_callback(
void *args);
84 eo_remove_queue_all_sync_local(
const eo_elem_t *eo_elem,
int delete_queues);
86 eo_remove_queue_all_sync_done_callback(
void *args);
91 return (
eo_elem_t *)((uintptr_t)eo_pool_elem -
99 const uint32_t objpool_subpools = MIN(4, OBJSUBPOOLS_MAX);
101 memset(eo_tbl, 0,
sizeof(
eo_tbl_t));
107 eo_elem->
eo = eo_idx2hdl(i);
109 env_spinlock_init(&eo_elem->
lock);
111 eo_elem->
stash = ODP_STASH_INVALID;
114 ret = objpool_init(&eo_pool->objpool, objpool_subpools);
119 objpool_add(&eo_pool->objpool, i % objpool_subpools,
122 env_atomic32_init(&
em_shm->eo_count);
134 if (unlikely(eo_pool_elem == NULL))
137 eo_elem = eo_poolelem2eo(eo_pool_elem);
138 env_atomic32_inc(&
em_shm->eo_count);
148 if (unlikely(eo_elem == NULL))
153 objpool_add(&
em_shm->eo_pool.objpool,
155 env_atomic32_dec(&
em_shm->eo_count);
171 if (unlikely(err !=
EM_OK))
174 q_elem->
max_events = (uint16_t)eo_elem->max_events;
176 q_elem->flags.use_multi_rcv = eo_elem->use_multi_rcv ?
true :
false;
177 if (eo_elem->use_multi_rcv)
182 q_elem->
eo = (uint16_t)(uintptr_t)eo_elem->
eo;
185 q_elem->
state = new_state;
188 env_spinlock_lock(&eo_elem->
lock);
191 env_spinlock_unlock(&eo_elem->
lock);
204 if (unlikely(err !=
EM_OK))
210 q_elem->
state = new_state;
225 env_spinlock_lock(&eo_elem->
lock);
226 err = eo_rem_queue_locked(eo_elem, q_elem);
227 env_spinlock_unlock(&eo_elem->
lock);
229 if (unlikely(err !=
EM_OK))
240 eo_rem_queue_all(
eo_elem_t *
const eo_elem)
248 env_spinlock_lock(&eo_elem->
lock);
251 list_for_each(&eo_elem->
queue_list, pos, list_node) {
252 q_elem = list_node_to_queue_elem(list_node);
254 err = eo_rem_queue_locked(eo_elem, q_elem);
255 if (unlikely(err !=
EM_OK))
259 env_spinlock_unlock(&eo_elem->
lock);
269 eo_delete_queue_all(
eo_elem_t *
const eo_elem)
277 env_spinlock_lock(&eo_elem->
lock);
280 list_for_each(&eo_elem->
queue_list, pos, list_node) {
281 q_elem = list_node_to_queue_elem(list_node);
283 err = eo_rem_queue_locked(eo_elem, q_elem);
284 if (unlikely(err !=
EM_OK))
288 if (unlikely(err !=
EM_OK))
292 env_spinlock_unlock(&eo_elem->
lock);
298 eo_start_local_req(
eo_elem_t *
const eo_elem,
303 eo_local_func_call_param_init(¶m);
304 param.eo_elem = eo_elem;
307 param.ev_id = EO_START_LOCAL_REQ;
308 param.f_done_callback = eo_start_done_callback;
309 param.num_notif = num_notif;
310 param.notif_tbl = notif_tbl;
311 param.exclude_current_core =
EM_FALSE;
312 param.sync_operation =
false;
314 return eo_local_func_call_req(¶m);
322 eo_start_done_callback(
void *args)
328 if (unlikely(eo_elem == NULL)) {
330 EM_ESCOPE_EO_START_DONE_CB,
335 if (check_eo_local_status(loc_func_retvals) ==
EM_OK) {
349 eo_start_sync_local_req(
eo_elem_t *
const eo_elem)
353 eo_local_func_call_param_init(¶m);
354 param.eo_elem = eo_elem;
357 param.ev_id = EO_START_SYNC_LOCAL_REQ;
358 param.f_done_callback = eo_start_sync_done_callback;
360 param.notif_tbl = NULL;
361 param.exclude_current_core =
EM_TRUE;
362 param.sync_operation =
true;
364 return eo_local_func_call_req(¶m);
372 eo_start_sync_done_callback(
void *args)
379 if (unlikely(eo_elem == NULL)) {
381 EM_ESCOPE_EO_START_SYNC_DONE_CB,
386 if (check_eo_local_status(loc_func_retvals) ==
EM_OK) {
415 const uint16_t qidx = queue_hdl2idx(queue);
419 if (unlikely(eo_elem == NULL))
422 env_spinlock_lock(&eo_elem->
lock);
424 for (
int i = 0; i < num; i++) {
425 entry_tbl[i].qidx = qidx;
426 entry_tbl[i].evptr = evhdl_tbl[i].evptr;
430 int ret = odp_stash_put_u64(eo_elem->
stash, &entry_tbl[0].u64, num);
432 if (unlikely(ret < 0))
435 env_spinlock_unlock(&eo_elem->
lock);
443 static void eo_start_send_multi(em_event_t ev_tbl[],
int num,
444 em_queue_t queue, em_event_group_t event_group)
454 if (unlikely(num_sent != num)) {
459 queue, num, num_sent);
474 const unsigned int max_ev = 32;
476 em_event_t ev_tbl[max_ev];
479 env_spinlock_lock(&eo_elem->
lock);
491 num = odp_stash_get_u64(eo_elem->
stash, &entry_tbl[0].u64 , max_ev);
493 if (unlikely(num < 0))
495 "odp_stash_get_u64() fails: %d", num);
496 goto buffered_send_exit;
499 for (
int i = 0; i < num; i++)
500 ev_tbl[i] = (em_event_t)(uintptr_t)entry_tbl[i].evptr;
502 event_to_hdr_multi(ev_tbl, ev_hdr_tbl, num);
506 EVSTATE__EO_START_SEND_BUFFERED);
515 const int qidx = entry_tbl[tbl_idx].qidx;
516 const em_queue_t queue = queue_idx2hdl(qidx);
517 const em_event_group_t event_group = ev_hdr_tbl[tbl_idx]->
egrp;
520 for (
int i = tbl_idx + 1; i < num &&
521 entry_tbl[i].qidx == qidx &&
522 ev_hdr_tbl[i]->
egrp == event_group; i++) {
527 eo_start_send_multi(&ev_tbl[tbl_idx], batch_cnt, queue, event_group);
529 tbl_idx += batch_cnt;
530 }
while (tbl_idx < num);
534 err = odp_stash_destroy(eo_elem->
stash);
536 eo_elem->
stash = ODP_STASH_INVALID;
537 env_spinlock_unlock(&eo_elem->
lock);
541 "odp_stash_destroy() fails: %d", err);
546 eo_stop_local_req(
eo_elem_t *
const eo_elem,
551 eo_local_func_call_param_init(¶m);
552 param.eo_elem = eo_elem;
555 param.ev_id = EO_STOP_LOCAL_REQ;
556 param.f_done_callback = eo_stop_done_callback;
557 param.num_notif = num_notif;
558 param.notif_tbl = notif_tbl;
559 param.exclude_current_core =
EM_FALSE;
560 param.sync_operation =
false;
562 return eo_local_func_call_req(¶m);
570 eo_stop_done_callback(
void *args)
575 void *
const eo_ctx = eo_elem->
eo_ctx;
581 if (unlikely(eo_elem == NULL)) {
583 EM_ESCOPE_EO_STOP_DONE_CB,
589 (void)check_eo_local_status(loc_func_retvals);
600 memset(&tmp_q_elem, 0,
sizeof(tmp_q_elem));
601 tmp_q_elem.
eo = (uint16_t)(uintptr_t)eo;
617 if (unlikely(ret !=
EM_OK))
619 "EO:%" PRI_EO " stop-func failed", eo);
626 eo_stop_sync_local_req(
eo_elem_t *
const eo_elem)
630 eo_local_func_call_param_init(¶m);
631 param.eo_elem = eo_elem;
634 param.ev_id = EO_STOP_SYNC_LOCAL_REQ;
635 param.f_done_callback = eo_stop_sync_done_callback;
637 param.notif_tbl = NULL;
638 param.exclude_current_core =
EM_TRUE;
639 param.sync_operation =
true;
641 return eo_local_func_call_req(¶m);
649 eo_stop_sync_done_callback(
void *args)
655 if (unlikely(eo_elem == NULL)) {
657 EM_ESCOPE_EO_STOP_SYNC_DONE_CB,
664 (void)check_eo_local_status(loc_func_retvals);
679 eo_local_func_call_param_init(¶m);
680 param.eo_elem = eo_elem;
681 param.q_elem = q_elem;
683 param.ev_id = EO_REM_QUEUE_LOCAL_REQ;
684 param.f_done_callback = eo_remove_queue_done_callback;
685 param.num_notif = num_notif;
686 param.notif_tbl = notif_tbl;
687 param.exclude_current_core =
EM_FALSE;
688 param.sync_operation =
false;
690 return eo_local_func_call_req(¶m);
703 eo_remove_queue_done_callback(
void *args)
710 if (unlikely(eo_elem == NULL || q_elem == NULL)) {
712 EM_ESCOPE_EO_REMOVE_QUEUE_DONE_CB,
713 "eo_elem/q_elem is NULL!");
717 (void)check_eo_local_status(loc_func_retvals);
722 if (unlikely(ret !=
EM_OK))
732 eo_remove_queue_sync_local_req(
eo_elem_t *
const eo_elem,
737 eo_local_func_call_param_init(¶m);
738 param.eo_elem = eo_elem;
739 param.q_elem = q_elem;
741 param.ev_id = EO_REM_QUEUE_SYNC_LOCAL_REQ;
742 param.f_done_callback = eo_remove_queue_sync_done_callback;
744 param.notif_tbl = NULL;
745 param.exclude_current_core =
EM_TRUE;
746 param.sync_operation =
true;
748 return eo_local_func_call_req(¶m);
761 eo_remove_queue_sync_done_callback(
void *args)
769 if (unlikely(eo_elem == NULL || q_elem == NULL)) {
771 EM_ESCOPE_EO_REMOVE_QUEUE_SYNC_DONE_CB,
772 "eo_elem/q_elem is NULL!");
778 (void)check_eo_local_status(loc_func_retvals);
783 if (unlikely(ret !=
EM_OK))
785 EM_ESCOPE_EO_REMOVE_QUEUE_SYNC_DONE_CB,
797 eo_remove_queue_all_local_req(
eo_elem_t *
const eo_elem,
int delete_queues,
802 eo_local_func_call_param_init(¶m);
803 param.eo_elem = eo_elem;
805 param.delete_queues = delete_queues;
806 param.ev_id = EO_REM_QUEUE_ALL_LOCAL_REQ;
807 param.f_done_callback = eo_remove_queue_all_done_callback;
808 param.num_notif = num_notif;
809 param.notif_tbl = notif_tbl;
810 param.exclude_current_core =
EM_FALSE;
811 param.sync_operation =
false;
813 return eo_local_func_call_req(¶m);
817 eo_remove_queue_all_local(
const eo_elem_t *eo_elem,
int delete_queues)
826 eo_remove_queue_all_done_callback(
void *args)
833 if (unlikely(eo_elem == NULL)) {
835 EM_ESCOPE_EO_REMOVE_QUEUE_ALL_DONE_CB,
840 (void)check_eo_local_status(loc_func_retvals);
844 ret = eo_delete_queue_all(eo_elem);
846 ret = eo_rem_queue_all(eo_elem);
848 if (unlikely(ret !=
EM_OK))
850 "EO:%" PRI_EO " removing all queues failed",
858 eo_remove_queue_all_sync_local_req(
eo_elem_t *
const eo_elem,
int delete_queues)
862 eo_local_func_call_param_init(¶m);
863 param.eo_elem = eo_elem;
865 param.delete_queues = delete_queues;
866 param.ev_id = EO_REM_QUEUE_ALL_SYNC_LOCAL_REQ;
867 param.f_done_callback = eo_remove_queue_all_sync_done_callback;
869 param.notif_tbl = NULL;
870 param.exclude_current_core =
EM_TRUE;
871 param.sync_operation =
true;
873 return eo_local_func_call_req(¶m);
877 eo_remove_queue_all_sync_local(
const eo_elem_t *eo_elem,
int delete_queues)
886 eo_remove_queue_all_sync_done_callback(
void *args)
894 if (unlikely(eo_elem == NULL)) {
896 EM_ESCOPE_EO_REMOVE_QUEUE_ALL_SYNC_DONE_CB,
903 (void)check_eo_local_status(loc_func_retvals);
907 ret = eo_delete_queue_all(eo_elem);
909 ret = eo_rem_queue_all(eo_elem);
911 if (unlikely(ret !=
EM_OK))
913 EM_ESCOPE_EO_REMOVE_QUEUE_ALL_SYNC_DONE_CB,
914 "EO:%" PRI_EO " removing all queues failed",
928 static const char core_err[] =
"coreXX:0x12345678 ";
929 char errmsg[cores *
sizeof(core_err)];
935 for (
int i = 0; i < cores; i++) {
936 err = loc_func_retvals->
core[i];
946 for (
int i = 0; i < cores; i++) {
947 err = loc_func_retvals->
core[i];
949 n = snprintf(&errmsg[c],
sizeof(core_err),
950 "core%02d:0x%08X ", i, err);
951 if ((
unsigned int)n >=
sizeof(core_err))
956 errmsg[cores *
sizeof(core_err) - 1] =
'\0';
959 "\nLocal start function failed on cores:\n"
967 memset(param, 0,
sizeof(*param));
985 void *f_done_arg_ptr;
990 free_count = core_count + 1;
991 if (param->exclude_current_core) {
1001 "Internal event (%u) allocation failed", param->ev_id);
1003 i_event->
id = param->ev_id;
1004 i_event->
loc_func.eo_elem = param->eo_elem;
1005 i_event->
loc_func.q_elem = param->q_elem;
1006 i_event->
loc_func.delete_queues = param->delete_queues;
1012 "Internal loc_func_retval_t allocation failed");
1014 loc_func_retvals->
eo_elem = param->eo_elem;
1015 loc_func_retvals->
q_elem = param->q_elem;
1017 loc_func_retvals->
event = tmp;
1019 env_atomic32_set(&loc_func_retvals->
free_at_zero, free_count);
1020 for (
int i = 0; i < core_count; i++)
1024 i_event->
loc_func.retvals = loc_func_retvals;
1027 f_done_arg_ptr = loc_func_retvals;
1037 param->f_done_callback(f_done_arg_ptr);
1043 param->f_done_callback, f_done_arg_ptr,
1044 param->num_notif, param->notif_tbl,
1045 param->sync_operation);
1046 if (unlikely(err)) {
1048 uint32_t unsent_cnt = err;
1052 cnt = env_atomic32_sub_return(&loc_func_retvals->
free_at_zero,
1060 EM_ESCOPE_EO_LOCAL_FUNC_CALL_REQ,
1061 "send_core_ctrl_events(mask=%s) failed",
1079 int delete_queues = i_ev->
loc_func.delete_queues;
1086 case EO_START_SYNC_LOCAL_REQ:
1098 case EO_START_LOCAL_REQ:
1105 memset(&tmp_q_elem, 0,
sizeof(tmp_q_elem));
1106 tmp_q_elem.
eo = (uint16_t)(uintptr_t)eo_elem->
eo;
1117 case EO_STOP_SYNC_LOCAL_REQ:
1129 case EO_STOP_LOCAL_REQ:
1137 memset(&tmp_q_elem, 0,
sizeof(tmp_q_elem));
1138 tmp_q_elem.
eo = (uint16_t)(uintptr_t)eo_elem->
eo;
1150 case EO_REM_QUEUE_LOCAL_REQ:
1151 status = eo_remove_queue_local(eo_elem, q_elem);
1153 case EO_REM_QUEUE_SYNC_LOCAL_REQ:
1154 status = eo_remove_queue_sync_local(eo_elem, q_elem);
1156 case EO_REM_QUEUE_ALL_LOCAL_REQ:
1157 status = eo_remove_queue_all_local(eo_elem, delete_queues);
1159 case EO_REM_QUEUE_ALL_SYNC_LOCAL_REQ:
1160 status = eo_remove_queue_all_sync_local(eo_elem, delete_queues);
1167 if (status !=
EM_OK) {
1172 "EO:%" PRI_EO "-%s:Local func(%" PRIx64
")fail",
1173 eo_elem->
eo, eo_elem->name, f_type);
1183 const uint32_t cnt =
1184 env_atomic32_sub_return(&loc_func_retvals->
free_at_zero, 1);
1185 if (unlikely(cnt == 0)) {
1186 (void)check_eo_local_status(loc_func_retvals);
1194 return env_atomic32_get(&
em_shm->eo_count);
1197 size_t eo_get_name(
const eo_elem_t *
const eo_elem,
1198 char name[],
const size_t maxlen)
1202 len = strnlen(eo_elem->name,
sizeof(eo_elem->name) - 1);
1203 if (maxlen - 1 < len)
1206 memcpy(name, eo_elem->name, len);
1214 const char *state_str;
1218 state_str =
"UNDEF";
1221 state_str =
"CREATED";
1224 state_str =
"STARTING";
1227 state_str =
"RUNNING";
1230 state_str =
"STOPPING";
1233 state_str =
"ERROR";
1236 state_str =
"UNKNOWN";
1243 #define EO_INFO_HDR_FMT \
1244 "Number of EOs: %d\n\n" \
1245 "ID Name State Start-local Stop-local" \
1246 " Multi-rcv Max-events Err-hdl Q-num EO-ctx\n" \
1247 "---------------------------------------------------------------------------" \
1248 "-----------------------------------------------\n%s\n"
1250 #define EO_INFO_LEN 123
1251 #define EO_INFO_FMT "%-10" PRI_EO "%-32s%-10s%-13c%-12c%-11c%-12d%-9c%-7d%-6c\n"
1255 unsigned int num_eo;
1270 const int eo_info_str_len = (num_eo + 10) * EO_INFO_LEN + 1;
1271 char eo_info_str[eo_info_str_len];
1274 eo_elem = eo_elem_get(eo);
1275 if (unlikely(eo_elem == NULL || !eo_allocated(eo_elem))) {
1280 n_print = snprintf(eo_info_str + len,
1281 eo_info_str_len - len,
1282 EO_INFO_FMT, eo, eo_elem->name,
1283 state_to_str(eo_elem->
state),
1286 eo_elem->use_multi_rcv ?
'Y' :
'N',
1287 eo_elem->max_events,
1290 eo_elem->
eo_ctx ?
'Y' :
'N');
1293 if (n_print >= eo_info_str_len - len)
1302 EM_PRINT(
"No EO has been created!\n");
1310 eo_info_str[len] =
'\0';
1311 EM_PRINT(EO_INFO_HDR_FMT, num_eo, eo_info_str);
1314 #define EO_Q_INFO_HDR_FMT \
1315 "EO %" PRI_EO "(%s) has %d queue(s):\n\n" \
1316 "Handle Name Priority Type State Qgrp" \
1318 "---------------------------------------------------------------------------" \
1322 #define EO_Q_INFO_LEN 85
1323 #define EO_Q_INFO_FMT \
1324 "%-10" PRI_QUEUE "%-32s%-10d%-10s%-9s%-10" PRI_QGRP "%-3c\n"
1334 const eo_elem_t *eo_elem = eo_elem_get(eo);
1336 if (unlikely(eo_elem == NULL || !eo_allocated(eo_elem))) {
1337 EM_PRINT(
"EO %" PRI_EO " is not created!\n", eo);
1352 const int eo_q_info_str_len = (q_num + 10) * EO_Q_INFO_LEN + 1;
1353 char eo_q_info_str[eo_q_info_str_len];
1356 q_elem = queue_elem_get(q);
1357 if (unlikely(q_elem == NULL || !queue_allocated(q_elem))) {
1364 n_print = snprintf(eo_q_info_str + len,
1365 eo_q_info_str_len - len,
1374 if (n_print >= eo_q_info_str_len - len)
1383 EM_PRINT(
"EO %" PRI_EO "(%s) has no queue!\n", eo, eo_elem->name);
1391 eo_q_info_str[len] =
'\0';
1392 EM_PRINT(EO_Q_INFO_HDR_FMT, eo, eo_elem->name, q_num, eo_q_info_str);
1400 unsigned int num_obj = 0;
1401 odp_stash_capability_t stash_capa;
1402 odp_stash_param_t stash_param;
1403 odp_stash_t stash = ODP_STASH_INVALID;
1405 int ret = odp_stash_capability(&stash_capa, ODP_STASH_TYPE_FIFO);
1408 return ODP_STASH_INVALID;
1410 odp_stash_param_init(&stash_param);
1412 stash_param.type = ODP_STASH_TYPE_FIFO;
1413 stash_param.put_mode = ODP_STASH_OP_MT;
1414 stash_param.get_mode = ODP_STASH_OP_MT;
1417 num_obj =
em_shm->opt.queue.min_events_default;
1419 stash_param.num_obj = num_obj;
1422 stash_param.obj_size =
sizeof(uint64_t);
1423 if (stash_param.num_obj > stash_capa.max_num.u64) {
1424 EM_LOG(EM_LOG_PRINT,
1425 "%s(): req stash.num_obj(%" PRIu64
") > capa.max_num.u64(%" PRIu64
").\n"
1426 " ==> using max value:%" PRIu64
"\n", __func__,
1427 stash_param.num_obj, stash_capa.max_num.u64, stash_capa.max_num.u64);
1428 stash_param.num_obj = stash_capa.max_num.u64;
1431 stash_param.cache_size = 0;
1433 stash = odp_stash_create(NULL, &stash_param);
1434 if (unlikely(stash == ODP_STASH_INVALID))
1435 return ODP_STASH_INVALID;