199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 299a2dd95SBruce Richardson * Copyright 2021 Mellanox Technologies, Ltd 356539289STyler Retzlaff * Copyright (C) 2022 Microsoft Corporation 499a2dd95SBruce Richardson */ 599a2dd95SBruce Richardson 699a2dd95SBruce Richardson #include <errno.h> 799a2dd95SBruce Richardson #include <pthread.h> 8b28c6196STyler Retzlaff #include <stdbool.h> 999a2dd95SBruce Richardson #include <stdlib.h> 1099a2dd95SBruce Richardson #include <string.h> 1199a2dd95SBruce Richardson 1299a2dd95SBruce Richardson #include <rte_errno.h> 1399a2dd95SBruce Richardson #include <rte_log.h> 1499a2dd95SBruce Richardson #include <rte_thread.h> 1599a2dd95SBruce Richardson 16ae67895bSDavid Marchand #include "eal_private.h" 17ae67895bSDavid Marchand 1899a2dd95SBruce Richardson struct eal_tls_key { 1999a2dd95SBruce Richardson pthread_key_t thread_index; 2099a2dd95SBruce Richardson }; 2199a2dd95SBruce Richardson 22*64f27886SDavid Marchand #ifndef RTE_EAL_PTHREAD_ATTR_SETAFFINITY_NP 23b28c6196STyler Retzlaff struct thread_start_context { 24ce6e911dSTyler Retzlaff rte_thread_func thread_func; 25b28c6196STyler Retzlaff void *thread_args; 26b28c6196STyler Retzlaff const rte_thread_attr_t *thread_attr; 27b28c6196STyler Retzlaff pthread_mutex_t wrapper_mutex; 28b28c6196STyler Retzlaff pthread_cond_t wrapper_cond; 29b28c6196STyler Retzlaff int wrapper_ret; 30b28c6196STyler Retzlaff bool wrapper_done; 31ce6e911dSTyler Retzlaff }; 32*64f27886SDavid Marchand #endif 33ce6e911dSTyler Retzlaff 34ca04c78bSTyler Retzlaff static int 35ca04c78bSTyler Retzlaff thread_map_priority_to_os_value(enum rte_thread_priority eal_pri, int *os_pri, 36ca04c78bSTyler Retzlaff int *pol) 37ca04c78bSTyler Retzlaff { 38ca04c78bSTyler Retzlaff /* Clear the output parameters. */ 39ca04c78bSTyler Retzlaff *os_pri = sched_get_priority_min(SCHED_OTHER) - 1; 40ca04c78bSTyler Retzlaff *pol = -1; 41ca04c78bSTyler Retzlaff 42ca04c78bSTyler Retzlaff switch (eal_pri) { 43ca04c78bSTyler Retzlaff case RTE_THREAD_PRIORITY_NORMAL: 44ca04c78bSTyler Retzlaff *pol = SCHED_OTHER; 45ca04c78bSTyler Retzlaff 46ca04c78bSTyler Retzlaff /* 47ca04c78bSTyler Retzlaff * Choose the middle of the range to represent the priority 48ca04c78bSTyler Retzlaff * 'normal'. 49ca04c78bSTyler Retzlaff * On Linux, this should be 0, since both 50ca04c78bSTyler Retzlaff * sched_get_priority_min/_max return 0 for SCHED_OTHER. 51ca04c78bSTyler Retzlaff */ 52ca04c78bSTyler Retzlaff *os_pri = (sched_get_priority_min(SCHED_OTHER) + 53ca04c78bSTyler Retzlaff sched_get_priority_max(SCHED_OTHER)) / 2; 54ca04c78bSTyler Retzlaff break; 55ca04c78bSTyler Retzlaff case RTE_THREAD_PRIORITY_REALTIME_CRITICAL: 56ca04c78bSTyler Retzlaff *pol = SCHED_RR; 57ca04c78bSTyler Retzlaff *os_pri = sched_get_priority_max(SCHED_RR); 58ca04c78bSTyler Retzlaff break; 59ca04c78bSTyler Retzlaff default: 60ae67895bSDavid Marchand EAL_LOG(DEBUG, "The requested priority value is invalid."); 61ca04c78bSTyler Retzlaff return EINVAL; 62ca04c78bSTyler Retzlaff } 63ca04c78bSTyler Retzlaff 64ca04c78bSTyler Retzlaff return 0; 65ca04c78bSTyler Retzlaff } 66ca04c78bSTyler Retzlaff 67ca04c78bSTyler Retzlaff static int 68ca04c78bSTyler Retzlaff thread_map_os_priority_to_eal_priority(int policy, int os_pri, 69ca04c78bSTyler Retzlaff enum rte_thread_priority *eal_pri) 70ca04c78bSTyler Retzlaff { 71ca04c78bSTyler Retzlaff switch (policy) { 72ca04c78bSTyler Retzlaff case SCHED_OTHER: 73ca04c78bSTyler Retzlaff if (os_pri == (sched_get_priority_min(SCHED_OTHER) + 74ca04c78bSTyler Retzlaff sched_get_priority_max(SCHED_OTHER)) / 2) { 75ca04c78bSTyler Retzlaff *eal_pri = RTE_THREAD_PRIORITY_NORMAL; 76ca04c78bSTyler Retzlaff return 0; 77ca04c78bSTyler Retzlaff } 78ca04c78bSTyler Retzlaff break; 79ca04c78bSTyler Retzlaff case SCHED_RR: 80ca04c78bSTyler Retzlaff if (os_pri == sched_get_priority_max(SCHED_RR)) { 81ca04c78bSTyler Retzlaff *eal_pri = RTE_THREAD_PRIORITY_REALTIME_CRITICAL; 82ca04c78bSTyler Retzlaff return 0; 83ca04c78bSTyler Retzlaff } 84ca04c78bSTyler Retzlaff break; 85ca04c78bSTyler Retzlaff default: 86ae67895bSDavid Marchand EAL_LOG(DEBUG, "The OS priority value does not map to an EAL-defined priority."); 87ca04c78bSTyler Retzlaff return EINVAL; 88ca04c78bSTyler Retzlaff } 89ca04c78bSTyler Retzlaff 90ca04c78bSTyler Retzlaff return 0; 91ca04c78bSTyler Retzlaff } 92ca04c78bSTyler Retzlaff 93*64f27886SDavid Marchand #ifndef RTE_EAL_PTHREAD_ATTR_SETAFFINITY_NP 94ce6e911dSTyler Retzlaff static void * 95b28c6196STyler Retzlaff thread_start_wrapper(void *arg) 96ce6e911dSTyler Retzlaff { 97b28c6196STyler Retzlaff struct thread_start_context *ctx = (struct thread_start_context *)arg; 98b28c6196STyler Retzlaff rte_thread_func thread_func = ctx->thread_func; 99b28c6196STyler Retzlaff void *thread_args = ctx->thread_args; 100b28c6196STyler Retzlaff int ret = 0; 101ce6e911dSTyler Retzlaff 102b28c6196STyler Retzlaff if (ctx->thread_attr != NULL && CPU_COUNT(&ctx->thread_attr->cpuset) > 0) { 103b28c6196STyler Retzlaff ret = rte_thread_set_affinity_by_id(rte_thread_self(), &ctx->thread_attr->cpuset); 104b28c6196STyler Retzlaff if (ret != 0) 105ae67895bSDavid Marchand EAL_LOG(DEBUG, "rte_thread_set_affinity_by_id failed"); 106b28c6196STyler Retzlaff } 107ce6e911dSTyler Retzlaff 108b28c6196STyler Retzlaff pthread_mutex_lock(&ctx->wrapper_mutex); 109b28c6196STyler Retzlaff ctx->wrapper_ret = ret; 110b28c6196STyler Retzlaff ctx->wrapper_done = true; 111b28c6196STyler Retzlaff pthread_cond_signal(&ctx->wrapper_cond); 112b28c6196STyler Retzlaff pthread_mutex_unlock(&ctx->wrapper_mutex); 113b28c6196STyler Retzlaff 114b28c6196STyler Retzlaff if (ret != 0) 115b28c6196STyler Retzlaff return NULL; 116b28c6196STyler Retzlaff 117b28c6196STyler Retzlaff return (void *)(uintptr_t)thread_func(thread_args); 118ce6e911dSTyler Retzlaff } 119*64f27886SDavid Marchand #endif 120ce6e911dSTyler Retzlaff 121ce6e911dSTyler Retzlaff int 122ce6e911dSTyler Retzlaff rte_thread_create(rte_thread_t *thread_id, 123ce6e911dSTyler Retzlaff const rte_thread_attr_t *thread_attr, 124ce6e911dSTyler Retzlaff rte_thread_func thread_func, void *args) 125ce6e911dSTyler Retzlaff { 126ce6e911dSTyler Retzlaff int ret = 0; 127ce6e911dSTyler Retzlaff pthread_attr_t attr; 128ce6e911dSTyler Retzlaff pthread_attr_t *attrp = NULL; 129ce6e911dSTyler Retzlaff struct sched_param param = { 130ce6e911dSTyler Retzlaff .sched_priority = 0, 131ce6e911dSTyler Retzlaff }; 132ce6e911dSTyler Retzlaff int policy = SCHED_OTHER; 133*64f27886SDavid Marchand #ifndef RTE_EAL_PTHREAD_ATTR_SETAFFINITY_NP 134b28c6196STyler Retzlaff struct thread_start_context ctx = { 135b28c6196STyler Retzlaff .thread_func = thread_func, 136b28c6196STyler Retzlaff .thread_args = args, 137b28c6196STyler Retzlaff .thread_attr = thread_attr, 138b28c6196STyler Retzlaff .wrapper_done = false, 139b28c6196STyler Retzlaff .wrapper_mutex = PTHREAD_MUTEX_INITIALIZER, 140b28c6196STyler Retzlaff .wrapper_cond = PTHREAD_COND_INITIALIZER, 141b28c6196STyler Retzlaff }; 142*64f27886SDavid Marchand #endif 143ce6e911dSTyler Retzlaff 144ce6e911dSTyler Retzlaff if (thread_attr != NULL) { 145ce6e911dSTyler Retzlaff ret = pthread_attr_init(&attr); 146ce6e911dSTyler Retzlaff if (ret != 0) { 147ae67895bSDavid Marchand EAL_LOG(DEBUG, "pthread_attr_init failed"); 148ce6e911dSTyler Retzlaff goto cleanup; 149ce6e911dSTyler Retzlaff } 150ce6e911dSTyler Retzlaff 151ce6e911dSTyler Retzlaff attrp = &attr; 152ce6e911dSTyler Retzlaff 153*64f27886SDavid Marchand #ifdef RTE_EAL_PTHREAD_ATTR_SETAFFINITY_NP 154*64f27886SDavid Marchand if (CPU_COUNT(&thread_attr->cpuset) > 0) { 155*64f27886SDavid Marchand ret = pthread_attr_setaffinity_np(attrp, sizeof(thread_attr->cpuset), 156*64f27886SDavid Marchand &thread_attr->cpuset); 157*64f27886SDavid Marchand if (ret != 0) { 158*64f27886SDavid Marchand EAL_LOG(DEBUG, "pthread_attr_setaffinity_np failed"); 159*64f27886SDavid Marchand goto cleanup; 160*64f27886SDavid Marchand } 161*64f27886SDavid Marchand } 162*64f27886SDavid Marchand #endif 163ce6e911dSTyler Retzlaff /* 164ce6e911dSTyler Retzlaff * Set the inherit scheduler parameter to explicit, 165ce6e911dSTyler Retzlaff * otherwise the priority attribute is ignored. 166ce6e911dSTyler Retzlaff */ 167ce6e911dSTyler Retzlaff ret = pthread_attr_setinheritsched(attrp, 168ce6e911dSTyler Retzlaff PTHREAD_EXPLICIT_SCHED); 169ce6e911dSTyler Retzlaff if (ret != 0) { 170ae67895bSDavid Marchand EAL_LOG(DEBUG, "pthread_attr_setinheritsched failed"); 171ce6e911dSTyler Retzlaff goto cleanup; 172ce6e911dSTyler Retzlaff } 173ce6e911dSTyler Retzlaff 174ce6e911dSTyler Retzlaff if (thread_attr->priority == 175ce6e911dSTyler Retzlaff RTE_THREAD_PRIORITY_REALTIME_CRITICAL) { 176ce6e911dSTyler Retzlaff ret = ENOTSUP; 177ce6e911dSTyler Retzlaff goto cleanup; 178ce6e911dSTyler Retzlaff } 179ce6e911dSTyler Retzlaff ret = thread_map_priority_to_os_value(thread_attr->priority, 180ce6e911dSTyler Retzlaff ¶m.sched_priority, &policy); 181ce6e911dSTyler Retzlaff if (ret != 0) 182ce6e911dSTyler Retzlaff goto cleanup; 183ce6e911dSTyler Retzlaff 184ce6e911dSTyler Retzlaff ret = pthread_attr_setschedpolicy(attrp, policy); 185ce6e911dSTyler Retzlaff if (ret != 0) { 186ae67895bSDavid Marchand EAL_LOG(DEBUG, "pthread_attr_setschedpolicy failed"); 187ce6e911dSTyler Retzlaff goto cleanup; 188ce6e911dSTyler Retzlaff } 189ce6e911dSTyler Retzlaff 190ce6e911dSTyler Retzlaff ret = pthread_attr_setschedparam(attrp, ¶m); 191ce6e911dSTyler Retzlaff if (ret != 0) { 192ae67895bSDavid Marchand EAL_LOG(DEBUG, "pthread_attr_setschedparam failed"); 193ce6e911dSTyler Retzlaff goto cleanup; 194ce6e911dSTyler Retzlaff } 195ce6e911dSTyler Retzlaff } 196ce6e911dSTyler Retzlaff 197*64f27886SDavid Marchand #ifdef RTE_EAL_PTHREAD_ATTR_SETAFFINITY_NP 198*64f27886SDavid Marchand ret = pthread_create((pthread_t *)&thread_id->opaque_id, attrp, 199*64f27886SDavid Marchand (void *)(void *)thread_func, args); 200*64f27886SDavid Marchand if (ret != 0) { 201*64f27886SDavid Marchand EAL_LOG(DEBUG, "pthread_create failed"); 202*64f27886SDavid Marchand goto cleanup; 203*64f27886SDavid Marchand } 204*64f27886SDavid Marchand #else /* !RTE_EAL_PTHREAD_ATTR_SETAFFINITY_NP */ 205ce6e911dSTyler Retzlaff ret = pthread_create((pthread_t *)&thread_id->opaque_id, attrp, 206b28c6196STyler Retzlaff thread_start_wrapper, &ctx); 207ce6e911dSTyler Retzlaff if (ret != 0) { 208ae67895bSDavid Marchand EAL_LOG(DEBUG, "pthread_create failed"); 209ce6e911dSTyler Retzlaff goto cleanup; 210ce6e911dSTyler Retzlaff } 211ce6e911dSTyler Retzlaff 212b28c6196STyler Retzlaff pthread_mutex_lock(&ctx.wrapper_mutex); 213b28c6196STyler Retzlaff while (!ctx.wrapper_done) 214b28c6196STyler Retzlaff pthread_cond_wait(&ctx.wrapper_cond, &ctx.wrapper_mutex); 215b28c6196STyler Retzlaff ret = ctx.wrapper_ret; 216b28c6196STyler Retzlaff pthread_mutex_unlock(&ctx.wrapper_mutex); 217ce6e911dSTyler Retzlaff 218b28c6196STyler Retzlaff if (ret != 0) 2191c1abf17SThomas Monjalon rte_thread_join(*thread_id, NULL); 220*64f27886SDavid Marchand #endif /* RTE_EAL_PTHREAD_ATTR_SETAFFINITY_NP */ 221b28c6196STyler Retzlaff 222ce6e911dSTyler Retzlaff cleanup: 223ce6e911dSTyler Retzlaff if (attrp != NULL) 224ce6e911dSTyler Retzlaff pthread_attr_destroy(&attr); 225ce6e911dSTyler Retzlaff 226ce6e911dSTyler Retzlaff return ret; 227ce6e911dSTyler Retzlaff } 228ce6e911dSTyler Retzlaff 229ce6e911dSTyler Retzlaff int 230ce6e911dSTyler Retzlaff rte_thread_join(rte_thread_t thread_id, uint32_t *value_ptr) 231ce6e911dSTyler Retzlaff { 232ce6e911dSTyler Retzlaff int ret = 0; 233ce6e911dSTyler Retzlaff void *res = (void *)(uintptr_t)0; 234ce6e911dSTyler Retzlaff void **pres = NULL; 235ce6e911dSTyler Retzlaff 236ce6e911dSTyler Retzlaff if (value_ptr != NULL) 237ce6e911dSTyler Retzlaff pres = &res; 238ce6e911dSTyler Retzlaff 239ce6e911dSTyler Retzlaff ret = pthread_join((pthread_t)thread_id.opaque_id, pres); 240ce6e911dSTyler Retzlaff if (ret != 0) { 241ae67895bSDavid Marchand EAL_LOG(DEBUG, "pthread_join failed"); 242ce6e911dSTyler Retzlaff return ret; 243ce6e911dSTyler Retzlaff } 244ce6e911dSTyler Retzlaff 245ce6e911dSTyler Retzlaff if (value_ptr != NULL) 246ce6e911dSTyler Retzlaff *value_ptr = (uint32_t)(uintptr_t)res; 247ce6e911dSTyler Retzlaff 248ce6e911dSTyler Retzlaff return 0; 249ce6e911dSTyler Retzlaff } 250ce6e911dSTyler Retzlaff 251ce6e911dSTyler Retzlaff int 252ce6e911dSTyler Retzlaff rte_thread_detach(rte_thread_t thread_id) 253ce6e911dSTyler Retzlaff { 254ce6e911dSTyler Retzlaff return pthread_detach((pthread_t)thread_id.opaque_id); 255ce6e911dSTyler Retzlaff } 256ce6e911dSTyler Retzlaff 257a2e94ca8STyler Retzlaff int 258a2e94ca8STyler Retzlaff rte_thread_equal(rte_thread_t t1, rte_thread_t t2) 259a2e94ca8STyler Retzlaff { 260a2e94ca8STyler Retzlaff return pthread_equal((pthread_t)t1.opaque_id, (pthread_t)t2.opaque_id); 261a2e94ca8STyler Retzlaff } 262a2e94ca8STyler Retzlaff 26356539289STyler Retzlaff rte_thread_t 26456539289STyler Retzlaff rte_thread_self(void) 26556539289STyler Retzlaff { 26656539289STyler Retzlaff RTE_BUILD_BUG_ON(sizeof(pthread_t) > sizeof(uintptr_t)); 26756539289STyler Retzlaff 26856539289STyler Retzlaff rte_thread_t thread_id; 26956539289STyler Retzlaff 27056539289STyler Retzlaff thread_id.opaque_id = (uintptr_t)pthread_self(); 27156539289STyler Retzlaff 27256539289STyler Retzlaff return thread_id; 27356539289STyler Retzlaff } 27456539289STyler Retzlaff 27599a2dd95SBruce Richardson int 276ca04c78bSTyler Retzlaff rte_thread_get_priority(rte_thread_t thread_id, 277ca04c78bSTyler Retzlaff enum rte_thread_priority *priority) 278ca04c78bSTyler Retzlaff { 279ca04c78bSTyler Retzlaff struct sched_param param; 280ca04c78bSTyler Retzlaff int policy; 281ca04c78bSTyler Retzlaff int ret; 282ca04c78bSTyler Retzlaff 283ca04c78bSTyler Retzlaff ret = pthread_getschedparam((pthread_t)thread_id.opaque_id, &policy, 284ca04c78bSTyler Retzlaff ¶m); 285ca04c78bSTyler Retzlaff if (ret != 0) { 286ae67895bSDavid Marchand EAL_LOG(DEBUG, "pthread_getschedparam failed"); 287ca04c78bSTyler Retzlaff goto cleanup; 288ca04c78bSTyler Retzlaff } 289ca04c78bSTyler Retzlaff 290ca04c78bSTyler Retzlaff return thread_map_os_priority_to_eal_priority(policy, 291ca04c78bSTyler Retzlaff param.sched_priority, priority); 292ca04c78bSTyler Retzlaff 293ca04c78bSTyler Retzlaff cleanup: 294ca04c78bSTyler Retzlaff return ret; 295ca04c78bSTyler Retzlaff } 296ca04c78bSTyler Retzlaff 297ca04c78bSTyler Retzlaff int 298ca04c78bSTyler Retzlaff rte_thread_set_priority(rte_thread_t thread_id, 299ca04c78bSTyler Retzlaff enum rte_thread_priority priority) 300ca04c78bSTyler Retzlaff { 301ca04c78bSTyler Retzlaff struct sched_param param; 302ca04c78bSTyler Retzlaff int policy; 303ca04c78bSTyler Retzlaff int ret; 304ca04c78bSTyler Retzlaff 305ca04c78bSTyler Retzlaff /* Realtime priority can cause crashes on non-Windows platforms. */ 306ca04c78bSTyler Retzlaff if (priority == RTE_THREAD_PRIORITY_REALTIME_CRITICAL) 307ca04c78bSTyler Retzlaff return ENOTSUP; 308ca04c78bSTyler Retzlaff 309ca04c78bSTyler Retzlaff ret = thread_map_priority_to_os_value(priority, ¶m.sched_priority, 310ca04c78bSTyler Retzlaff &policy); 311ca04c78bSTyler Retzlaff if (ret != 0) 312ca04c78bSTyler Retzlaff return ret; 313ca04c78bSTyler Retzlaff 314ca04c78bSTyler Retzlaff return pthread_setschedparam((pthread_t)thread_id.opaque_id, policy, 315ca04c78bSTyler Retzlaff ¶m); 316ca04c78bSTyler Retzlaff } 317ca04c78bSTyler Retzlaff 318ca04c78bSTyler Retzlaff int 31999a2dd95SBruce Richardson rte_thread_key_create(rte_thread_key *key, void (*destructor)(void *)) 32099a2dd95SBruce Richardson { 32199a2dd95SBruce Richardson int err; 32299a2dd95SBruce Richardson 32399a2dd95SBruce Richardson *key = malloc(sizeof(**key)); 32499a2dd95SBruce Richardson if ((*key) == NULL) { 325ae67895bSDavid Marchand EAL_LOG(DEBUG, "Cannot allocate TLS key."); 32699a2dd95SBruce Richardson rte_errno = ENOMEM; 32799a2dd95SBruce Richardson return -1; 32899a2dd95SBruce Richardson } 32999a2dd95SBruce Richardson err = pthread_key_create(&((*key)->thread_index), destructor); 33099a2dd95SBruce Richardson if (err) { 331ae67895bSDavid Marchand EAL_LOG(DEBUG, "pthread_key_create failed: %s", 33299a2dd95SBruce Richardson strerror(err)); 33399a2dd95SBruce Richardson free(*key); 33499a2dd95SBruce Richardson rte_errno = ENOEXEC; 33599a2dd95SBruce Richardson return -1; 33699a2dd95SBruce Richardson } 33799a2dd95SBruce Richardson return 0; 33899a2dd95SBruce Richardson } 33999a2dd95SBruce Richardson 34099a2dd95SBruce Richardson int 34199a2dd95SBruce Richardson rte_thread_key_delete(rte_thread_key key) 34299a2dd95SBruce Richardson { 34399a2dd95SBruce Richardson int err; 34499a2dd95SBruce Richardson 34599a2dd95SBruce Richardson if (!key) { 346ae67895bSDavid Marchand EAL_LOG(DEBUG, "Invalid TLS key."); 34799a2dd95SBruce Richardson rte_errno = EINVAL; 34899a2dd95SBruce Richardson return -1; 34999a2dd95SBruce Richardson } 35099a2dd95SBruce Richardson err = pthread_key_delete(key->thread_index); 35199a2dd95SBruce Richardson if (err) { 352ae67895bSDavid Marchand EAL_LOG(DEBUG, "pthread_key_delete failed: %s", 35399a2dd95SBruce Richardson strerror(err)); 35499a2dd95SBruce Richardson free(key); 35599a2dd95SBruce Richardson rte_errno = ENOEXEC; 35699a2dd95SBruce Richardson return -1; 35799a2dd95SBruce Richardson } 35899a2dd95SBruce Richardson free(key); 35999a2dd95SBruce Richardson return 0; 36099a2dd95SBruce Richardson } 36199a2dd95SBruce Richardson 36299a2dd95SBruce Richardson int 36399a2dd95SBruce Richardson rte_thread_value_set(rte_thread_key key, const void *value) 36499a2dd95SBruce Richardson { 36599a2dd95SBruce Richardson int err; 36699a2dd95SBruce Richardson 36799a2dd95SBruce Richardson if (!key) { 368ae67895bSDavid Marchand EAL_LOG(DEBUG, "Invalid TLS key."); 36999a2dd95SBruce Richardson rte_errno = EINVAL; 37099a2dd95SBruce Richardson return -1; 37199a2dd95SBruce Richardson } 37299a2dd95SBruce Richardson err = pthread_setspecific(key->thread_index, value); 37399a2dd95SBruce Richardson if (err) { 374ae67895bSDavid Marchand EAL_LOG(DEBUG, "pthread_setspecific failed: %s", 37599a2dd95SBruce Richardson strerror(err)); 37699a2dd95SBruce Richardson rte_errno = ENOEXEC; 37799a2dd95SBruce Richardson return -1; 37899a2dd95SBruce Richardson } 37999a2dd95SBruce Richardson return 0; 38099a2dd95SBruce Richardson } 38199a2dd95SBruce Richardson 38299a2dd95SBruce Richardson void * 38399a2dd95SBruce Richardson rte_thread_value_get(rte_thread_key key) 38499a2dd95SBruce Richardson { 38599a2dd95SBruce Richardson if (!key) { 386ae67895bSDavid Marchand EAL_LOG(DEBUG, "Invalid TLS key."); 38799a2dd95SBruce Richardson rte_errno = EINVAL; 38899a2dd95SBruce Richardson return NULL; 38999a2dd95SBruce Richardson } 39099a2dd95SBruce Richardson return pthread_getspecific(key->thread_index); 39199a2dd95SBruce Richardson } 392b70a9b78STyler Retzlaff 393b70a9b78STyler Retzlaff int 394b70a9b78STyler Retzlaff rte_thread_set_affinity_by_id(rte_thread_t thread_id, 395b70a9b78STyler Retzlaff const rte_cpuset_t *cpuset) 396b70a9b78STyler Retzlaff { 397b70a9b78STyler Retzlaff return pthread_setaffinity_np((pthread_t)thread_id.opaque_id, 398b70a9b78STyler Retzlaff sizeof(*cpuset), cpuset); 399b70a9b78STyler Retzlaff } 400b70a9b78STyler Retzlaff 401b70a9b78STyler Retzlaff int 402b70a9b78STyler Retzlaff rte_thread_get_affinity_by_id(rte_thread_t thread_id, 403b70a9b78STyler Retzlaff rte_cpuset_t *cpuset) 404b70a9b78STyler Retzlaff { 405b70a9b78STyler Retzlaff return pthread_getaffinity_np((pthread_t)thread_id.opaque_id, 406b70a9b78STyler Retzlaff sizeof(*cpuset), cpuset); 407b70a9b78STyler Retzlaff } 408