80 em_atomic_group_t agrp = agrp_idx2hdl(i);
82 atomic_group_elem_get(agrp);
84 if (unlikely(!agrp_elem))
90 odp_ticketlock_init(&agrp_elem->lock);
92 odp_atomic_init_u32(&agrp_elem->
num_queues, 0);
96 ret = objpool_init(&atomic_group_pool->objpool, objpool_subpools);
101 atomic_group_elem = &atomic_group_tbl->
ag_elem[i];
102 objpool_add(&atomic_group_pool->objpool, i % objpool_subpools,
110ag_pool_elem2ag_elem(
const objpool_elem_t *
const atomic_group_pool_elem)
119em_atomic_group_t atomic_group_alloc(
void)
124 ag_p_elem = objpool_rem(&
em_shm->atomic_group_pool.objpool,
127 if (unlikely(ag_p_elem == NULL))
130 ag_elem = ag_pool_elem2ag_elem(ag_p_elem);
136em_status_t atomic_group_free(em_atomic_group_t atomic_group)
140 if (unlikely(agrp_elem == NULL))
143 objpool_add(&
em_shm->atomic_group_pool.objpool,
161 if (!invalid_atomic_group(atomic_group)) {
163 atomic_group_elem_get(atomic_group);
165 atomic_group_rem_queue_list(ag_elem, q_elem);
171unsigned int atomic_group_count(
void)
184static void ag_internal_enq_error(em_atomic_group_t atomic_group,
185 odp_event_t odp_evtbl[],
const int num_free)
191 event_init_odp_multi(odp_evtbl, ev_tbl, ev_hdr_tbl,
192 num_free,
true, NULL);
200 "Atomic group:%" PRI_AGRP " internal enqueue fails: %d events dropped",
201 atomic_group, num_free);
218 odp_event_t odp_evtbl[],
const int num_events,
225 const em_queue_t queue = (em_queue_t)(uintptr_t)q_elem->
queue;
226 const uint16_t qidx = (uint16_t)queue_hdl2idx(queue);
228 for (
int i = 0; i < num_events; i++)
230 .evptr = (uintptr_t)odp_evtbl[i]};
242 (void)__atomic_fetch_add(&ag_elem->dispatch_lock.lock_and_evcnt,
243 (uint64_t)num_events, __ATOMIC_RELEASE);
246 int ret = odp_stash_put_u64(stash, &entry_tbl[0].u64, num_events);
248 if (unlikely(ret != num_events)) {
249 int enq_cnt = ret > 0 ? ret : 0;
251 (void)__atomic_fetch_sub(&ag_elem->dispatch_lock.lock_and_evcnt,
252 (uint64_t)(num_events - enq_cnt),
255 &odp_evtbl[enq_cnt], num_events - enq_cnt);
281 uint32_t deq_cnt = 0;
282 uint32_t max_deq = num_events;
290 &entry_tbl[0].u64 , max_deq);
296 if (deq_cnt < max_deq) {
298 &entry_tbl[deq_cnt].u64 ,
307 "Atomic group:%" PRI_AGRP " internal dequeue fails:\n"
308 " max_deq:%d deq_cnt:%d (hi_cnt:%d lo_cnt:%d)",
309 ag_elem->
atomic_group, max_deq, deq_cnt, hi_cnt, lo_cnt);
314 (void)__atomic_fetch_sub(&ag_elem->dispatch_lock.lock_and_evcnt,
315 deq_cnt, __ATOMIC_ACQUIRE);
330ag_dispatch_batches(
const stash_entry_t deq_entry_tbl[],
const uint32_t deq_cnt)
336 for (uint32_t i = 0; i < deq_cnt; i++)
337 deq_evtbl[i] = (odp_event_t)(uintptr_t)deq_entry_tbl[i].evptr;
340 uint32_t tbl_idx = 0;
347 const uint32_t qidx = deq_entry_tbl[tbl_idx].qidx;
348 const em_queue_t queue = queue_idx2hdl(qidx);
349 queue_elem_t *
const batch_qelem = queue_elem_get(queue);
350 uint32_t batch_cnt = 1;
353 for (uint32_t i = tbl_idx + 1; i < deq_cnt &&
354 deq_entry_tbl[i].qidx == qidx; i++) {
358 dispatch_events(&deq_evtbl[tbl_idx],
359 batch_cnt, batch_qelem);
360 tbl_idx += batch_cnt;
361 }
while (tbl_idx < deq_cnt);
382 .wrap = WRAP_PROTECT,
385 .wrap = WRAP_PROTECT,
388 return __atomic_compare_exchange_n(&ag_elem->dispatch_lock.lock_and_evcnt,
391 false, __ATOMIC_ACQUIRE ,
415 bool success =
false;
421 __atomic_load_n(&ag_elem->dispatch_lock.lock_and_evcnt,
423 lock_desired.parts.lock = 1;
424 lock_desired.parts.wrap = lock_expected.parts.wrap;
425 lock_desired.parts.evcnt = lock_expected.parts.evcnt;
427 success = __atomic_compare_exchange_n(&ag_elem->dispatch_lock.lock_and_evcnt,
430 false, __ATOMIC_ACQUIRE ,
434 bool lock_taken = lock_expected.parts.lock == 0 && lock_desired.parts.lock == 1;
467 .wrap = WRAP_PROTECT,
470 .wrap = WRAP_PROTECT,
472 bool unlocked = __atomic_compare_exchange_n(&ag_elem->dispatch_lock.lock_and_evcnt,
475 false, __ATOMIC_RELEASE ,
491 bool success =
false;
497 __atomic_load_n(&ag_elem->dispatch_lock.lock_and_evcnt,
500 if (lock_expected.parts.lock == 1) {
510 if (lock_expected.parts.evcnt == 0 &&
511 lock_expected.parts.wrap == WRAP_PROTECT) {
517 lock_desired.parts.lock = 1;
518 lock_desired.parts.wrap = lock_expected.parts.wrap;
519 lock_desired.parts.evcnt = lock_expected.parts.evcnt;
521 success = __atomic_compare_exchange_n(&ag_elem->dispatch_lock.lock_and_evcnt,
524 false, __ATOMIC_ACQUIRE ,
540void atomic_group_release(
void)
560 bool success =
false;
566 __atomic_load_n(&ag_elem->dispatch_lock.lock_and_evcnt,
568 lock_desired.parts.lock = 0;
569 lock_desired.parts.wrap = lock_expected.parts.wrap;
570 lock_desired.parts.evcnt = lock_expected.parts.evcnt;
572 success = __atomic_compare_exchange_n(&ag_elem->dispatch_lock.lock_and_evcnt,
575 false, __ATOMIC_ACQUIRE ,
598 uint32_t deq_cnt = ag_internal_deq(ag_elem, entry_tbl ,
605 ag_dispatch_batches(entry_tbl, deq_cnt);
608 bool unlocked = ag_unlock(ag_elem);
644void atomic_group_dispatch(odp_event_t odp_evtbl[],
const int num_events,
649 if (ag_acquire_if_idle(ag_elem)) {
656 odp_schedule_release_atomic();
658 dispatch_events(odp_evtbl, num_events, q_elem);
667 if (!ag_unlock(ag_elem))
668 ag_dispatch_loop(ag_elem);
678 ag_internal_enq(ag_elem, q_elem, odp_evtbl, num_events, q_elem->
priority);
680 if (!ag_trylock(ag_elem))
684 odp_schedule_release_atomic();
685 ag_dispatch_loop(ag_elem);
688#define AG_INFO_HDR_STR \
689"Number of atomic groups: %d\n\n" \
690"ID Name Qgrp Q-num\n" \
691"---------------------------------------------------------\n%s\n"
693#define AG_INFO_LEN 58
694#define AG_INFO_FMT "%-10" PRI_AGRP "%-32s%-10" PRI_QGRP "%-5d\n"
696void print_atomic_group_info(
void)
700 em_atomic_group_t ag_check;
717 const int ag_info_str_len = (ag_num + 10) * AG_INFO_LEN + 1;
718 char ag_info_str[ag_info_str_len];
721 ag_elem = atomic_group_elem_get(ag);
726 if (unlikely(ag_elem == NULL || ag_check != ag ||
727 !atomic_group_allocated(ag_elem))) {
732 n_print = snprintf(ag_info_str + len, ag_info_str_len - len,
737 if (n_print >= ag_info_str_len - len)
746 EM_PRINT(
"No atomic group has been created\n");
754 ag_info_str[len] =
'\0';
755 EM_PRINT(AG_INFO_HDR_STR, ag_num, ag_info_str);
758#define AG_QUEUE_INFO_HDR_STR \
759"Atomic group %" PRI_AGRP "(%s) has %d queue(s):\n\n" \
760"ID Name Priority Type State Qgrp Ctx\n" \
761"-----------------------------------------------------------------------------------\n" \
764#define AG_Q_INFO_LEN 85
765#define AG_Q_INFO_FMT "%-10" PRI_QUEUE "%-32s%-10d%-10s%-9s%-10" PRI_QGRP "%-3c\n"
767void print_atomic_group_queues(em_atomic_group_t ag)
778 if (unlikely(ag_elem == NULL || !atomic_group_allocated(ag_elem))) {
779 EM_PRINT(
"Atomic group %" PRI_AGRP "is not created!\n", ag);
794 int q_info_str_len = (q_num + 10) * AG_Q_INFO_LEN + 1;
795 char q_info_str[q_info_str_len];
798 q_elem = queue_elem_get(ag_queue);
800 if (unlikely(q_elem == NULL || !queue_allocated(q_elem))) {
807 n_print = snprintf(q_info_str + len, q_info_str_len - len,
808 AG_Q_INFO_FMT, ag_queue, q_name,
810 queue_type_str(q_elem->
type),
811 queue_state_str(q_elem->
state),
816 if (n_print >= q_info_str_len - len)
825 EM_PRINT(
"Atomic group %" PRI_AGRP "(%s) has no queue!\n",
834 q_info_str[len] =
'\0';
835 EM_PRINT(AG_QUEUE_INFO_HDR_STR, ag, ag_elem->
name, q_num, q_info_str);
838void print_ag_elem_info(
void)
843 "ag-elem size: %zu B\n",
846 DBG_PRINT(
"\t\toffset\tsize\n"
847 "\t\t------\t-----\n"
848 "atomic_group:\t%3zu B\t%3zu B\n"
849 "queue_group:\t%3zu B\t%3zu B\n"
850 "ag pool_elem:\t%3zu B\t%3zu B\n"
851 "stashes:\t%3zu B\t%3zu B\n"
852 "lock:\t\t%3zu B\t%3zu B\n"
853 "num_queues:\t%3zu B\t%3zu B\n"
854 "qlist_head[]:\t%3zu B\t%3zu B\n"
855 "name:\t\t%3zu B\t%3zu B\n",
#define INTERNAL_ERROR(error, escope, fmt,...)
ENV_LOCAL em_locm_t em_locm
#define EM_QUEUE_NAME_LEN
#define EM_SCHED_MULTI_MAX_BURST
#define EM_MAX_ATOMIC_GROUPS
#define EM_ATOMIC_GROUP_NAME_LEN
#define EM_SCHED_AG_MULTI_MAX_BURST
#define EM_ATOMIC_GROUP_UNDEF
em_atomic_group_t em_atomic_group_find(const char *name)
em_queue_t em_atomic_group_queue_next(void)
em_queue_t em_atomic_group_queue_first(unsigned int *num, em_atomic_group_t atomic_group)
size_t em_atomic_group_name(em_atomic_group_t atomic_group, char *name, size_t maxlen)
em_atomic_group_t em_atomic_group_next(void)
em_atomic_group_t em_atomic_group_first(unsigned int *num)
@ EM_ERR_OPERATION_FAILED
void em_free_multi(em_event_t events[], int num)
queue_elem_t * sched_q_elem
odp_atomic_u32_t num_queues
em_queue_group_t queue_group
char name[EM_ATOMIC_GROUP_NAME_LEN]
em_atomic_group_t atomic_group
struct atomic_group_elem_t::@30 stashes
odp_atomic_u32_t num_hi_prio_queues
objpool_elem_t atomic_group_pool_elem
atomic_group_elem_t ag_elem[EM_MAX_ATOMIC_GROUPS]
em_locm_current_t current
bool atomic_group_released
odp_atomic_u32_t atomic_group_count
em_atomic_group_t atomic_group
q_elem_atomic_group_t agrp
em_queue_group_t queue_group