199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 299a2dd95SBruce Richardson * Copyright 2021 Mellanox Technologies, Ltd 3b70a9b78STyler Retzlaff * Copyright (C) 2022 Microsoft Corporation 499a2dd95SBruce Richardson */ 599a2dd95SBruce Richardson 672b452c5SDmitry Kozlyuk #include <errno.h> 772b452c5SDmitry Kozlyuk 899a2dd95SBruce Richardson #include <rte_common.h> 999a2dd95SBruce Richardson #include <rte_errno.h> 1099a2dd95SBruce Richardson #include <rte_thread.h> 11b70a9b78STyler Retzlaff 12b70a9b78STyler Retzlaff #include "eal_windows.h" 1399a2dd95SBruce Richardson 1499a2dd95SBruce Richardson struct eal_tls_key { 1599a2dd95SBruce Richardson DWORD thread_index; 1699a2dd95SBruce Richardson }; 1799a2dd95SBruce Richardson 18ce6e911dSTyler Retzlaff struct thread_routine_ctx { 19ce6e911dSTyler Retzlaff rte_thread_func thread_func; 20ce6e911dSTyler Retzlaff void *routine_args; 21ce6e911dSTyler Retzlaff }; 22ce6e911dSTyler Retzlaff 23b70a9b78STyler Retzlaff /* Translates the most common error codes related to threads */ 24b70a9b78STyler Retzlaff static int 25b70a9b78STyler Retzlaff thread_translate_win32_error(DWORD error) 26b70a9b78STyler Retzlaff { 27b70a9b78STyler Retzlaff switch (error) { 28b70a9b78STyler Retzlaff case ERROR_SUCCESS: 29b70a9b78STyler Retzlaff return 0; 30b70a9b78STyler Retzlaff 31b70a9b78STyler Retzlaff case ERROR_INVALID_PARAMETER: 32b70a9b78STyler Retzlaff return EINVAL; 33b70a9b78STyler Retzlaff 34b70a9b78STyler Retzlaff case ERROR_INVALID_HANDLE: 35b70a9b78STyler Retzlaff return EFAULT; 36b70a9b78STyler Retzlaff 37b70a9b78STyler Retzlaff case ERROR_NOT_ENOUGH_MEMORY: 38b70a9b78STyler Retzlaff /* FALLTHROUGH */ 39b70a9b78STyler Retzlaff case ERROR_NO_SYSTEM_RESOURCES: 40b70a9b78STyler Retzlaff return ENOMEM; 41b70a9b78STyler Retzlaff 42b70a9b78STyler Retzlaff case ERROR_PRIVILEGE_NOT_HELD: 43b70a9b78STyler Retzlaff /* FALLTHROUGH */ 44b70a9b78STyler Retzlaff case ERROR_ACCESS_DENIED: 45b70a9b78STyler Retzlaff return EACCES; 46b70a9b78STyler Retzlaff 47b70a9b78STyler Retzlaff case ERROR_ALREADY_EXISTS: 48b70a9b78STyler Retzlaff return EEXIST; 49b70a9b78STyler Retzlaff 50b70a9b78STyler Retzlaff case ERROR_POSSIBLE_DEADLOCK: 51b70a9b78STyler Retzlaff return EDEADLK; 52b70a9b78STyler Retzlaff 53b70a9b78STyler Retzlaff case ERROR_INVALID_FUNCTION: 54b70a9b78STyler Retzlaff /* FALLTHROUGH */ 55b70a9b78STyler Retzlaff case ERROR_CALL_NOT_IMPLEMENTED: 56b70a9b78STyler Retzlaff return ENOSYS; 57b70a9b78STyler Retzlaff } 58b70a9b78STyler Retzlaff 59b70a9b78STyler Retzlaff return EINVAL; 60b70a9b78STyler Retzlaff } 61b70a9b78STyler Retzlaff 62b70a9b78STyler Retzlaff static int 63b70a9b78STyler Retzlaff thread_log_last_error(const char *message) 64b70a9b78STyler Retzlaff { 65b70a9b78STyler Retzlaff DWORD error = GetLastError(); 66b70a9b78STyler Retzlaff RTE_LOG(DEBUG, EAL, "GetLastError()=%lu: %s\n", error, message); 67b70a9b78STyler Retzlaff 68b70a9b78STyler Retzlaff return thread_translate_win32_error(error); 69b70a9b78STyler Retzlaff } 70b70a9b78STyler Retzlaff 71ca04c78bSTyler Retzlaff static int 72ca04c78bSTyler Retzlaff thread_map_priority_to_os_value(enum rte_thread_priority eal_pri, int *os_pri, 73ca04c78bSTyler Retzlaff DWORD *pri_class) 74ca04c78bSTyler Retzlaff { 75ca04c78bSTyler Retzlaff /* Clear the output parameters. */ 76ca04c78bSTyler Retzlaff *os_pri = -1; 77ca04c78bSTyler Retzlaff *pri_class = -1; 78ca04c78bSTyler Retzlaff 79ca04c78bSTyler Retzlaff switch (eal_pri) { 80ca04c78bSTyler Retzlaff case RTE_THREAD_PRIORITY_NORMAL: 81ca04c78bSTyler Retzlaff *pri_class = NORMAL_PRIORITY_CLASS; 82ca04c78bSTyler Retzlaff *os_pri = THREAD_PRIORITY_NORMAL; 83ca04c78bSTyler Retzlaff break; 84ca04c78bSTyler Retzlaff case RTE_THREAD_PRIORITY_REALTIME_CRITICAL: 85ca04c78bSTyler Retzlaff *pri_class = REALTIME_PRIORITY_CLASS; 86ca04c78bSTyler Retzlaff *os_pri = THREAD_PRIORITY_TIME_CRITICAL; 87ca04c78bSTyler Retzlaff break; 88ca04c78bSTyler Retzlaff default: 89ca04c78bSTyler Retzlaff RTE_LOG(DEBUG, EAL, "The requested priority value is invalid.\n"); 90ca04c78bSTyler Retzlaff return EINVAL; 91ca04c78bSTyler Retzlaff } 92ca04c78bSTyler Retzlaff 93ca04c78bSTyler Retzlaff return 0; 94ca04c78bSTyler Retzlaff } 95ca04c78bSTyler Retzlaff 96ca04c78bSTyler Retzlaff static int 97ca04c78bSTyler Retzlaff thread_map_os_priority_to_eal_value(int os_pri, DWORD pri_class, 98ca04c78bSTyler Retzlaff enum rte_thread_priority *eal_pri) 99ca04c78bSTyler Retzlaff { 100ca04c78bSTyler Retzlaff switch (pri_class) { 101ca04c78bSTyler Retzlaff case NORMAL_PRIORITY_CLASS: 102ca04c78bSTyler Retzlaff if (os_pri == THREAD_PRIORITY_NORMAL) { 103ca04c78bSTyler Retzlaff *eal_pri = RTE_THREAD_PRIORITY_NORMAL; 104ca04c78bSTyler Retzlaff return 0; 105ca04c78bSTyler Retzlaff } 106ca04c78bSTyler Retzlaff break; 107ca04c78bSTyler Retzlaff case HIGH_PRIORITY_CLASS: 108ca04c78bSTyler Retzlaff RTE_LOG(WARNING, EAL, "The OS priority class is high not real-time.\n"); 109ca04c78bSTyler Retzlaff /* FALLTHROUGH */ 110ca04c78bSTyler Retzlaff case REALTIME_PRIORITY_CLASS: 111ca04c78bSTyler Retzlaff if (os_pri == THREAD_PRIORITY_TIME_CRITICAL) { 112ca04c78bSTyler Retzlaff *eal_pri = RTE_THREAD_PRIORITY_REALTIME_CRITICAL; 113ca04c78bSTyler Retzlaff return 0; 114ca04c78bSTyler Retzlaff } 115ca04c78bSTyler Retzlaff break; 116ca04c78bSTyler Retzlaff default: 117ca04c78bSTyler Retzlaff RTE_LOG(DEBUG, EAL, "The OS priority value does not map to an EAL-defined priority.\n"); 118ca04c78bSTyler Retzlaff return EINVAL; 119ca04c78bSTyler Retzlaff } 120ca04c78bSTyler Retzlaff 121ca04c78bSTyler Retzlaff return 0; 122ca04c78bSTyler Retzlaff } 123ca04c78bSTyler Retzlaff 124ce6e911dSTyler Retzlaff static int 125ce6e911dSTyler Retzlaff convert_cpuset_to_affinity(const rte_cpuset_t *cpuset, 126ce6e911dSTyler Retzlaff PGROUP_AFFINITY affinity) 127ce6e911dSTyler Retzlaff { 128ce6e911dSTyler Retzlaff int ret = 0; 129ce6e911dSTyler Retzlaff PGROUP_AFFINITY cpu_affinity = NULL; 130ce6e911dSTyler Retzlaff unsigned int cpu_idx; 131ce6e911dSTyler Retzlaff 132ce6e911dSTyler Retzlaff memset(affinity, 0, sizeof(GROUP_AFFINITY)); 133ce6e911dSTyler Retzlaff affinity->Group = (USHORT)-1; 134ce6e911dSTyler Retzlaff 135ce6e911dSTyler Retzlaff /* Check that all cpus of the set belong to the same processor group and 136ce6e911dSTyler Retzlaff * accumulate thread affinity to be applied. 137ce6e911dSTyler Retzlaff */ 138ce6e911dSTyler Retzlaff for (cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) { 139ce6e911dSTyler Retzlaff if (!CPU_ISSET(cpu_idx, cpuset)) 140ce6e911dSTyler Retzlaff continue; 141ce6e911dSTyler Retzlaff 142ce6e911dSTyler Retzlaff cpu_affinity = eal_get_cpu_affinity(cpu_idx); 143ce6e911dSTyler Retzlaff 144ce6e911dSTyler Retzlaff if (affinity->Group == (USHORT)-1) { 145ce6e911dSTyler Retzlaff affinity->Group = cpu_affinity->Group; 146ce6e911dSTyler Retzlaff } else if (affinity->Group != cpu_affinity->Group) { 147ce6e911dSTyler Retzlaff RTE_LOG(DEBUG, EAL, "All processors must belong to the same processor group\n"); 148ce6e911dSTyler Retzlaff ret = ENOTSUP; 149ce6e911dSTyler Retzlaff goto cleanup; 150ce6e911dSTyler Retzlaff } 151ce6e911dSTyler Retzlaff 152ce6e911dSTyler Retzlaff affinity->Mask |= cpu_affinity->Mask; 153ce6e911dSTyler Retzlaff } 154ce6e911dSTyler Retzlaff 155ce6e911dSTyler Retzlaff if (affinity->Mask == 0) { 156ce6e911dSTyler Retzlaff ret = EINVAL; 157ce6e911dSTyler Retzlaff goto cleanup; 158ce6e911dSTyler Retzlaff } 159ce6e911dSTyler Retzlaff 160ce6e911dSTyler Retzlaff cleanup: 161ce6e911dSTyler Retzlaff return ret; 162ce6e911dSTyler Retzlaff } 163ce6e911dSTyler Retzlaff 164ce6e911dSTyler Retzlaff static DWORD 165ce6e911dSTyler Retzlaff thread_func_wrapper(void *arg) 166ce6e911dSTyler Retzlaff { 167ce6e911dSTyler Retzlaff struct thread_routine_ctx ctx = *(struct thread_routine_ctx *)arg; 168ce6e911dSTyler Retzlaff 169ce6e911dSTyler Retzlaff free(arg); 170ce6e911dSTyler Retzlaff 171ce6e911dSTyler Retzlaff return (DWORD)ctx.thread_func(ctx.routine_args); 172ce6e911dSTyler Retzlaff } 173ce6e911dSTyler Retzlaff 174ce6e911dSTyler Retzlaff int 175ce6e911dSTyler Retzlaff rte_thread_create(rte_thread_t *thread_id, 176ce6e911dSTyler Retzlaff const rte_thread_attr_t *thread_attr, 177ce6e911dSTyler Retzlaff rte_thread_func thread_func, void *args) 178ce6e911dSTyler Retzlaff { 179ce6e911dSTyler Retzlaff int ret = 0; 180ce6e911dSTyler Retzlaff DWORD tid; 181ce6e911dSTyler Retzlaff HANDLE thread_handle = NULL; 182ce6e911dSTyler Retzlaff GROUP_AFFINITY thread_affinity; 183ce6e911dSTyler Retzlaff struct thread_routine_ctx *ctx; 184ce6e911dSTyler Retzlaff 185ce6e911dSTyler Retzlaff ctx = calloc(1, sizeof(*ctx)); 186ce6e911dSTyler Retzlaff if (ctx == NULL) { 187ce6e911dSTyler Retzlaff RTE_LOG(DEBUG, EAL, "Insufficient memory for thread context allocations\n"); 188ce6e911dSTyler Retzlaff ret = ENOMEM; 189ce6e911dSTyler Retzlaff goto cleanup; 190ce6e911dSTyler Retzlaff } 191ce6e911dSTyler Retzlaff ctx->routine_args = args; 192ce6e911dSTyler Retzlaff ctx->thread_func = thread_func; 193ce6e911dSTyler Retzlaff 194ce6e911dSTyler Retzlaff thread_handle = CreateThread(NULL, 0, thread_func_wrapper, ctx, 195ce6e911dSTyler Retzlaff CREATE_SUSPENDED, &tid); 196ce6e911dSTyler Retzlaff if (thread_handle == NULL) { 197ce6e911dSTyler Retzlaff ret = thread_log_last_error("CreateThread()"); 198ce6e911dSTyler Retzlaff goto cleanup; 199ce6e911dSTyler Retzlaff } 200ce6e911dSTyler Retzlaff thread_id->opaque_id = tid; 201ce6e911dSTyler Retzlaff 202ce6e911dSTyler Retzlaff if (thread_attr != NULL) { 203ce6e911dSTyler Retzlaff if (CPU_COUNT(&thread_attr->cpuset) > 0) { 204ce6e911dSTyler Retzlaff ret = convert_cpuset_to_affinity( 205ce6e911dSTyler Retzlaff &thread_attr->cpuset, 206ce6e911dSTyler Retzlaff &thread_affinity 207ce6e911dSTyler Retzlaff ); 208ce6e911dSTyler Retzlaff if (ret != 0) { 209ce6e911dSTyler Retzlaff RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n"); 210ce6e911dSTyler Retzlaff goto cleanup; 211ce6e911dSTyler Retzlaff } 212ce6e911dSTyler Retzlaff 213ce6e911dSTyler Retzlaff if (!SetThreadGroupAffinity(thread_handle, 214ce6e911dSTyler Retzlaff &thread_affinity, NULL)) { 215ce6e911dSTyler Retzlaff ret = thread_log_last_error("SetThreadGroupAffinity()"); 216ce6e911dSTyler Retzlaff goto cleanup; 217ce6e911dSTyler Retzlaff } 218ce6e911dSTyler Retzlaff } 219ce6e911dSTyler Retzlaff ret = rte_thread_set_priority(*thread_id, 220ce6e911dSTyler Retzlaff thread_attr->priority); 221ce6e911dSTyler Retzlaff if (ret != 0) { 222ce6e911dSTyler Retzlaff RTE_LOG(DEBUG, EAL, "Unable to set thread priority\n"); 223ce6e911dSTyler Retzlaff goto cleanup; 224ce6e911dSTyler Retzlaff } 225ce6e911dSTyler Retzlaff } 226ce6e911dSTyler Retzlaff 227ce6e911dSTyler Retzlaff if (ResumeThread(thread_handle) == (DWORD)-1) { 228ce6e911dSTyler Retzlaff ret = thread_log_last_error("ResumeThread()"); 229ce6e911dSTyler Retzlaff goto cleanup; 230ce6e911dSTyler Retzlaff } 231ce6e911dSTyler Retzlaff 232ce6e911dSTyler Retzlaff ctx = NULL; 233ce6e911dSTyler Retzlaff cleanup: 234ce6e911dSTyler Retzlaff free(ctx); 235ce6e911dSTyler Retzlaff if (thread_handle != NULL) { 236ce6e911dSTyler Retzlaff CloseHandle(thread_handle); 237ce6e911dSTyler Retzlaff thread_handle = NULL; 238ce6e911dSTyler Retzlaff } 239ce6e911dSTyler Retzlaff 240ce6e911dSTyler Retzlaff return ret; 241ce6e911dSTyler Retzlaff } 242ce6e911dSTyler Retzlaff 243ce6e911dSTyler Retzlaff int 244ce6e911dSTyler Retzlaff rte_thread_join(rte_thread_t thread_id, uint32_t *value_ptr) 245ce6e911dSTyler Retzlaff { 246ce6e911dSTyler Retzlaff HANDLE thread_handle; 247ce6e911dSTyler Retzlaff DWORD result; 248ce6e911dSTyler Retzlaff DWORD exit_code = 0; 249ce6e911dSTyler Retzlaff BOOL err; 250ce6e911dSTyler Retzlaff int ret = 0; 251ce6e911dSTyler Retzlaff 252ce6e911dSTyler Retzlaff thread_handle = OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION, 253ce6e911dSTyler Retzlaff FALSE, thread_id.opaque_id); 254ce6e911dSTyler Retzlaff if (thread_handle == NULL) { 255ce6e911dSTyler Retzlaff ret = thread_log_last_error("OpenThread()"); 256ce6e911dSTyler Retzlaff goto cleanup; 257ce6e911dSTyler Retzlaff } 258ce6e911dSTyler Retzlaff 259ce6e911dSTyler Retzlaff result = WaitForSingleObject(thread_handle, INFINITE); 260ce6e911dSTyler Retzlaff if (result != WAIT_OBJECT_0) { 261ce6e911dSTyler Retzlaff ret = thread_log_last_error("WaitForSingleObject()"); 262ce6e911dSTyler Retzlaff goto cleanup; 263ce6e911dSTyler Retzlaff } 264ce6e911dSTyler Retzlaff 265ce6e911dSTyler Retzlaff if (value_ptr != NULL) { 266ce6e911dSTyler Retzlaff err = GetExitCodeThread(thread_handle, &exit_code); 267ce6e911dSTyler Retzlaff if (err == 0) { 268ce6e911dSTyler Retzlaff ret = thread_log_last_error("GetExitCodeThread()"); 269ce6e911dSTyler Retzlaff goto cleanup; 270ce6e911dSTyler Retzlaff } 271ce6e911dSTyler Retzlaff *value_ptr = exit_code; 272ce6e911dSTyler Retzlaff } 273ce6e911dSTyler Retzlaff 274ce6e911dSTyler Retzlaff cleanup: 275ce6e911dSTyler Retzlaff if (thread_handle != NULL) { 276ce6e911dSTyler Retzlaff CloseHandle(thread_handle); 277ce6e911dSTyler Retzlaff thread_handle = NULL; 278ce6e911dSTyler Retzlaff } 279ce6e911dSTyler Retzlaff 280ce6e911dSTyler Retzlaff return ret; 281ce6e911dSTyler Retzlaff } 282ce6e911dSTyler Retzlaff 283ce6e911dSTyler Retzlaff int 284ce6e911dSTyler Retzlaff rte_thread_detach(rte_thread_t thread_id) 285ce6e911dSTyler Retzlaff { 286ce6e911dSTyler Retzlaff /* No resources that need to be released. */ 287ce6e911dSTyler Retzlaff RTE_SET_USED(thread_id); 288ce6e911dSTyler Retzlaff 289ce6e911dSTyler Retzlaff return 0; 290ce6e911dSTyler Retzlaff } 291ce6e911dSTyler Retzlaff 292*a2e94ca8STyler Retzlaff int 293*a2e94ca8STyler Retzlaff rte_thread_equal(rte_thread_t t1, rte_thread_t t2) 294*a2e94ca8STyler Retzlaff { 295*a2e94ca8STyler Retzlaff return t1.opaque_id == t2.opaque_id; 296*a2e94ca8STyler Retzlaff } 297*a2e94ca8STyler Retzlaff 29856539289STyler Retzlaff rte_thread_t 29956539289STyler Retzlaff rte_thread_self(void) 30056539289STyler Retzlaff { 30156539289STyler Retzlaff rte_thread_t thread_id; 30256539289STyler Retzlaff 30356539289STyler Retzlaff thread_id.opaque_id = GetCurrentThreadId(); 30456539289STyler Retzlaff 30556539289STyler Retzlaff return thread_id; 30656539289STyler Retzlaff } 30756539289STyler Retzlaff 30899a2dd95SBruce Richardson int 309ca04c78bSTyler Retzlaff rte_thread_get_priority(rte_thread_t thread_id, 310ca04c78bSTyler Retzlaff enum rte_thread_priority *priority) 311ca04c78bSTyler Retzlaff { 312ca04c78bSTyler Retzlaff HANDLE thread_handle = NULL; 313ca04c78bSTyler Retzlaff DWORD pri_class; 314ca04c78bSTyler Retzlaff int os_pri; 315ca04c78bSTyler Retzlaff int ret; 316ca04c78bSTyler Retzlaff 317ca04c78bSTyler Retzlaff pri_class = GetPriorityClass(GetCurrentProcess()); 318ca04c78bSTyler Retzlaff if (pri_class == 0) { 319ca04c78bSTyler Retzlaff ret = thread_log_last_error("GetPriorityClass()"); 320ca04c78bSTyler Retzlaff goto cleanup; 321ca04c78bSTyler Retzlaff } 322ca04c78bSTyler Retzlaff 323ca04c78bSTyler Retzlaff thread_handle = OpenThread(THREAD_SET_INFORMATION | 324ca04c78bSTyler Retzlaff THREAD_QUERY_INFORMATION, FALSE, thread_id.opaque_id); 325ca04c78bSTyler Retzlaff if (thread_handle == NULL) { 326ca04c78bSTyler Retzlaff ret = thread_log_last_error("OpenThread()"); 327ca04c78bSTyler Retzlaff goto cleanup; 328ca04c78bSTyler Retzlaff } 329ca04c78bSTyler Retzlaff 330ca04c78bSTyler Retzlaff os_pri = GetThreadPriority(thread_handle); 331ca04c78bSTyler Retzlaff if (os_pri == THREAD_PRIORITY_ERROR_RETURN) { 332ca04c78bSTyler Retzlaff ret = thread_log_last_error("GetThreadPriority()"); 333ca04c78bSTyler Retzlaff goto cleanup; 334ca04c78bSTyler Retzlaff } 335ca04c78bSTyler Retzlaff 336ca04c78bSTyler Retzlaff ret = thread_map_os_priority_to_eal_value(os_pri, pri_class, priority); 337ca04c78bSTyler Retzlaff if (ret != 0) 338ca04c78bSTyler Retzlaff goto cleanup; 339ca04c78bSTyler Retzlaff 340ca04c78bSTyler Retzlaff cleanup: 341ca04c78bSTyler Retzlaff if (thread_handle != NULL) 342ca04c78bSTyler Retzlaff CloseHandle(thread_handle); 343ca04c78bSTyler Retzlaff 344ca04c78bSTyler Retzlaff return ret; 345ca04c78bSTyler Retzlaff } 346ca04c78bSTyler Retzlaff 347ca04c78bSTyler Retzlaff int 348ca04c78bSTyler Retzlaff rte_thread_set_priority(rte_thread_t thread_id, 349ca04c78bSTyler Retzlaff enum rte_thread_priority priority) 350ca04c78bSTyler Retzlaff { 351ca04c78bSTyler Retzlaff HANDLE thread_handle; 352ca04c78bSTyler Retzlaff DWORD priority_class; 353ca04c78bSTyler Retzlaff int os_priority; 354ca04c78bSTyler Retzlaff int ret = 0; 355ca04c78bSTyler Retzlaff 356ca04c78bSTyler Retzlaff thread_handle = OpenThread(THREAD_SET_INFORMATION | 357ca04c78bSTyler Retzlaff THREAD_QUERY_INFORMATION, FALSE, thread_id.opaque_id); 358ca04c78bSTyler Retzlaff if (thread_handle == NULL) { 359ca04c78bSTyler Retzlaff ret = thread_log_last_error("OpenThread()"); 360ca04c78bSTyler Retzlaff goto cleanup; 361ca04c78bSTyler Retzlaff } 362ca04c78bSTyler Retzlaff 363ca04c78bSTyler Retzlaff ret = thread_map_priority_to_os_value(priority, &os_priority, 364ca04c78bSTyler Retzlaff &priority_class); 365ca04c78bSTyler Retzlaff if (ret != 0) 366ca04c78bSTyler Retzlaff goto cleanup; 367ca04c78bSTyler Retzlaff 368ca04c78bSTyler Retzlaff if (!SetPriorityClass(GetCurrentProcess(), priority_class)) { 369ca04c78bSTyler Retzlaff ret = thread_log_last_error("SetPriorityClass()"); 370ca04c78bSTyler Retzlaff goto cleanup; 371ca04c78bSTyler Retzlaff } 372ca04c78bSTyler Retzlaff 373ca04c78bSTyler Retzlaff if (!SetThreadPriority(thread_handle, os_priority)) { 374ca04c78bSTyler Retzlaff ret = thread_log_last_error("SetThreadPriority()"); 375ca04c78bSTyler Retzlaff goto cleanup; 376ca04c78bSTyler Retzlaff } 377ca04c78bSTyler Retzlaff 378ca04c78bSTyler Retzlaff cleanup: 379ca04c78bSTyler Retzlaff if (thread_handle != NULL) 380ca04c78bSTyler Retzlaff CloseHandle(thread_handle); 381ca04c78bSTyler Retzlaff 382ca04c78bSTyler Retzlaff return ret; 383ca04c78bSTyler Retzlaff } 384ca04c78bSTyler Retzlaff 385ca04c78bSTyler Retzlaff int 38699a2dd95SBruce Richardson rte_thread_key_create(rte_thread_key *key, 38799a2dd95SBruce Richardson __rte_unused void (*destructor)(void *)) 38899a2dd95SBruce Richardson { 38999a2dd95SBruce Richardson *key = malloc(sizeof(**key)); 39099a2dd95SBruce Richardson if ((*key) == NULL) { 39199a2dd95SBruce Richardson RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n"); 39299a2dd95SBruce Richardson rte_errno = ENOMEM; 39399a2dd95SBruce Richardson return -1; 39499a2dd95SBruce Richardson } 39599a2dd95SBruce Richardson (*key)->thread_index = TlsAlloc(); 39699a2dd95SBruce Richardson if ((*key)->thread_index == TLS_OUT_OF_INDEXES) { 39799a2dd95SBruce Richardson RTE_LOG_WIN32_ERR("TlsAlloc()"); 39899a2dd95SBruce Richardson free(*key); 39999a2dd95SBruce Richardson rte_errno = ENOEXEC; 40099a2dd95SBruce Richardson return -1; 40199a2dd95SBruce Richardson } 40299a2dd95SBruce Richardson return 0; 40399a2dd95SBruce Richardson } 40499a2dd95SBruce Richardson 40599a2dd95SBruce Richardson int 40699a2dd95SBruce Richardson rte_thread_key_delete(rte_thread_key key) 40799a2dd95SBruce Richardson { 40899a2dd95SBruce Richardson if (!key) { 40999a2dd95SBruce Richardson RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n"); 41099a2dd95SBruce Richardson rte_errno = EINVAL; 41199a2dd95SBruce Richardson return -1; 41299a2dd95SBruce Richardson } 41399a2dd95SBruce Richardson if (!TlsFree(key->thread_index)) { 41499a2dd95SBruce Richardson RTE_LOG_WIN32_ERR("TlsFree()"); 41599a2dd95SBruce Richardson free(key); 41699a2dd95SBruce Richardson rte_errno = ENOEXEC; 41799a2dd95SBruce Richardson return -1; 41899a2dd95SBruce Richardson } 41999a2dd95SBruce Richardson free(key); 42099a2dd95SBruce Richardson return 0; 42199a2dd95SBruce Richardson } 42299a2dd95SBruce Richardson 42399a2dd95SBruce Richardson int 42499a2dd95SBruce Richardson rte_thread_value_set(rte_thread_key key, const void *value) 42599a2dd95SBruce Richardson { 42699a2dd95SBruce Richardson char *p; 42799a2dd95SBruce Richardson 42899a2dd95SBruce Richardson if (!key) { 42999a2dd95SBruce Richardson RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n"); 43099a2dd95SBruce Richardson rte_errno = EINVAL; 43199a2dd95SBruce Richardson return -1; 43299a2dd95SBruce Richardson } 43399a2dd95SBruce Richardson /* discard const qualifier */ 43499a2dd95SBruce Richardson p = (char *) (uintptr_t) value; 43599a2dd95SBruce Richardson if (!TlsSetValue(key->thread_index, p)) { 43699a2dd95SBruce Richardson RTE_LOG_WIN32_ERR("TlsSetValue()"); 43799a2dd95SBruce Richardson rte_errno = ENOEXEC; 43899a2dd95SBruce Richardson return -1; 43999a2dd95SBruce Richardson } 44099a2dd95SBruce Richardson return 0; 44199a2dd95SBruce Richardson } 44299a2dd95SBruce Richardson 44399a2dd95SBruce Richardson void * 44499a2dd95SBruce Richardson rte_thread_value_get(rte_thread_key key) 44599a2dd95SBruce Richardson { 44699a2dd95SBruce Richardson void *output; 44799a2dd95SBruce Richardson 44899a2dd95SBruce Richardson if (!key) { 44999a2dd95SBruce Richardson RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n"); 45099a2dd95SBruce Richardson rte_errno = EINVAL; 45199a2dd95SBruce Richardson return NULL; 45299a2dd95SBruce Richardson } 45399a2dd95SBruce Richardson output = TlsGetValue(key->thread_index); 45499a2dd95SBruce Richardson if (GetLastError() != ERROR_SUCCESS) { 45599a2dd95SBruce Richardson RTE_LOG_WIN32_ERR("TlsGetValue()"); 45699a2dd95SBruce Richardson rte_errno = ENOEXEC; 45799a2dd95SBruce Richardson return NULL; 45899a2dd95SBruce Richardson } 45999a2dd95SBruce Richardson return output; 46099a2dd95SBruce Richardson } 461b70a9b78STyler Retzlaff 462b70a9b78STyler Retzlaff int 463b70a9b78STyler Retzlaff rte_thread_set_affinity_by_id(rte_thread_t thread_id, 464b70a9b78STyler Retzlaff const rte_cpuset_t *cpuset) 465b70a9b78STyler Retzlaff { 466b70a9b78STyler Retzlaff int ret = 0; 467b70a9b78STyler Retzlaff GROUP_AFFINITY thread_affinity; 468b70a9b78STyler Retzlaff HANDLE thread_handle = NULL; 469b70a9b78STyler Retzlaff 470b70a9b78STyler Retzlaff if (cpuset == NULL) { 471b70a9b78STyler Retzlaff ret = EINVAL; 472b70a9b78STyler Retzlaff goto cleanup; 473b70a9b78STyler Retzlaff } 474b70a9b78STyler Retzlaff 475b70a9b78STyler Retzlaff ret = convert_cpuset_to_affinity(cpuset, &thread_affinity); 476b70a9b78STyler Retzlaff if (ret != 0) { 477b70a9b78STyler Retzlaff RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n"); 478b70a9b78STyler Retzlaff goto cleanup; 479b70a9b78STyler Retzlaff } 480b70a9b78STyler Retzlaff 481b70a9b78STyler Retzlaff thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, 482b70a9b78STyler Retzlaff thread_id.opaque_id); 483b70a9b78STyler Retzlaff if (thread_handle == NULL) { 484b70a9b78STyler Retzlaff ret = thread_log_last_error("OpenThread()"); 485b70a9b78STyler Retzlaff goto cleanup; 486b70a9b78STyler Retzlaff } 487b70a9b78STyler Retzlaff 488b70a9b78STyler Retzlaff if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) { 489b70a9b78STyler Retzlaff ret = thread_log_last_error("SetThreadGroupAffinity()"); 490b70a9b78STyler Retzlaff goto cleanup; 491b70a9b78STyler Retzlaff } 492b70a9b78STyler Retzlaff 493b70a9b78STyler Retzlaff cleanup: 494b70a9b78STyler Retzlaff if (thread_handle != NULL) { 495b70a9b78STyler Retzlaff CloseHandle(thread_handle); 496b70a9b78STyler Retzlaff thread_handle = NULL; 497b70a9b78STyler Retzlaff } 498b70a9b78STyler Retzlaff 499b70a9b78STyler Retzlaff return ret; 500b70a9b78STyler Retzlaff } 501b70a9b78STyler Retzlaff 502b70a9b78STyler Retzlaff int 503b70a9b78STyler Retzlaff rte_thread_get_affinity_by_id(rte_thread_t thread_id, 504b70a9b78STyler Retzlaff rte_cpuset_t *cpuset) 505b70a9b78STyler Retzlaff { 506b70a9b78STyler Retzlaff HANDLE thread_handle = NULL; 507b70a9b78STyler Retzlaff PGROUP_AFFINITY cpu_affinity; 508b70a9b78STyler Retzlaff GROUP_AFFINITY thread_affinity; 509b70a9b78STyler Retzlaff unsigned int cpu_idx; 510b70a9b78STyler Retzlaff int ret = 0; 511b70a9b78STyler Retzlaff 512b70a9b78STyler Retzlaff if (cpuset == NULL) { 513b70a9b78STyler Retzlaff ret = EINVAL; 514b70a9b78STyler Retzlaff goto cleanup; 515b70a9b78STyler Retzlaff } 516b70a9b78STyler Retzlaff 517b70a9b78STyler Retzlaff thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, 518b70a9b78STyler Retzlaff thread_id.opaque_id); 519b70a9b78STyler Retzlaff if (thread_handle == NULL) { 520b70a9b78STyler Retzlaff ret = thread_log_last_error("OpenThread()"); 521b70a9b78STyler Retzlaff goto cleanup; 522b70a9b78STyler Retzlaff } 523b70a9b78STyler Retzlaff 524b70a9b78STyler Retzlaff /* obtain previous thread affinity */ 525b70a9b78STyler Retzlaff if (!GetThreadGroupAffinity(thread_handle, &thread_affinity)) { 526b70a9b78STyler Retzlaff ret = thread_log_last_error("GetThreadGroupAffinity()"); 527b70a9b78STyler Retzlaff goto cleanup; 528b70a9b78STyler Retzlaff } 529b70a9b78STyler Retzlaff 530b70a9b78STyler Retzlaff CPU_ZERO(cpuset); 531b70a9b78STyler Retzlaff 532b70a9b78STyler Retzlaff /* Convert affinity to DPDK cpu set */ 533b70a9b78STyler Retzlaff for (cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) { 534b70a9b78STyler Retzlaff 535b70a9b78STyler Retzlaff cpu_affinity = eal_get_cpu_affinity(cpu_idx); 536b70a9b78STyler Retzlaff 537b70a9b78STyler Retzlaff if ((cpu_affinity->Group == thread_affinity.Group) && 538b70a9b78STyler Retzlaff ((cpu_affinity->Mask & thread_affinity.Mask) != 0)) { 539b70a9b78STyler Retzlaff CPU_SET(cpu_idx, cpuset); 540b70a9b78STyler Retzlaff } 541b70a9b78STyler Retzlaff } 542b70a9b78STyler Retzlaff 543b70a9b78STyler Retzlaff cleanup: 544b70a9b78STyler Retzlaff if (thread_handle != NULL) { 545b70a9b78STyler Retzlaff CloseHandle(thread_handle); 546b70a9b78STyler Retzlaff thread_handle = NULL; 547b70a9b78STyler Retzlaff } 548b70a9b78STyler Retzlaff return ret; 549b70a9b78STyler Retzlaff } 550