59#include "em_libconfig.h"
66 odp_rwlock_init(&core_map->
rwlock);
74 uint32_t thr_max = MIN(odp_thread_count_max(), ODP_THREAD_COUNT_MAX);
77 thr_max < 1 || max_cores > thr_max) {
78 EM_LOG(EM_LOG_ERR,
"Invalid max core_count=%d! EM_MAX_CORES=%u, ODP-thr-max=%d\n",
87 if (mask_count < 1 || mask_count < max_cores) {
91 EM_LOG(EM_LOG_ERR,
"Invalid phys_mask=%s! set bits=%d < max core_count=%d\n",
92 mask_str, mask_count, max_cores);
110 if (sched_getaffinity(tid,
sizeof(cpu_set), &cpu_set) == -1) {
111 EM_LOG(EM_LOG_ERR,
"sched_getaffinity() failed: %s (%d)\n",
112 strerror(errno), errno);
116 const uint32_t cpu_set_count = CPU_COUNT(&cpu_set);
119 if (cpu_set_count != 1) {
121 "EM-core type is WORKER, but cpuset count=%d != 1\n",
126 if (cpu_set_count > max_cores) {
128 "EM-core type is CONTROL, but cpuset count=%d > max=%d\n",
129 cpu_set_count, max_cores);
138 for (
int i = 0; i < CPU_SETSIZE; i++) {
139 if (CPU_ISSET(i, &cpu_set))
154 "Cpuset of the control EM-core must be subset of conf.phys_mask\n"
155 "cpuset=%s conf.phys_mask=%s\n",
156 cpuset_str, allowed_str);
160 EM_LOG(EM_LOG_ERR,
"Unsupported EM-core type:%d\n", core_type);
179static int determine_core_id(
int req_core_id, uint32_t max_cores,
const core_map_t *core_map)
181 if (unlikely(req_core_id < -1)) {
183 "Requested core-id:%d invalid:\n"
184 " -1: Let EM decide, [0 - %u]: req id range\n",
185 req_core_id, max_cores - 1);
192 if (req_core_id == -1) {
193 uint32_t core_id = 0;
195 for (; core_id < max_cores; core_id++) {
200 if (unlikely(core_id == max_cores)) {
201 EM_LOG(EM_LOG_ERR,
"No free EM-core ids found in range [0 - %u] (max:%u)\n",
202 max_cores - 1, max_cores);
212 if ((uint32_t)req_core_id >= max_cores) {
213 EM_LOG(EM_LOG_ERR,
"Given core-id:%d too large (max:%u)\n",
214 req_core_id, max_cores - 1);
220 if (unlikely(unavailable)) {
221 EM_LOG(EM_LOG_ERR,
"Given core-id:%d already in use\n", req_core_id);
237 const int phys_core = odp_cpu_id();
238 const pid_t tid = gettid();
247 EM_LOG(EM_LOG_ERR,
"The used phys_core:%d not allowed by the phys_mask:%s\n",
248 phys_core, mask_str);
253 err = verify_sched_affinity(conf_local->
core_type, tid,
254 max_cores, allowed_mask);
255 if (unlikely(err !=
EM_OK))
258 const int odp_thr = odp_thread_id();
259 const int thr_max = MIN(odp_thread_count_max(), ODP_THREAD_COUNT_MAX);
261 if (odp_thr < 0 || odp_thr >= thr_max) {
262 EM_LOG(EM_LOG_ERR,
"Invalid ODP thread-id:%d, id range is 0->%d\n",
271 snprintf(path,
sizeof(path),
"/proc/%d/stat", tid);
272 path[
sizeof(path) - 1] =
'\0';
273 path_len = strnlen(path,
sizeof(path));
275 if (path_len >=
sizeof(path)) {
276 EM_LOG(EM_LOG_ERR,
"strnlen(%s)=%zu >= sizeof(path)=%zu\n",
277 path, path_len,
sizeof(path));
285 odp_rwlock_write_lock(&core_map->
rwlock);
288 core_id = determine_core_id(conf_local->
core_id , max_cores, core_map);
289 if (unlikely(core_id < 0)) {
291 odp_rwlock_write_unlock(&core_map->
rwlock);
296 uint32_t current_core_count = odp_atomic_fetch_inc_u32(&core_map->
current_core_count) + 1;
298 if (unlikely(current_core_count > max_cores)) {
302 odp_rwlock_write_unlock(&core_map->
rwlock);
303 EM_LOG(EM_LOG_ERR,
"Current core count:%d too large (max:%d)\n",
304 current_core_count, max_cores);
308 core_map->rwlocked.thr_vs_logic.
logic[odp_thr] = (uint8_t)core_id;
309 core_map->rwlocked.thr_vs_logic.
odp_thr[core_id] = (uint16_t)odp_thr;
310 core_map->rwlocked.
tids[core_id] = tid;
315 odp_thrmask_set(&core_map->rwlocked.
thrmask_all, odp_thr);
331 odp_rwlock_write_unlock(&core_map->
rwlock);
333 DBG_PRINT(
"EM-core%02d (%s): %s() - EM-cores:%d (workers:%u ctrl:%u), EM-ext-thrs:%u\n",
348 const int odp_thr = odp_thread_id();
349 const int thr_max = MIN(odp_thread_count_max(), ODP_THREAD_COUNT_MAX);
350 const pid_t tid = gettid();
354 if (odp_thr < 0 || odp_thr >= thr_max) {
356 "Ext-thread: Invalid ODP thread-id:%d, id range is 0->%d\n",
364 odp_rwlock_write_lock(&core_map->
rwlock);
368 odp_thrmask_set(&core_map->rwlocked.
thrmask_all, odp_thr);
369 core_map->rwlocked.
ext_tids[odp_thr] = tid;
374 odp_rwlock_write_unlock(&core_map->
rwlock);
376 DBG_PRINT(
"EM-extthr%02d (EXT): %s() - EM-cores:%d (workers:%u ctrl:%u), EM-ext-thrs:%u\n",
392 const int thr = odp_thread_id();
393 int32_t cnt = odp_atomic_fetch_dec_u32(&
em_shm->core_map.ongoing_term_reqs[thr]);
396 DBG_PRINT(
"EM-core%02d (thr%02d): TERM_THREAD_REQ from thr%02d - ongoing-term-reqs=%d\n",
399 DBG_PRINT(
"EM-extthr%02d: TERM_THREAD_REQ from thr%02d - ongoing-term-reqs=%d\n",
402 if (unlikely(cnt < 0)) {
404 "TERM_THREAD_REQ - ongoing-term-reqs=%d", i_ev->
id, cnt);
414static void term_thread_req_done_callback(
void *arg)
421 DBG_PRINT(
"EM-core%02d (thr%02d): TERM_THREAD_REQ DONE\n",
424 DBG_PRINT(
"EM-extthr%02d: TERM_THREAD_REQ DONE\n",
432term_thread_req(
int thread_id,
const odp_thrmask_t *remain_thrmask_emcores,
em_escope_t escope)
438 "Internal event (TERM_THREAD_REQ) allocation failed");
442 i_event->
id = TERM_THREAD_REQ;
446 term_thread_req_done_callback, NULL,
449 char mask_str[ODP_THRMASK_STR_SIZE];
451 odp_thrmask_to_str(remain_thrmask_emcores, mask_str, ODP_THRMASK_STR_SIZE);
453 "send_core_ctrl_events(mask=%s) failed", mask_str);
462 const int32_t core_id = locm->
core_id;
463 const int odp_thr = odp_thread_id();
464 odp_thrmask_t remain_thrmask_emcores;
470 odp_rwlock_write_lock(&core_map->
rwlock);
472 int32_t current_core_count = odp_atomic_fetch_dec_u32(&core_map->
current_core_count) - 1;
474 core_map->rwlocked.thr_vs_logic.
logic[odp_thr] = 0;
475 core_map->rwlocked.thr_vs_logic.
odp_thr[core_id] = 0;
486 odp_thrmask_clr(&core_map->rwlocked.
thrmask_all, odp_thr);
488 odp_thrmask_copy(&remain_thrmask_emcores, &core_map->rwlocked.
thrmask_emcores);
490 if (current_core_count > 0) {
491 int thr = odp_thrmask_first(&remain_thrmask_emcores);
495 thr = odp_thrmask_next(&remain_thrmask_emcores, thr);
499 core_map->rwlocked.
tids[core_id] = 0;
503 if (current_core_count >= 1)
504 stat = term_thread_req(odp_thr, &remain_thrmask_emcores, escope);
509 odp_rwlock_write_unlock(&core_map->
rwlock);
514 if (current_core_count < 1) {
516 term_thread_req_done_callback(NULL);
519 if (unlikely(current_core_count < 0))
520 EM_LOG(EM_LOG_ERR,
"Current core count invalid: %d", current_core_count);
522 DBG_PRINT(
"EM-core%02d (thr%02d): %s() - current core count:%d\n",
523 locm->
core_id, odp_thr, __func__, current_core_count);
525 return current_core_count;
530 const int odp_thr = odp_thread_id();
531 odp_thrmask_t remain_thrmask_emcores;
537 odp_rwlock_write_lock(&core_map->
rwlock);
543 odp_thrmask_clr(&core_map->rwlocked.
thrmask_all, odp_thr);
545 odp_thrmask_copy(&remain_thrmask_emcores, &core_map->rwlocked.
thrmask_emcores);
547 if (current_core_count > 0) {
548 int thr = odp_thrmask_first(&remain_thrmask_emcores);
552 thr = odp_thrmask_next(&remain_thrmask_emcores, thr);
557 core_map->rwlocked.
ext_tids[odp_thr] = 0;
559 if (current_core_count >= 1)
560 stat = term_thread_req(odp_thr, &remain_thrmask_emcores, escope);
565 odp_rwlock_write_unlock(&core_map->
rwlock);
570 if (current_core_count < 1) {
572 term_thread_req_done_callback(NULL);
575 if (unlikely(current_core_count < 0)) {
576 EM_LOG(EM_LOG_ERR,
"Current core count invalid: %d", current_core_count);
580 DBG_PRINT(
"EM-extthr%02d: %s() - current EM-core count:%d\n",
581 odp_thr, __func__, current_core_count);
583 return current_core_count;
587 odp_thrmask_t *
const odp_thrmask )
591 odp_thrmask_zero(odp_thrmask);
597 int odp_thread_id = core_map->rwlocked.thr_vs_logic.
odp_thr[core];
599 odp_thrmask_set(odp_thrmask, odp_thread_id);
607 odp_thrmask_t *
const odp_thrmask )
611 odp_thrmask_zero(odp_thrmask);
613 odp_rwlock_read_lock(&core_map->
rwlock);
618 int odp_thread_id = core_map->rwlocked.thr_vs_logic.
odp_thr[core];
620 odp_thrmask_set(odp_thrmask, odp_thread_id);
624 odp_rwlock_read_unlock(&core_map->
rwlock);
637int read_proc_cpuid(FILE *proc_tid_stat_file)
639 if (unlikely(!proc_tid_stat_file))
643 const int cpu_field_idx = 39;
647 if (likely(fgets(buffer,
sizeof(buffer), proc_tid_stat_file) != NULL)) {
648 const char *stat_token;
651 stat_token = strtok_r(buffer,
" ", &saveptr);
654 for (
int i = 1; i < cpu_field_idx; i++) {
655 if (unlikely(!stat_token))
657 stat_token = strtok_r(NULL,
" ", &saveptr);
661 if (likely(stat_token)) {
663 long value = strtol(stat_token, &endptr, 10);
666 if (endptr != stat_token && *endptr ==
'\0' &&
667 value >= 0 && value <= INT_MAX)
#define INTERNAL_ERROR(error, escope, fmt,...)
#define RETURN_ERROR_IF(cond, error, escope, fmt,...)
int send_core_ctrl_events(const odp_thrmask_t *const thr_mask, em_event_t ctrl_event, void(*f_done_callback)(void *arg_ptr), void *f_done_arg_ptr, int num_notif, const em_notif_t notif_tbl[], bool sync_operation)
Sends an internal control event to each thread set in 'mask'.
ENV_LOCAL em_locm_t em_locm
void em_core_mask_or(em_core_mask_t *dst, const em_core_mask_t *src1, const em_core_mask_t *src2)
int em_core_mask_equal(const em_core_mask_t *mask1, const em_core_mask_t *mask2)
int em_core_mask_count(const em_core_mask_t *mask)
void em_core_mask_tostr(char *mask_str, int len, const em_core_mask_t *mask)
int em_core_mask_first(const em_core_mask_t *mask)
void em_core_mask_set(int core, em_core_mask_t *mask)
void em_core_mask_clr(int core, em_core_mask_t *mask)
int em_core_mask_isset(int core, const em_core_mask_t *mask)
int em_core_mask_next(const em_core_mask_t *mask, int idx)
#define EM_CORE_MASK_STRLEN
void em_core_mask_zero(em_core_mask_t *mask)
em_event_t em_alloc(uint32_t size, em_event_type_t type, em_pool_t pool)
void * em_event_pointer(em_event_t event)
odp_atomic_u32_t external_thread_count
char proc_tid_stat_paths[EM_MAX_CORES][32]
uint8_t logic[ODP_THREAD_COUNT_MAX]
em_core_type_t core_types[EM_MAX_CORES]
pid_t ext_tids[ODP_THREAD_COUNT_MAX]
odp_atomic_u32_t current_core_count
uint16_t odp_thr[EM_MAX_CORES]
odp_atomic_u32_t worker_core_count
odp_atomic_u32_t ongoing_term_reqs[ODP_THREAD_COUNT_MAX]
odp_thrmask_t thrmask_extthrs
odp_thrmask_t thrmask_all
odp_thrmask_t thrmask_emcores
em_core_mask_t logic_mask
odp_atomic_u32_t control_core_count
em_core_mask_t worker_mask
em_core_mask_t control_mask
em_conf_local_t conf_local
struct internal_event_t::@52 term_thread