1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2021 Mellanox Technologies, Ltd
3 * Copyright (C) 2022 Microsoft Corporation
6 #include <rte_common.h>
8 #include <rte_thread.h>
10 #include "eal_windows.h"
16 /* Translates the most common error codes related to threads */
18 thread_translate_win32_error(DWORD error)
24 case ERROR_INVALID_PARAMETER:
27 case ERROR_INVALID_HANDLE:
30 case ERROR_NOT_ENOUGH_MEMORY:
32 case ERROR_NO_SYSTEM_RESOURCES:
35 case ERROR_PRIVILEGE_NOT_HELD:
37 case ERROR_ACCESS_DENIED:
40 case ERROR_ALREADY_EXISTS:
43 case ERROR_POSSIBLE_DEADLOCK:
46 case ERROR_INVALID_FUNCTION:
48 case ERROR_CALL_NOT_IMPLEMENTED:
56 thread_log_last_error(const char *message)
58 DWORD error = GetLastError();
59 RTE_LOG(DEBUG, EAL, "GetLastError()=%lu: %s\n", error, message);
61 return thread_translate_win32_error(error);
65 thread_map_priority_to_os_value(enum rte_thread_priority eal_pri, int *os_pri,
68 /* Clear the output parameters. */
73 case RTE_THREAD_PRIORITY_NORMAL:
74 *pri_class = NORMAL_PRIORITY_CLASS;
75 *os_pri = THREAD_PRIORITY_NORMAL;
77 case RTE_THREAD_PRIORITY_REALTIME_CRITICAL:
78 *pri_class = REALTIME_PRIORITY_CLASS;
79 *os_pri = THREAD_PRIORITY_TIME_CRITICAL;
82 RTE_LOG(DEBUG, EAL, "The requested priority value is invalid.\n");
90 thread_map_os_priority_to_eal_value(int os_pri, DWORD pri_class,
91 enum rte_thread_priority *eal_pri)
94 case NORMAL_PRIORITY_CLASS:
95 if (os_pri == THREAD_PRIORITY_NORMAL) {
96 *eal_pri = RTE_THREAD_PRIORITY_NORMAL;
100 case HIGH_PRIORITY_CLASS:
101 RTE_LOG(WARNING, EAL, "The OS priority class is high not real-time.\n");
103 case REALTIME_PRIORITY_CLASS:
104 if (os_pri == THREAD_PRIORITY_TIME_CRITICAL) {
105 *eal_pri = RTE_THREAD_PRIORITY_REALTIME_CRITICAL;
110 RTE_LOG(DEBUG, EAL, "The OS priority value does not map to an EAL-defined priority.\n");
118 rte_thread_self(void)
120 rte_thread_t thread_id;
122 thread_id.opaque_id = GetCurrentThreadId();
128 rte_thread_get_priority(rte_thread_t thread_id,
129 enum rte_thread_priority *priority)
131 HANDLE thread_handle = NULL;
136 pri_class = GetPriorityClass(GetCurrentProcess());
137 if (pri_class == 0) {
138 ret = thread_log_last_error("GetPriorityClass()");
142 thread_handle = OpenThread(THREAD_SET_INFORMATION |
143 THREAD_QUERY_INFORMATION, FALSE, thread_id.opaque_id);
144 if (thread_handle == NULL) {
145 ret = thread_log_last_error("OpenThread()");
149 os_pri = GetThreadPriority(thread_handle);
150 if (os_pri == THREAD_PRIORITY_ERROR_RETURN) {
151 ret = thread_log_last_error("GetThreadPriority()");
155 ret = thread_map_os_priority_to_eal_value(os_pri, pri_class, priority);
160 if (thread_handle != NULL)
161 CloseHandle(thread_handle);
167 rte_thread_set_priority(rte_thread_t thread_id,
168 enum rte_thread_priority priority)
170 HANDLE thread_handle;
171 DWORD priority_class;
175 thread_handle = OpenThread(THREAD_SET_INFORMATION |
176 THREAD_QUERY_INFORMATION, FALSE, thread_id.opaque_id);
177 if (thread_handle == NULL) {
178 ret = thread_log_last_error("OpenThread()");
182 ret = thread_map_priority_to_os_value(priority, &os_priority,
187 if (!SetPriorityClass(GetCurrentProcess(), priority_class)) {
188 ret = thread_log_last_error("SetPriorityClass()");
192 if (!SetThreadPriority(thread_handle, os_priority)) {
193 ret = thread_log_last_error("SetThreadPriority()");
198 if (thread_handle != NULL)
199 CloseHandle(thread_handle);
205 rte_thread_key_create(rte_thread_key *key,
206 __rte_unused void (*destructor)(void *))
208 *key = malloc(sizeof(**key));
209 if ((*key) == NULL) {
210 RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
214 (*key)->thread_index = TlsAlloc();
215 if ((*key)->thread_index == TLS_OUT_OF_INDEXES) {
216 RTE_LOG_WIN32_ERR("TlsAlloc()");
225 rte_thread_key_delete(rte_thread_key key)
228 RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
232 if (!TlsFree(key->thread_index)) {
233 RTE_LOG_WIN32_ERR("TlsFree()");
243 rte_thread_value_set(rte_thread_key key, const void *value)
248 RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
252 /* discard const qualifier */
253 p = (char *) (uintptr_t) value;
254 if (!TlsSetValue(key->thread_index, p)) {
255 RTE_LOG_WIN32_ERR("TlsSetValue()");
263 rte_thread_value_get(rte_thread_key key)
268 RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
272 output = TlsGetValue(key->thread_index);
273 if (GetLastError() != ERROR_SUCCESS) {
274 RTE_LOG_WIN32_ERR("TlsGetValue()");
282 convert_cpuset_to_affinity(const rte_cpuset_t *cpuset,
283 PGROUP_AFFINITY affinity)
286 PGROUP_AFFINITY cpu_affinity = NULL;
287 unsigned int cpu_idx;
289 memset(affinity, 0, sizeof(GROUP_AFFINITY));
290 affinity->Group = (USHORT)-1;
292 /* Check that all cpus of the set belong to the same processor group and
293 * accumulate thread affinity to be applied.
295 for (cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
296 if (!CPU_ISSET(cpu_idx, cpuset))
299 cpu_affinity = eal_get_cpu_affinity(cpu_idx);
301 if (affinity->Group == (USHORT)-1) {
302 affinity->Group = cpu_affinity->Group;
303 } else if (affinity->Group != cpu_affinity->Group) {
304 RTE_LOG(DEBUG, EAL, "All processors must belong to the same processor group\n");
309 affinity->Mask |= cpu_affinity->Mask;
312 if (affinity->Mask == 0) {
322 rte_thread_set_affinity_by_id(rte_thread_t thread_id,
323 const rte_cpuset_t *cpuset)
326 GROUP_AFFINITY thread_affinity;
327 HANDLE thread_handle = NULL;
329 if (cpuset == NULL) {
334 ret = convert_cpuset_to_affinity(cpuset, &thread_affinity);
336 RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
340 thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE,
341 thread_id.opaque_id);
342 if (thread_handle == NULL) {
343 ret = thread_log_last_error("OpenThread()");
347 if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) {
348 ret = thread_log_last_error("SetThreadGroupAffinity()");
353 if (thread_handle != NULL) {
354 CloseHandle(thread_handle);
355 thread_handle = NULL;
362 rte_thread_get_affinity_by_id(rte_thread_t thread_id,
363 rte_cpuset_t *cpuset)
365 HANDLE thread_handle = NULL;
366 PGROUP_AFFINITY cpu_affinity;
367 GROUP_AFFINITY thread_affinity;
368 unsigned int cpu_idx;
371 if (cpuset == NULL) {
376 thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE,
377 thread_id.opaque_id);
378 if (thread_handle == NULL) {
379 ret = thread_log_last_error("OpenThread()");
383 /* obtain previous thread affinity */
384 if (!GetThreadGroupAffinity(thread_handle, &thread_affinity)) {
385 ret = thread_log_last_error("GetThreadGroupAffinity()");
391 /* Convert affinity to DPDK cpu set */
392 for (cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
394 cpu_affinity = eal_get_cpu_affinity(cpu_idx);
396 if ((cpu_affinity->Group == thread_affinity.Group) &&
397 ((cpu_affinity->Mask & thread_affinity.Mask) != 0)) {
398 CPU_SET(cpu_idx, cpuset);
403 if (thread_handle != NULL) {
404 CloseHandle(thread_handle);
405 thread_handle = NULL;