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", 179db77fe7dSTyler 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 208841e87dfSArnaud Fiorini rte_eal_trace_thread_lcore_running(lcore_id, f); 209841e87dfSArnaud Fiorini 210a95d7054SDavid Marchand /* call the function and store the return value */ 211a95d7054SDavid Marchand fct_arg = lcore_config[lcore_id].arg; 212a95d7054SDavid Marchand ret = f(fct_arg); 213a95d7054SDavid Marchand lcore_config[lcore_id].ret = ret; 214a95d7054SDavid Marchand lcore_config[lcore_id].f = NULL; 215a95d7054SDavid Marchand lcore_config[lcore_id].arg = NULL; 216a95d7054SDavid Marchand 217a95d7054SDavid Marchand /* Store the state with release order to ensure that 218a95d7054SDavid Marchand * the memory operations from the worker thread 219a95d7054SDavid Marchand * are completed before the state is updated. 220a95d7054SDavid Marchand * Use 'state' as the guard variable. 221a95d7054SDavid Marchand */ 222a95d7054SDavid Marchand __atomic_store_n(&lcore_config[lcore_id].state, WAIT, 223a95d7054SDavid Marchand __ATOMIC_RELEASE); 224841e87dfSArnaud Fiorini 225841e87dfSArnaud Fiorini rte_eal_trace_thread_lcore_stopped(lcore_id); 226a95d7054SDavid Marchand } 227a95d7054SDavid Marchand 228a95d7054SDavid Marchand /* never reached */ 2298b0a1b8cSTyler Retzlaff /* return 0; */ 230a95d7054SDavid Marchand } 231a95d7054SDavid Marchand 232705356f0SHonnappa Nagarahalli enum __rte_ctrl_thread_status { 233705356f0SHonnappa Nagarahalli CTRL_THREAD_LAUNCHING, /* Yet to call pthread_create function */ 234705356f0SHonnappa Nagarahalli CTRL_THREAD_RUNNING, /* Control thread is running successfully */ 235705356f0SHonnappa Nagarahalli CTRL_THREAD_ERROR /* Control thread encountered an error */ 236705356f0SHonnappa Nagarahalli }; 237705356f0SHonnappa Nagarahalli 23899a2dd95SBruce Richardson struct rte_thread_ctrl_params { 239878b7468STyler Retzlaff union { 240878b7468STyler Retzlaff void *(*ctrl_start_routine)(void *arg); 241878b7468STyler Retzlaff rte_thread_func control_start_routine; 242878b7468STyler Retzlaff } u; 24399a2dd95SBruce Richardson void *arg; 244705356f0SHonnappa Nagarahalli int ret; 245705356f0SHonnappa Nagarahalli /* Control thread status. 246705356f0SHonnappa Nagarahalli * If the status is CTRL_THREAD_ERROR, 'ret' has the error code. 247705356f0SHonnappa Nagarahalli */ 248705356f0SHonnappa Nagarahalli enum __rte_ctrl_thread_status ctrl_thread_status; 24999a2dd95SBruce Richardson }; 25099a2dd95SBruce Richardson 251878b7468STyler Retzlaff static int ctrl_thread_init(void *arg) 25299a2dd95SBruce Richardson { 25399a2dd95SBruce Richardson struct internal_config *internal_conf = 25499a2dd95SBruce Richardson eal_get_internal_configuration(); 25599a2dd95SBruce Richardson rte_cpuset_t *cpuset = &internal_conf->ctrl_cpuset; 25699a2dd95SBruce Richardson struct rte_thread_ctrl_params *params = arg; 25799a2dd95SBruce Richardson 25899a2dd95SBruce Richardson __rte_thread_init(rte_lcore_id(), cpuset); 2597e7b6762SKaisen You /* Set control thread socket ID to SOCKET_ID_ANY 2607e7b6762SKaisen You * as control threads may be scheduled on any NUMA node. 2617e7b6762SKaisen You */ 2627e7b6762SKaisen You RTE_PER_LCORE(_socket_id) = SOCKET_ID_ANY; 2638b0a1b8cSTyler Retzlaff params->ret = rte_thread_set_affinity_by_id(rte_thread_self(), cpuset); 264705356f0SHonnappa Nagarahalli if (params->ret != 0) { 265705356f0SHonnappa Nagarahalli __atomic_store_n(¶ms->ctrl_thread_status, 266705356f0SHonnappa Nagarahalli CTRL_THREAD_ERROR, __ATOMIC_RELEASE); 267b27c1bd8STyler Retzlaff return 1; 268705356f0SHonnappa Nagarahalli } 269705356f0SHonnappa Nagarahalli 270705356f0SHonnappa Nagarahalli __atomic_store_n(¶ms->ctrl_thread_status, 271705356f0SHonnappa Nagarahalli CTRL_THREAD_RUNNING, __ATOMIC_RELEASE); 27299a2dd95SBruce Richardson 273878b7468STyler Retzlaff return 0; 274878b7468STyler Retzlaff } 275878b7468STyler Retzlaff 276878b7468STyler Retzlaff static void *ctrl_thread_start(void *arg) 277878b7468STyler Retzlaff { 278878b7468STyler Retzlaff struct rte_thread_ctrl_params *params = arg; 279b27c1bd8STyler Retzlaff void *start_arg = params->arg; 280878b7468STyler Retzlaff void *(*start_routine)(void *) = params->u.ctrl_start_routine; 281878b7468STyler Retzlaff 282878b7468STyler Retzlaff if (ctrl_thread_init(arg) != 0) 283878b7468STyler Retzlaff return NULL; 284878b7468STyler Retzlaff 285b27c1bd8STyler Retzlaff return start_routine(start_arg); 286878b7468STyler Retzlaff } 287878b7468STyler Retzlaff 288878b7468STyler Retzlaff static uint32_t control_thread_start(void *arg) 289878b7468STyler Retzlaff { 290878b7468STyler Retzlaff struct rte_thread_ctrl_params *params = arg; 291b27c1bd8STyler Retzlaff void *start_arg = params->arg; 292878b7468STyler Retzlaff rte_thread_func start_routine = params->u.control_start_routine; 293878b7468STyler Retzlaff 294878b7468STyler Retzlaff if (ctrl_thread_init(arg) != 0) 295b27c1bd8STyler Retzlaff return 0; 296878b7468STyler Retzlaff 297b27c1bd8STyler Retzlaff return start_routine(start_arg); 29899a2dd95SBruce Richardson } 29999a2dd95SBruce Richardson 30099a2dd95SBruce Richardson int 30199a2dd95SBruce Richardson rte_ctrl_thread_create(pthread_t *thread, const char *name, 30299a2dd95SBruce Richardson const pthread_attr_t *attr, 30399a2dd95SBruce Richardson void *(*start_routine)(void *), void *arg) 30499a2dd95SBruce Richardson { 30599a2dd95SBruce Richardson struct rte_thread_ctrl_params *params; 306705356f0SHonnappa Nagarahalli enum __rte_ctrl_thread_status ctrl_thread_status; 30799a2dd95SBruce Richardson int ret; 30899a2dd95SBruce Richardson 30999a2dd95SBruce Richardson params = malloc(sizeof(*params)); 31099a2dd95SBruce Richardson if (!params) 31199a2dd95SBruce Richardson return -ENOMEM; 31299a2dd95SBruce Richardson 313878b7468STyler Retzlaff params->u.ctrl_start_routine = start_routine; 31499a2dd95SBruce Richardson params->arg = arg; 315705356f0SHonnappa Nagarahalli params->ret = 0; 316705356f0SHonnappa Nagarahalli params->ctrl_thread_status = CTRL_THREAD_LAUNCHING; 31799a2dd95SBruce Richardson 318878b7468STyler Retzlaff ret = pthread_create(thread, attr, ctrl_thread_start, (void *)params); 319705356f0SHonnappa Nagarahalli if (ret != 0) { 320705356f0SHonnappa Nagarahalli free(params); 321705356f0SHonnappa Nagarahalli return -ret; 322705356f0SHonnappa Nagarahalli } 32399a2dd95SBruce Richardson 3246d87be58STyler Retzlaff if (name != NULL) 3256d87be58STyler Retzlaff rte_thread_set_name((rte_thread_t){(uintptr_t)*thread}, name); 32699a2dd95SBruce Richardson 327705356f0SHonnappa Nagarahalli /* Wait for the control thread to initialize successfully */ 328705356f0SHonnappa Nagarahalli while ((ctrl_thread_status = 329705356f0SHonnappa Nagarahalli __atomic_load_n(¶ms->ctrl_thread_status, 330705356f0SHonnappa Nagarahalli __ATOMIC_ACQUIRE)) == CTRL_THREAD_LAUNCHING) { 331705356f0SHonnappa Nagarahalli /* Yield the CPU. Using sched_yield call requires maintaining 332705356f0SHonnappa Nagarahalli * another implementation for Windows as sched_yield is not 333705356f0SHonnappa Nagarahalli * supported on Windows. 334705356f0SHonnappa Nagarahalli */ 335705356f0SHonnappa Nagarahalli rte_delay_us_sleep(1); 336705356f0SHonnappa Nagarahalli } 33799a2dd95SBruce Richardson 338705356f0SHonnappa Nagarahalli /* Check if the control thread encountered an error */ 339705356f0SHonnappa Nagarahalli if (ctrl_thread_status == CTRL_THREAD_ERROR) { 340705356f0SHonnappa Nagarahalli /* ctrl thread is exiting */ 341db77fe7dSTyler Retzlaff rte_thread_join((rte_thread_t){(uintptr_t)*thread}, NULL); 342705356f0SHonnappa Nagarahalli } 34399a2dd95SBruce Richardson 344705356f0SHonnappa Nagarahalli ret = params->ret; 34599a2dd95SBruce Richardson free(params); 34699a2dd95SBruce Richardson 34799a2dd95SBruce Richardson return -ret; 34899a2dd95SBruce Richardson } 34999a2dd95SBruce Richardson 35099a2dd95SBruce Richardson int 351878b7468STyler Retzlaff rte_thread_create_control(rte_thread_t *thread, const char *name, 35270d19787SThomas Monjalon rte_thread_func start_routine, void *arg) 353878b7468STyler Retzlaff { 354878b7468STyler Retzlaff struct rte_thread_ctrl_params *params; 355878b7468STyler Retzlaff enum __rte_ctrl_thread_status ctrl_thread_status; 356878b7468STyler Retzlaff int ret; 357878b7468STyler Retzlaff 358878b7468STyler Retzlaff params = malloc(sizeof(*params)); 359878b7468STyler Retzlaff if (params == NULL) 360878b7468STyler Retzlaff return -ENOMEM; 361878b7468STyler Retzlaff 362878b7468STyler Retzlaff params->u.control_start_routine = start_routine; 363878b7468STyler Retzlaff params->arg = arg; 364878b7468STyler Retzlaff params->ret = 0; 365878b7468STyler Retzlaff params->ctrl_thread_status = CTRL_THREAD_LAUNCHING; 366878b7468STyler Retzlaff 36770d19787SThomas Monjalon ret = rte_thread_create(thread, NULL, control_thread_start, params); 368878b7468STyler Retzlaff if (ret != 0) { 369878b7468STyler Retzlaff free(params); 370878b7468STyler Retzlaff return -ret; 371878b7468STyler Retzlaff } 372878b7468STyler Retzlaff 373878b7468STyler Retzlaff if (name != NULL) 374878b7468STyler Retzlaff rte_thread_set_name(*thread, name); 375878b7468STyler Retzlaff 376878b7468STyler Retzlaff /* Wait for the control thread to initialize successfully */ 377878b7468STyler Retzlaff while ((ctrl_thread_status = 378878b7468STyler Retzlaff __atomic_load_n(¶ms->ctrl_thread_status, 379878b7468STyler Retzlaff __ATOMIC_ACQUIRE)) == CTRL_THREAD_LAUNCHING) { 380878b7468STyler Retzlaff rte_delay_us_sleep(1); 381878b7468STyler Retzlaff } 382878b7468STyler Retzlaff 383878b7468STyler Retzlaff /* Check if the control thread encountered an error */ 384878b7468STyler Retzlaff if (ctrl_thread_status == CTRL_THREAD_ERROR) { 385878b7468STyler Retzlaff /* ctrl thread is exiting */ 386878b7468STyler Retzlaff rte_thread_join(*thread, NULL); 387878b7468STyler Retzlaff } 388878b7468STyler Retzlaff 389878b7468STyler Retzlaff ret = params->ret; 390878b7468STyler Retzlaff free(params); 391878b7468STyler Retzlaff 392878b7468STyler Retzlaff return ret; 393878b7468STyler Retzlaff } 394878b7468STyler Retzlaff 395*ce703c47SThomas Monjalon static void 396*ce703c47SThomas Monjalon add_internal_prefix(char *prefixed_name, const char *name, size_t size) 397*ce703c47SThomas Monjalon { 398*ce703c47SThomas Monjalon size_t prefixlen; 399*ce703c47SThomas Monjalon 400*ce703c47SThomas Monjalon /* Check RTE_THREAD_INTERNAL_NAME_SIZE definition. */ 401*ce703c47SThomas Monjalon RTE_BUILD_BUG_ON(RTE_THREAD_INTERNAL_NAME_SIZE != 402*ce703c47SThomas Monjalon RTE_THREAD_NAME_SIZE - sizeof(RTE_THREAD_INTERNAL_PREFIX) + 1); 403*ce703c47SThomas Monjalon 404*ce703c47SThomas Monjalon prefixlen = strlen(RTE_THREAD_INTERNAL_PREFIX); 405*ce703c47SThomas Monjalon strlcpy(prefixed_name, RTE_THREAD_INTERNAL_PREFIX, size); 406*ce703c47SThomas Monjalon strlcpy(prefixed_name + prefixlen, name, size - prefixlen); 407*ce703c47SThomas Monjalon } 408*ce703c47SThomas Monjalon 409*ce703c47SThomas Monjalon int 410*ce703c47SThomas Monjalon rte_thread_create_internal_control(rte_thread_t *id, const char *name, 411*ce703c47SThomas Monjalon rte_thread_func func, void *arg) 412*ce703c47SThomas Monjalon { 413*ce703c47SThomas Monjalon char prefixed_name[RTE_THREAD_NAME_SIZE]; 414*ce703c47SThomas Monjalon 415*ce703c47SThomas Monjalon add_internal_prefix(prefixed_name, name, sizeof(prefixed_name)); 416*ce703c47SThomas Monjalon return rte_thread_create_control(id, prefixed_name, func, arg); 417*ce703c47SThomas Monjalon } 418*ce703c47SThomas Monjalon 419*ce703c47SThomas Monjalon void 420*ce703c47SThomas Monjalon rte_thread_set_prefixed_name(rte_thread_t id, const char *name) 421*ce703c47SThomas Monjalon { 422*ce703c47SThomas Monjalon char prefixed_name[RTE_THREAD_NAME_SIZE]; 423*ce703c47SThomas Monjalon 424*ce703c47SThomas Monjalon add_internal_prefix(prefixed_name, name, sizeof(prefixed_name)); 425*ce703c47SThomas Monjalon rte_thread_set_name(id, prefixed_name); 426*ce703c47SThomas Monjalon } 427*ce703c47SThomas Monjalon 428878b7468STyler Retzlaff int 42999a2dd95SBruce Richardson rte_thread_register(void) 43099a2dd95SBruce Richardson { 43199a2dd95SBruce Richardson unsigned int lcore_id; 43299a2dd95SBruce Richardson rte_cpuset_t cpuset; 43399a2dd95SBruce Richardson 43499a2dd95SBruce Richardson /* EAL init flushes all lcores, we can't register before. */ 43599a2dd95SBruce Richardson if (eal_get_internal_configuration()->init_complete != 1) { 43699a2dd95SBruce Richardson RTE_LOG(DEBUG, EAL, "Called %s before EAL init.\n", __func__); 43799a2dd95SBruce Richardson rte_errno = EINVAL; 43899a2dd95SBruce Richardson return -1; 43999a2dd95SBruce Richardson } 44099a2dd95SBruce Richardson if (!rte_mp_disable()) { 44199a2dd95SBruce Richardson RTE_LOG(ERR, EAL, "Multiprocess in use, registering non-EAL threads is not supported.\n"); 44299a2dd95SBruce Richardson rte_errno = EINVAL; 44399a2dd95SBruce Richardson return -1; 44499a2dd95SBruce Richardson } 4458b0a1b8cSTyler Retzlaff if (rte_thread_get_affinity_by_id(rte_thread_self(), &cpuset) != 0) 44699a2dd95SBruce Richardson CPU_ZERO(&cpuset); 44799a2dd95SBruce Richardson lcore_id = eal_lcore_non_eal_allocate(); 44899a2dd95SBruce Richardson if (lcore_id >= RTE_MAX_LCORE) 44999a2dd95SBruce Richardson lcore_id = LCORE_ID_ANY; 45099a2dd95SBruce Richardson __rte_thread_init(lcore_id, &cpuset); 45199a2dd95SBruce Richardson if (lcore_id == LCORE_ID_ANY) { 45299a2dd95SBruce Richardson rte_errno = ENOMEM; 45399a2dd95SBruce Richardson return -1; 45499a2dd95SBruce Richardson } 45599a2dd95SBruce Richardson RTE_LOG(DEBUG, EAL, "Registered non-EAL thread as lcore %u.\n", 45699a2dd95SBruce Richardson lcore_id); 45799a2dd95SBruce Richardson return 0; 45899a2dd95SBruce Richardson } 45999a2dd95SBruce Richardson 46099a2dd95SBruce Richardson void 46199a2dd95SBruce Richardson rte_thread_unregister(void) 46299a2dd95SBruce Richardson { 46399a2dd95SBruce Richardson unsigned int lcore_id = rte_lcore_id(); 46499a2dd95SBruce Richardson 46599a2dd95SBruce Richardson if (lcore_id != LCORE_ID_ANY) 46699a2dd95SBruce Richardson eal_lcore_non_eal_release(lcore_id); 46799a2dd95SBruce Richardson __rte_thread_uninit(); 46899a2dd95SBruce Richardson if (lcore_id != LCORE_ID_ANY) 46999a2dd95SBruce Richardson RTE_LOG(DEBUG, EAL, "Unregistered non-EAL thread (was lcore %u).\n", 47099a2dd95SBruce Richardson lcore_id); 47199a2dd95SBruce Richardson } 47251e6608aSTyler Retzlaff 47351e6608aSTyler Retzlaff int 47451e6608aSTyler Retzlaff rte_thread_attr_init(rte_thread_attr_t *attr) 47551e6608aSTyler Retzlaff { 47651e6608aSTyler Retzlaff if (attr == NULL) 47751e6608aSTyler Retzlaff return EINVAL; 47851e6608aSTyler Retzlaff 47951e6608aSTyler Retzlaff CPU_ZERO(&attr->cpuset); 48051e6608aSTyler Retzlaff attr->priority = RTE_THREAD_PRIORITY_NORMAL; 48151e6608aSTyler Retzlaff 48251e6608aSTyler Retzlaff return 0; 48351e6608aSTyler Retzlaff } 48451e6608aSTyler Retzlaff 48551e6608aSTyler Retzlaff int 48651e6608aSTyler Retzlaff rte_thread_attr_set_priority(rte_thread_attr_t *thread_attr, 48751e6608aSTyler Retzlaff enum rte_thread_priority priority) 48851e6608aSTyler Retzlaff { 48951e6608aSTyler Retzlaff if (thread_attr == NULL) 49051e6608aSTyler Retzlaff return EINVAL; 49151e6608aSTyler Retzlaff 49251e6608aSTyler Retzlaff thread_attr->priority = priority; 49351e6608aSTyler Retzlaff 49451e6608aSTyler Retzlaff return 0; 49551e6608aSTyler Retzlaff } 49651e6608aSTyler Retzlaff 49751e6608aSTyler Retzlaff int 49851e6608aSTyler Retzlaff rte_thread_attr_set_affinity(rte_thread_attr_t *thread_attr, 49951e6608aSTyler Retzlaff rte_cpuset_t *cpuset) 50051e6608aSTyler Retzlaff { 50151e6608aSTyler Retzlaff if (thread_attr == NULL) 50251e6608aSTyler Retzlaff return EINVAL; 50351e6608aSTyler Retzlaff 50451e6608aSTyler Retzlaff if (cpuset == NULL) 50551e6608aSTyler Retzlaff return EINVAL; 50651e6608aSTyler Retzlaff 50751e6608aSTyler Retzlaff thread_attr->cpuset = *cpuset; 50851e6608aSTyler Retzlaff 50951e6608aSTyler Retzlaff return 0; 51051e6608aSTyler Retzlaff } 51151e6608aSTyler Retzlaff 51251e6608aSTyler Retzlaff int 51351e6608aSTyler Retzlaff rte_thread_attr_get_affinity(rte_thread_attr_t *thread_attr, 51451e6608aSTyler Retzlaff rte_cpuset_t *cpuset) 51551e6608aSTyler Retzlaff { 51651e6608aSTyler Retzlaff if (thread_attr == NULL) 51751e6608aSTyler Retzlaff return EINVAL; 51851e6608aSTyler Retzlaff 51951e6608aSTyler Retzlaff if (cpuset == NULL) 52051e6608aSTyler Retzlaff return EINVAL; 52151e6608aSTyler Retzlaff 52251e6608aSTyler Retzlaff *cpuset = thread_attr->cpuset; 52351e6608aSTyler Retzlaff 52451e6608aSTyler Retzlaff return 0; 52551e6608aSTyler Retzlaff } 526