199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 299a2dd95SBruce Richardson * Copyright(c) 2010-2014 Intel Corporation 399a2dd95SBruce Richardson */ 499a2dd95SBruce Richardson 551e6608aSTyler Retzlaff #include <errno.h> 699a2dd95SBruce Richardson #include <stdio.h> 799a2dd95SBruce Richardson #include <stdlib.h> 899a2dd95SBruce Richardson #include <pthread.h> 999a2dd95SBruce Richardson #include <sched.h> 1099a2dd95SBruce Richardson #include <assert.h> 1199a2dd95SBruce Richardson #include <string.h> 1299a2dd95SBruce Richardson 1345a685caSAnkur Dwivedi #include <eal_trace_internal.h> 1499a2dd95SBruce Richardson #include <rte_errno.h> 1599a2dd95SBruce Richardson #include <rte_lcore.h> 1699a2dd95SBruce Richardson #include <rte_log.h> 1799a2dd95SBruce Richardson #include <rte_memory.h> 1899a2dd95SBruce Richardson #include <rte_trace_point.h> 1999a2dd95SBruce Richardson 2099a2dd95SBruce Richardson #include "eal_internal_cfg.h" 2199a2dd95SBruce Richardson #include "eal_private.h" 2299a2dd95SBruce Richardson #include "eal_thread.h" 2399a2dd95SBruce Richardson #include "eal_trace.h" 2499a2dd95SBruce Richardson 2599a2dd95SBruce Richardson RTE_DEFINE_PER_LCORE(unsigned int, _lcore_id) = LCORE_ID_ANY; 2699a2dd95SBruce Richardson RTE_DEFINE_PER_LCORE(int, _thread_id) = -1; 2799a2dd95SBruce Richardson static RTE_DEFINE_PER_LCORE(unsigned int, _socket_id) = 2899a2dd95SBruce Richardson (unsigned int)SOCKET_ID_ANY; 2999a2dd95SBruce Richardson static RTE_DEFINE_PER_LCORE(rte_cpuset_t, _cpuset); 3099a2dd95SBruce Richardson 3199a2dd95SBruce Richardson unsigned rte_socket_id(void) 3299a2dd95SBruce Richardson { 3399a2dd95SBruce Richardson return RTE_PER_LCORE(_socket_id); 3499a2dd95SBruce Richardson } 3599a2dd95SBruce Richardson 3699a2dd95SBruce Richardson static int 3799a2dd95SBruce Richardson eal_cpuset_socket_id(rte_cpuset_t *cpusetp) 3899a2dd95SBruce Richardson { 3999a2dd95SBruce Richardson unsigned cpu = 0; 4099a2dd95SBruce Richardson int socket_id = SOCKET_ID_ANY; 4199a2dd95SBruce Richardson int sid; 4299a2dd95SBruce Richardson 4399a2dd95SBruce Richardson if (cpusetp == NULL) 4499a2dd95SBruce Richardson return SOCKET_ID_ANY; 4599a2dd95SBruce Richardson 4699a2dd95SBruce Richardson do { 4799a2dd95SBruce Richardson if (!CPU_ISSET(cpu, cpusetp)) 4899a2dd95SBruce Richardson continue; 4999a2dd95SBruce Richardson 5099a2dd95SBruce Richardson if (socket_id == SOCKET_ID_ANY) 5199a2dd95SBruce Richardson socket_id = eal_cpu_socket_id(cpu); 5299a2dd95SBruce Richardson 5399a2dd95SBruce Richardson sid = eal_cpu_socket_id(cpu); 5499a2dd95SBruce Richardson if (socket_id != sid) { 5599a2dd95SBruce Richardson socket_id = SOCKET_ID_ANY; 5699a2dd95SBruce Richardson break; 5799a2dd95SBruce Richardson } 5899a2dd95SBruce Richardson 5999a2dd95SBruce Richardson } while (++cpu < CPU_SETSIZE); 6099a2dd95SBruce Richardson 6199a2dd95SBruce Richardson return socket_id; 6299a2dd95SBruce Richardson } 6399a2dd95SBruce Richardson 6499a2dd95SBruce Richardson static void 6599a2dd95SBruce Richardson thread_update_affinity(rte_cpuset_t *cpusetp) 6699a2dd95SBruce Richardson { 6799a2dd95SBruce Richardson unsigned int lcore_id = rte_lcore_id(); 6899a2dd95SBruce Richardson 6999a2dd95SBruce Richardson /* store socket_id in TLS for quick access */ 7099a2dd95SBruce Richardson RTE_PER_LCORE(_socket_id) = 7199a2dd95SBruce Richardson eal_cpuset_socket_id(cpusetp); 7299a2dd95SBruce Richardson 7399a2dd95SBruce Richardson /* store cpuset in TLS for quick access */ 7499a2dd95SBruce Richardson memmove(&RTE_PER_LCORE(_cpuset), cpusetp, 7599a2dd95SBruce Richardson sizeof(rte_cpuset_t)); 7699a2dd95SBruce Richardson 7799a2dd95SBruce Richardson if (lcore_id != (unsigned)LCORE_ID_ANY) { 7899a2dd95SBruce Richardson /* EAL thread will update lcore_config */ 7999a2dd95SBruce Richardson lcore_config[lcore_id].socket_id = RTE_PER_LCORE(_socket_id); 8099a2dd95SBruce Richardson memmove(&lcore_config[lcore_id].cpuset, cpusetp, 8199a2dd95SBruce Richardson sizeof(rte_cpuset_t)); 8299a2dd95SBruce Richardson } 8399a2dd95SBruce Richardson } 8499a2dd95SBruce Richardson 8599a2dd95SBruce Richardson int 8699a2dd95SBruce Richardson rte_thread_set_affinity(rte_cpuset_t *cpusetp) 8799a2dd95SBruce Richardson { 888b0a1b8cSTyler Retzlaff if (rte_thread_set_affinity_by_id(rte_thread_self(), cpusetp) != 0) { 898b0a1b8cSTyler Retzlaff RTE_LOG(ERR, EAL, "rte_thread_set_affinity_by_id failed\n"); 9099a2dd95SBruce Richardson return -1; 9199a2dd95SBruce Richardson } 9299a2dd95SBruce Richardson 9399a2dd95SBruce Richardson thread_update_affinity(cpusetp); 9499a2dd95SBruce Richardson return 0; 9599a2dd95SBruce Richardson } 9699a2dd95SBruce Richardson 9799a2dd95SBruce Richardson void 9899a2dd95SBruce Richardson rte_thread_get_affinity(rte_cpuset_t *cpusetp) 9999a2dd95SBruce Richardson { 10099a2dd95SBruce Richardson assert(cpusetp); 10199a2dd95SBruce Richardson memmove(cpusetp, &RTE_PER_LCORE(_cpuset), 10299a2dd95SBruce Richardson sizeof(rte_cpuset_t)); 10399a2dd95SBruce Richardson } 10499a2dd95SBruce Richardson 10599a2dd95SBruce Richardson int 10699a2dd95SBruce Richardson eal_thread_dump_affinity(rte_cpuset_t *cpuset, char *str, unsigned int size) 10799a2dd95SBruce Richardson { 10899a2dd95SBruce Richardson unsigned cpu; 10999a2dd95SBruce Richardson int ret; 11099a2dd95SBruce Richardson unsigned int out = 0; 11199a2dd95SBruce Richardson 11299a2dd95SBruce Richardson for (cpu = 0; cpu < CPU_SETSIZE; cpu++) { 11399a2dd95SBruce Richardson if (!CPU_ISSET(cpu, cpuset)) 11499a2dd95SBruce Richardson continue; 11599a2dd95SBruce Richardson 11699a2dd95SBruce Richardson ret = snprintf(str + out, 11799a2dd95SBruce Richardson size - out, "%u,", cpu); 11899a2dd95SBruce Richardson if (ret < 0 || (unsigned)ret >= size - out) { 11999a2dd95SBruce Richardson /* string will be truncated */ 12099a2dd95SBruce Richardson ret = -1; 12199a2dd95SBruce Richardson goto exit; 12299a2dd95SBruce Richardson } 12399a2dd95SBruce Richardson 12499a2dd95SBruce Richardson out += ret; 12599a2dd95SBruce Richardson } 12699a2dd95SBruce Richardson 12799a2dd95SBruce Richardson ret = 0; 12899a2dd95SBruce Richardson exit: 12999a2dd95SBruce Richardson /* remove the last separator */ 13099a2dd95SBruce Richardson if (out > 0) 13199a2dd95SBruce Richardson str[out - 1] = '\0'; 13299a2dd95SBruce Richardson 13399a2dd95SBruce Richardson return ret; 13499a2dd95SBruce Richardson } 13599a2dd95SBruce Richardson 13699a2dd95SBruce Richardson int 13799a2dd95SBruce Richardson eal_thread_dump_current_affinity(char *str, unsigned int size) 13899a2dd95SBruce Richardson { 13999a2dd95SBruce Richardson rte_cpuset_t cpuset; 14099a2dd95SBruce Richardson 14199a2dd95SBruce Richardson rte_thread_get_affinity(&cpuset); 14299a2dd95SBruce Richardson return eal_thread_dump_affinity(&cpuset, str, size); 14399a2dd95SBruce Richardson } 14499a2dd95SBruce Richardson 14599a2dd95SBruce Richardson void 14699a2dd95SBruce Richardson __rte_thread_init(unsigned int lcore_id, rte_cpuset_t *cpuset) 14799a2dd95SBruce Richardson { 14899a2dd95SBruce Richardson /* set the lcore ID in per-lcore memory area */ 14999a2dd95SBruce Richardson RTE_PER_LCORE(_lcore_id) = lcore_id; 15099a2dd95SBruce Richardson 15199a2dd95SBruce Richardson /* acquire system unique id */ 15299a2dd95SBruce Richardson rte_gettid(); 15399a2dd95SBruce Richardson 15499a2dd95SBruce Richardson thread_update_affinity(cpuset); 15599a2dd95SBruce Richardson 15699a2dd95SBruce Richardson __rte_trace_mem_per_thread_alloc(); 15799a2dd95SBruce Richardson } 15899a2dd95SBruce Richardson 15999a2dd95SBruce Richardson void 16099a2dd95SBruce Richardson __rte_thread_uninit(void) 16199a2dd95SBruce Richardson { 16299a2dd95SBruce Richardson trace_mem_per_thread_free(); 16399a2dd95SBruce Richardson 16499a2dd95SBruce Richardson RTE_PER_LCORE(_lcore_id) = LCORE_ID_ANY; 16599a2dd95SBruce Richardson } 16699a2dd95SBruce Richardson 167a95d7054SDavid Marchand /* main loop of threads */ 1688b0a1b8cSTyler Retzlaff __rte_noreturn uint32_t 169a95d7054SDavid Marchand eal_thread_loop(void *arg) 170a95d7054SDavid Marchand { 171a95d7054SDavid Marchand unsigned int lcore_id = (uintptr_t)arg; 172a95d7054SDavid Marchand char cpuset[RTE_CPU_AFFINITY_STR_LEN]; 173a95d7054SDavid Marchand int ret; 174a95d7054SDavid Marchand 175a95d7054SDavid Marchand __rte_thread_init(lcore_id, &lcore_config[lcore_id].cpuset); 176a95d7054SDavid Marchand 177a95d7054SDavid Marchand ret = eal_thread_dump_current_affinity(cpuset, sizeof(cpuset)); 178a95d7054SDavid Marchand RTE_LOG(DEBUG, EAL, "lcore %u is ready (tid=%zx;cpuset=[%s%s])\n", 179*db77fe7dSTyler Retzlaff lcore_id, rte_thread_self().opaque_id, cpuset, 180a95d7054SDavid Marchand ret == 0 ? "" : "..."); 181a95d7054SDavid Marchand 182a95d7054SDavid Marchand rte_eal_trace_thread_lcore_ready(lcore_id, cpuset); 183a95d7054SDavid Marchand 184a95d7054SDavid Marchand /* read on our pipe to get commands */ 185a95d7054SDavid Marchand while (1) { 186a95d7054SDavid Marchand lcore_function_t *f; 187a95d7054SDavid Marchand void *fct_arg; 188a95d7054SDavid Marchand 189a95d7054SDavid Marchand eal_thread_wait_command(); 190a95d7054SDavid Marchand 191a95d7054SDavid Marchand /* Set the state to 'RUNNING'. Use release order 192a95d7054SDavid Marchand * since 'state' variable is used as the guard variable. 193a95d7054SDavid Marchand */ 194a95d7054SDavid Marchand __atomic_store_n(&lcore_config[lcore_id].state, RUNNING, 195a95d7054SDavid Marchand __ATOMIC_RELEASE); 196a95d7054SDavid Marchand 197a95d7054SDavid Marchand eal_thread_ack_command(); 198a95d7054SDavid Marchand 199a95d7054SDavid Marchand /* Load 'f' with acquire order to ensure that 200a95d7054SDavid Marchand * the memory operations from the main thread 201a95d7054SDavid Marchand * are accessed only after update to 'f' is visible. 202a95d7054SDavid Marchand * Wait till the update to 'f' is visible to the worker. 203a95d7054SDavid Marchand */ 204a95d7054SDavid Marchand while ((f = __atomic_load_n(&lcore_config[lcore_id].f, 205a95d7054SDavid Marchand __ATOMIC_ACQUIRE)) == NULL) 206a95d7054SDavid Marchand rte_pause(); 207a95d7054SDavid Marchand 208a95d7054SDavid Marchand /* call the function and store the return value */ 209a95d7054SDavid Marchand fct_arg = lcore_config[lcore_id].arg; 210a95d7054SDavid Marchand ret = f(fct_arg); 211a95d7054SDavid Marchand lcore_config[lcore_id].ret = ret; 212a95d7054SDavid Marchand lcore_config[lcore_id].f = NULL; 213a95d7054SDavid Marchand lcore_config[lcore_id].arg = NULL; 214a95d7054SDavid Marchand 215a95d7054SDavid Marchand /* Store the state with release order to ensure that 216a95d7054SDavid Marchand * the memory operations from the worker thread 217a95d7054SDavid Marchand * are completed before the state is updated. 218a95d7054SDavid Marchand * Use 'state' as the guard variable. 219a95d7054SDavid Marchand */ 220a95d7054SDavid Marchand __atomic_store_n(&lcore_config[lcore_id].state, WAIT, 221a95d7054SDavid Marchand __ATOMIC_RELEASE); 222a95d7054SDavid Marchand } 223a95d7054SDavid Marchand 224a95d7054SDavid Marchand /* never reached */ 2258b0a1b8cSTyler Retzlaff /* return 0; */ 226a95d7054SDavid Marchand } 227a95d7054SDavid Marchand 228705356f0SHonnappa Nagarahalli enum __rte_ctrl_thread_status { 229705356f0SHonnappa Nagarahalli CTRL_THREAD_LAUNCHING, /* Yet to call pthread_create function */ 230705356f0SHonnappa Nagarahalli CTRL_THREAD_RUNNING, /* Control thread is running successfully */ 231705356f0SHonnappa Nagarahalli CTRL_THREAD_ERROR /* Control thread encountered an error */ 232705356f0SHonnappa Nagarahalli }; 233705356f0SHonnappa Nagarahalli 23499a2dd95SBruce Richardson struct rte_thread_ctrl_params { 235878b7468STyler Retzlaff union { 236878b7468STyler Retzlaff void *(*ctrl_start_routine)(void *arg); 237878b7468STyler Retzlaff rte_thread_func control_start_routine; 238878b7468STyler Retzlaff } u; 23999a2dd95SBruce Richardson void *arg; 240705356f0SHonnappa Nagarahalli int ret; 241705356f0SHonnappa Nagarahalli /* Control thread status. 242705356f0SHonnappa Nagarahalli * If the status is CTRL_THREAD_ERROR, 'ret' has the error code. 243705356f0SHonnappa Nagarahalli */ 244705356f0SHonnappa Nagarahalli enum __rte_ctrl_thread_status ctrl_thread_status; 24599a2dd95SBruce Richardson }; 24699a2dd95SBruce Richardson 247878b7468STyler Retzlaff static int ctrl_thread_init(void *arg) 24899a2dd95SBruce Richardson { 24999a2dd95SBruce Richardson struct internal_config *internal_conf = 25099a2dd95SBruce Richardson eal_get_internal_configuration(); 25199a2dd95SBruce Richardson rte_cpuset_t *cpuset = &internal_conf->ctrl_cpuset; 25299a2dd95SBruce Richardson struct rte_thread_ctrl_params *params = arg; 25399a2dd95SBruce Richardson 25499a2dd95SBruce Richardson __rte_thread_init(rte_lcore_id(), cpuset); 2557e7b6762SKaisen You /* Set control thread socket ID to SOCKET_ID_ANY 2567e7b6762SKaisen You * as control threads may be scheduled on any NUMA node. 2577e7b6762SKaisen You */ 2587e7b6762SKaisen You RTE_PER_LCORE(_socket_id) = SOCKET_ID_ANY; 2598b0a1b8cSTyler Retzlaff params->ret = rte_thread_set_affinity_by_id(rte_thread_self(), cpuset); 260705356f0SHonnappa Nagarahalli if (params->ret != 0) { 261705356f0SHonnappa Nagarahalli __atomic_store_n(¶ms->ctrl_thread_status, 262705356f0SHonnappa Nagarahalli CTRL_THREAD_ERROR, __ATOMIC_RELEASE); 263b27c1bd8STyler Retzlaff return 1; 264705356f0SHonnappa Nagarahalli } 265705356f0SHonnappa Nagarahalli 266705356f0SHonnappa Nagarahalli __atomic_store_n(¶ms->ctrl_thread_status, 267705356f0SHonnappa Nagarahalli CTRL_THREAD_RUNNING, __ATOMIC_RELEASE); 26899a2dd95SBruce Richardson 269878b7468STyler Retzlaff return 0; 270878b7468STyler Retzlaff } 271878b7468STyler Retzlaff 272878b7468STyler Retzlaff static void *ctrl_thread_start(void *arg) 273878b7468STyler Retzlaff { 274878b7468STyler Retzlaff struct rte_thread_ctrl_params *params = arg; 275b27c1bd8STyler Retzlaff void *start_arg = params->arg; 276878b7468STyler Retzlaff void *(*start_routine)(void *) = params->u.ctrl_start_routine; 277878b7468STyler Retzlaff 278878b7468STyler Retzlaff if (ctrl_thread_init(arg) != 0) 279878b7468STyler Retzlaff return NULL; 280878b7468STyler Retzlaff 281b27c1bd8STyler Retzlaff return start_routine(start_arg); 282878b7468STyler Retzlaff } 283878b7468STyler Retzlaff 284878b7468STyler Retzlaff static uint32_t control_thread_start(void *arg) 285878b7468STyler Retzlaff { 286878b7468STyler Retzlaff struct rte_thread_ctrl_params *params = arg; 287b27c1bd8STyler Retzlaff void *start_arg = params->arg; 288878b7468STyler Retzlaff rte_thread_func start_routine = params->u.control_start_routine; 289878b7468STyler Retzlaff 290878b7468STyler Retzlaff if (ctrl_thread_init(arg) != 0) 291b27c1bd8STyler Retzlaff return 0; 292878b7468STyler Retzlaff 293b27c1bd8STyler Retzlaff return start_routine(start_arg); 29499a2dd95SBruce Richardson } 29599a2dd95SBruce Richardson 29699a2dd95SBruce Richardson int 29799a2dd95SBruce Richardson rte_ctrl_thread_create(pthread_t *thread, const char *name, 29899a2dd95SBruce Richardson const pthread_attr_t *attr, 29999a2dd95SBruce Richardson void *(*start_routine)(void *), void *arg) 30099a2dd95SBruce Richardson { 30199a2dd95SBruce Richardson struct rte_thread_ctrl_params *params; 302705356f0SHonnappa Nagarahalli enum __rte_ctrl_thread_status ctrl_thread_status; 30399a2dd95SBruce Richardson int ret; 30499a2dd95SBruce Richardson 30599a2dd95SBruce Richardson params = malloc(sizeof(*params)); 30699a2dd95SBruce Richardson if (!params) 30799a2dd95SBruce Richardson return -ENOMEM; 30899a2dd95SBruce Richardson 309878b7468STyler Retzlaff params->u.ctrl_start_routine = start_routine; 31099a2dd95SBruce Richardson params->arg = arg; 311705356f0SHonnappa Nagarahalli params->ret = 0; 312705356f0SHonnappa Nagarahalli params->ctrl_thread_status = CTRL_THREAD_LAUNCHING; 31399a2dd95SBruce Richardson 314878b7468STyler Retzlaff ret = pthread_create(thread, attr, ctrl_thread_start, (void *)params); 315705356f0SHonnappa Nagarahalli if (ret != 0) { 316705356f0SHonnappa Nagarahalli free(params); 317705356f0SHonnappa Nagarahalli return -ret; 318705356f0SHonnappa Nagarahalli } 31999a2dd95SBruce Richardson 3206d87be58STyler Retzlaff if (name != NULL) 3216d87be58STyler Retzlaff rte_thread_set_name((rte_thread_t){(uintptr_t)*thread}, name); 32299a2dd95SBruce Richardson 323705356f0SHonnappa Nagarahalli /* Wait for the control thread to initialize successfully */ 324705356f0SHonnappa Nagarahalli while ((ctrl_thread_status = 325705356f0SHonnappa Nagarahalli __atomic_load_n(¶ms->ctrl_thread_status, 326705356f0SHonnappa Nagarahalli __ATOMIC_ACQUIRE)) == CTRL_THREAD_LAUNCHING) { 327705356f0SHonnappa Nagarahalli /* Yield the CPU. Using sched_yield call requires maintaining 328705356f0SHonnappa Nagarahalli * another implementation for Windows as sched_yield is not 329705356f0SHonnappa Nagarahalli * supported on Windows. 330705356f0SHonnappa Nagarahalli */ 331705356f0SHonnappa Nagarahalli rte_delay_us_sleep(1); 332705356f0SHonnappa Nagarahalli } 33399a2dd95SBruce Richardson 334705356f0SHonnappa Nagarahalli /* Check if the control thread encountered an error */ 335705356f0SHonnappa Nagarahalli if (ctrl_thread_status == CTRL_THREAD_ERROR) { 336705356f0SHonnappa Nagarahalli /* ctrl thread is exiting */ 337*db77fe7dSTyler Retzlaff rte_thread_join((rte_thread_t){(uintptr_t)*thread}, NULL); 338705356f0SHonnappa Nagarahalli } 33999a2dd95SBruce Richardson 340705356f0SHonnappa Nagarahalli ret = params->ret; 34199a2dd95SBruce Richardson free(params); 34299a2dd95SBruce Richardson 34399a2dd95SBruce Richardson return -ret; 34499a2dd95SBruce Richardson } 34599a2dd95SBruce Richardson 34699a2dd95SBruce Richardson int 347878b7468STyler Retzlaff rte_thread_create_control(rte_thread_t *thread, const char *name, 348878b7468STyler Retzlaff const rte_thread_attr_t *attr, rte_thread_func start_routine, 349878b7468STyler Retzlaff void *arg) 350878b7468STyler Retzlaff { 351878b7468STyler Retzlaff struct rte_thread_ctrl_params *params; 352878b7468STyler Retzlaff enum __rte_ctrl_thread_status ctrl_thread_status; 353878b7468STyler Retzlaff int ret; 354878b7468STyler Retzlaff 355878b7468STyler Retzlaff params = malloc(sizeof(*params)); 356878b7468STyler Retzlaff if (params == NULL) 357878b7468STyler Retzlaff return -ENOMEM; 358878b7468STyler Retzlaff 359878b7468STyler Retzlaff params->u.control_start_routine = start_routine; 360878b7468STyler Retzlaff params->arg = arg; 361878b7468STyler Retzlaff params->ret = 0; 362878b7468STyler Retzlaff params->ctrl_thread_status = CTRL_THREAD_LAUNCHING; 363878b7468STyler Retzlaff 364878b7468STyler Retzlaff ret = rte_thread_create(thread, attr, control_thread_start, params); 365878b7468STyler Retzlaff if (ret != 0) { 366878b7468STyler Retzlaff free(params); 367878b7468STyler Retzlaff return -ret; 368878b7468STyler Retzlaff } 369878b7468STyler Retzlaff 370878b7468STyler Retzlaff if (name != NULL) 371878b7468STyler Retzlaff rte_thread_set_name(*thread, name); 372878b7468STyler Retzlaff 373878b7468STyler Retzlaff /* Wait for the control thread to initialize successfully */ 374878b7468STyler Retzlaff while ((ctrl_thread_status = 375878b7468STyler Retzlaff __atomic_load_n(¶ms->ctrl_thread_status, 376878b7468STyler Retzlaff __ATOMIC_ACQUIRE)) == CTRL_THREAD_LAUNCHING) { 377878b7468STyler Retzlaff rte_delay_us_sleep(1); 378878b7468STyler Retzlaff } 379878b7468STyler Retzlaff 380878b7468STyler Retzlaff /* Check if the control thread encountered an error */ 381878b7468STyler Retzlaff if (ctrl_thread_status == CTRL_THREAD_ERROR) { 382878b7468STyler Retzlaff /* ctrl thread is exiting */ 383878b7468STyler Retzlaff rte_thread_join(*thread, NULL); 384878b7468STyler Retzlaff } 385878b7468STyler Retzlaff 386878b7468STyler Retzlaff ret = params->ret; 387878b7468STyler Retzlaff free(params); 388878b7468STyler Retzlaff 389878b7468STyler Retzlaff return ret; 390878b7468STyler Retzlaff } 391878b7468STyler Retzlaff 392878b7468STyler Retzlaff int 39399a2dd95SBruce Richardson rte_thread_register(void) 39499a2dd95SBruce Richardson { 39599a2dd95SBruce Richardson unsigned int lcore_id; 39699a2dd95SBruce Richardson rte_cpuset_t cpuset; 39799a2dd95SBruce Richardson 39899a2dd95SBruce Richardson /* EAL init flushes all lcores, we can't register before. */ 39999a2dd95SBruce Richardson if (eal_get_internal_configuration()->init_complete != 1) { 40099a2dd95SBruce Richardson RTE_LOG(DEBUG, EAL, "Called %s before EAL init.\n", __func__); 40199a2dd95SBruce Richardson rte_errno = EINVAL; 40299a2dd95SBruce Richardson return -1; 40399a2dd95SBruce Richardson } 40499a2dd95SBruce Richardson if (!rte_mp_disable()) { 40599a2dd95SBruce Richardson RTE_LOG(ERR, EAL, "Multiprocess in use, registering non-EAL threads is not supported.\n"); 40699a2dd95SBruce Richardson rte_errno = EINVAL; 40799a2dd95SBruce Richardson return -1; 40899a2dd95SBruce Richardson } 4098b0a1b8cSTyler Retzlaff if (rte_thread_get_affinity_by_id(rte_thread_self(), &cpuset) != 0) 41099a2dd95SBruce Richardson CPU_ZERO(&cpuset); 41199a2dd95SBruce Richardson lcore_id = eal_lcore_non_eal_allocate(); 41299a2dd95SBruce Richardson if (lcore_id >= RTE_MAX_LCORE) 41399a2dd95SBruce Richardson lcore_id = LCORE_ID_ANY; 41499a2dd95SBruce Richardson __rte_thread_init(lcore_id, &cpuset); 41599a2dd95SBruce Richardson if (lcore_id == LCORE_ID_ANY) { 41699a2dd95SBruce Richardson rte_errno = ENOMEM; 41799a2dd95SBruce Richardson return -1; 41899a2dd95SBruce Richardson } 41999a2dd95SBruce Richardson RTE_LOG(DEBUG, EAL, "Registered non-EAL thread as lcore %u.\n", 42099a2dd95SBruce Richardson lcore_id); 42199a2dd95SBruce Richardson return 0; 42299a2dd95SBruce Richardson } 42399a2dd95SBruce Richardson 42499a2dd95SBruce Richardson void 42599a2dd95SBruce Richardson rte_thread_unregister(void) 42699a2dd95SBruce Richardson { 42799a2dd95SBruce Richardson unsigned int lcore_id = rte_lcore_id(); 42899a2dd95SBruce Richardson 42999a2dd95SBruce Richardson if (lcore_id != LCORE_ID_ANY) 43099a2dd95SBruce Richardson eal_lcore_non_eal_release(lcore_id); 43199a2dd95SBruce Richardson __rte_thread_uninit(); 43299a2dd95SBruce Richardson if (lcore_id != LCORE_ID_ANY) 43399a2dd95SBruce Richardson RTE_LOG(DEBUG, EAL, "Unregistered non-EAL thread (was lcore %u).\n", 43499a2dd95SBruce Richardson lcore_id); 43599a2dd95SBruce Richardson } 43651e6608aSTyler Retzlaff 43751e6608aSTyler Retzlaff int 43851e6608aSTyler Retzlaff rte_thread_attr_init(rte_thread_attr_t *attr) 43951e6608aSTyler Retzlaff { 44051e6608aSTyler Retzlaff if (attr == NULL) 44151e6608aSTyler Retzlaff return EINVAL; 44251e6608aSTyler Retzlaff 44351e6608aSTyler Retzlaff CPU_ZERO(&attr->cpuset); 44451e6608aSTyler Retzlaff attr->priority = RTE_THREAD_PRIORITY_NORMAL; 44551e6608aSTyler Retzlaff 44651e6608aSTyler Retzlaff return 0; 44751e6608aSTyler Retzlaff } 44851e6608aSTyler Retzlaff 44951e6608aSTyler Retzlaff int 45051e6608aSTyler Retzlaff rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr, 45151e6608aSTyler Retzlaff enum rte_thread_priority priority) 45251e6608aSTyler Retzlaff { 45351e6608aSTyler Retzlaff if (thread_attr == NULL) 45451e6608aSTyler Retzlaff return EINVAL; 45551e6608aSTyler Retzlaff 45651e6608aSTyler Retzlaff thread_attr->priority = priority; 45751e6608aSTyler Retzlaff 45851e6608aSTyler Retzlaff return 0; 45951e6608aSTyler Retzlaff } 46051e6608aSTyler Retzlaff 46151e6608aSTyler Retzlaff int 46251e6608aSTyler Retzlaff rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr, 46351e6608aSTyler Retzlaff rte_cpuset_t *cpuset) 46451e6608aSTyler Retzlaff { 46551e6608aSTyler Retzlaff if (thread_attr == NULL) 46651e6608aSTyler Retzlaff return EINVAL; 46751e6608aSTyler Retzlaff 46851e6608aSTyler Retzlaff if (cpuset == NULL) 46951e6608aSTyler Retzlaff return EINVAL; 47051e6608aSTyler Retzlaff 47151e6608aSTyler Retzlaff thread_attr->cpuset = *cpuset; 47251e6608aSTyler Retzlaff 47351e6608aSTyler Retzlaff return 0; 47451e6608aSTyler Retzlaff } 47551e6608aSTyler Retzlaff 47651e6608aSTyler Retzlaff int 47751e6608aSTyler Retzlaff rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr, 47851e6608aSTyler Retzlaff rte_cpuset_t *cpuset) 47951e6608aSTyler Retzlaff { 48051e6608aSTyler Retzlaff if (thread_attr == NULL) 48151e6608aSTyler Retzlaff return EINVAL; 48251e6608aSTyler Retzlaff 48351e6608aSTyler Retzlaff if (cpuset == NULL) 48451e6608aSTyler Retzlaff return EINVAL; 48551e6608aSTyler Retzlaff 48651e6608aSTyler Retzlaff *cpuset = thread_attr->cpuset; 48751e6608aSTyler Retzlaff 48851e6608aSTyler Retzlaff return 0; 48951e6608aSTyler Retzlaff } 490