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);
67 rte_thread_t thread_id;
69 thread_id.opaque_id = GetCurrentThreadId();
75 rte_thread_key_create(rte_thread_key *key,
76 __rte_unused void (*destructor)(void *))
78 *key = malloc(sizeof(**key));
80 RTE_LOG(DEBUG, EAL, "Cannot allocate TLS key.\n");
84 (*key)->thread_index = TlsAlloc();
85 if ((*key)->thread_index == TLS_OUT_OF_INDEXES) {
86 RTE_LOG_WIN32_ERR("TlsAlloc()");
95 rte_thread_key_delete(rte_thread_key key)
98 RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
102 if (!TlsFree(key->thread_index)) {
103 RTE_LOG_WIN32_ERR("TlsFree()");
113 rte_thread_value_set(rte_thread_key key, const void *value)
118 RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
122 /* discard const qualifier */
123 p = (char *) (uintptr_t) value;
124 if (!TlsSetValue(key->thread_index, p)) {
125 RTE_LOG_WIN32_ERR("TlsSetValue()");
133 rte_thread_value_get(rte_thread_key key)
138 RTE_LOG(DEBUG, EAL, "Invalid TLS key.\n");
142 output = TlsGetValue(key->thread_index);
143 if (GetLastError() != ERROR_SUCCESS) {
144 RTE_LOG_WIN32_ERR("TlsGetValue()");
152 convert_cpuset_to_affinity(const rte_cpuset_t *cpuset,
153 PGROUP_AFFINITY affinity)
156 PGROUP_AFFINITY cpu_affinity = NULL;
157 unsigned int cpu_idx;
159 memset(affinity, 0, sizeof(GROUP_AFFINITY));
160 affinity->Group = (USHORT)-1;
162 /* Check that all cpus of the set belong to the same processor group and
163 * accumulate thread affinity to be applied.
165 for (cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
166 if (!CPU_ISSET(cpu_idx, cpuset))
169 cpu_affinity = eal_get_cpu_affinity(cpu_idx);
171 if (affinity->Group == (USHORT)-1) {
172 affinity->Group = cpu_affinity->Group;
173 } else if (affinity->Group != cpu_affinity->Group) {
174 RTE_LOG(DEBUG, EAL, "All processors must belong to the same processor group\n");
179 affinity->Mask |= cpu_affinity->Mask;
182 if (affinity->Mask == 0) {
192 rte_thread_set_affinity_by_id(rte_thread_t thread_id,
193 const rte_cpuset_t *cpuset)
196 GROUP_AFFINITY thread_affinity;
197 HANDLE thread_handle = NULL;
199 if (cpuset == NULL) {
204 ret = convert_cpuset_to_affinity(cpuset, &thread_affinity);
206 RTE_LOG(DEBUG, EAL, "Unable to convert cpuset to thread affinity\n");
210 thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE,
211 thread_id.opaque_id);
212 if (thread_handle == NULL) {
213 ret = thread_log_last_error("OpenThread()");
217 if (!SetThreadGroupAffinity(thread_handle, &thread_affinity, NULL)) {
218 ret = thread_log_last_error("SetThreadGroupAffinity()");
223 if (thread_handle != NULL) {
224 CloseHandle(thread_handle);
225 thread_handle = NULL;
232 rte_thread_get_affinity_by_id(rte_thread_t thread_id,
233 rte_cpuset_t *cpuset)
235 HANDLE thread_handle = NULL;
236 PGROUP_AFFINITY cpu_affinity;
237 GROUP_AFFINITY thread_affinity;
238 unsigned int cpu_idx;
241 if (cpuset == NULL) {
246 thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE,
247 thread_id.opaque_id);
248 if (thread_handle == NULL) {
249 ret = thread_log_last_error("OpenThread()");
253 /* obtain previous thread affinity */
254 if (!GetThreadGroupAffinity(thread_handle, &thread_affinity)) {
255 ret = thread_log_last_error("GetThreadGroupAffinity()");
261 /* Convert affinity to DPDK cpu set */
262 for (cpu_idx = 0; cpu_idx < CPU_SETSIZE; cpu_idx++) {
264 cpu_affinity = eal_get_cpu_affinity(cpu_idx);
266 if ((cpu_affinity->Group == thread_affinity.Group) &&
267 ((cpu_affinity->Mask & thread_affinity.Mask) != 0)) {
268 CPU_SET(cpu_idx, cpuset);
273 if (thread_handle != NULL) {
274 CloseHandle(thread_handle);
275 thread_handle = NULL;