xref: /dpdk/lib/eal/windows/include/pthread.h (revision bbbe38a6d59ccdda25917712701e629d0b10af6f)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2019 Intel Corporation
3  */
4 
5 #ifndef _PTHREAD_H_
6 #define _PTHREAD_H_
7 
8 #include <stdint.h>
9 #include <sched.h>
10 
11 /**
12  * This file is required to support the common code in eal_common_proc.c,
13  * eal_common_thread.c and common\include\rte_per_lcore.h as Microsoft libc
14  * does not contain pthread.h. This may be removed in future releases.
15  */
16 #ifdef __cplusplus
17 extern "C" {
18 #endif
19 
20 #include <rte_common.h>
21 #include <rte_windows.h>
22 
23 #define PTHREAD_BARRIER_SERIAL_THREAD TRUE
24 
25 /* defining pthread_t type on Windows since there is no in Microsoft libc*/
26 typedef uintptr_t pthread_t;
27 
28 /* defining pthread_attr_t type on Windows since there is no in Microsoft libc*/
29 typedef void *pthread_attr_t;
30 
31 typedef void *pthread_mutexattr_t;
32 
33 typedef CRITICAL_SECTION pthread_mutex_t;
34 
35 typedef SYNCHRONIZATION_BARRIER pthread_barrier_t;
36 
37 #define pthread_barrier_init(barrier, attr, count) \
38 	!InitializeSynchronizationBarrier(barrier, count, -1)
39 #define pthread_barrier_wait(barrier) EnterSynchronizationBarrier(barrier, \
40 	SYNCHRONIZATION_BARRIER_FLAGS_BLOCK_ONLY)
41 #define pthread_barrier_destroy(barrier) \
42 	!DeleteSynchronizationBarrier(barrier)
43 #define pthread_cancel(thread) !TerminateThread((HANDLE) thread, 0)
44 
45 /* pthread function overrides */
46 #define pthread_self() \
47 	((pthread_t)GetCurrentThreadId())
48 
49 
50 static inline int
51 pthread_equal(pthread_t t1, pthread_t t2)
52 {
53 	return t1 == t2;
54 }
55 
56 static inline int
57 pthread_setaffinity_np(pthread_t threadid, size_t cpuset_size,
58 			rte_cpuset_t *cpuset)
59 {
60 	DWORD_PTR ret = 0;
61 	HANDLE thread_handle;
62 
63 	if (cpuset == NULL || cpuset_size == 0)
64 		return -1;
65 
66 	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, threadid);
67 	if (thread_handle == NULL) {
68 		RTE_LOG_WIN32_ERR("OpenThread()");
69 		return -1;
70 	}
71 
72 	ret = SetThreadAffinityMask(thread_handle, *cpuset->_bits);
73 	if (ret == 0) {
74 		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
75 		goto close_handle;
76 	}
77 
78 close_handle:
79 	if (CloseHandle(thread_handle) == 0) {
80 		RTE_LOG_WIN32_ERR("CloseHandle()");
81 		return -1;
82 	}
83 	return (ret == 0) ? -1 : 0;
84 }
85 
86 static inline int
87 pthread_getaffinity_np(pthread_t threadid, size_t cpuset_size,
88 			rte_cpuset_t *cpuset)
89 {
90 	/* Workaround for the lack of a GetThreadAffinityMask()
91 	 *API in Windows
92 	 */
93 	DWORD_PTR prev_affinity_mask;
94 	HANDLE thread_handle;
95 	DWORD_PTR ret = 0;
96 
97 	if (cpuset == NULL || cpuset_size == 0)
98 		return -1;
99 
100 	thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, threadid);
101 	if (thread_handle == NULL) {
102 		RTE_LOG_WIN32_ERR("OpenThread()");
103 		return -1;
104 	}
105 
106 	/* obtain previous mask by setting dummy mask */
107 	prev_affinity_mask = SetThreadAffinityMask(thread_handle, 0x1);
108 	if (prev_affinity_mask == 0) {
109 		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
110 		goto close_handle;
111 	}
112 
113 	/* set it back! */
114 	ret = SetThreadAffinityMask(thread_handle, prev_affinity_mask);
115 	if (ret == 0) {
116 		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
117 		goto close_handle;
118 	}
119 
120 	memset(cpuset, 0, cpuset_size);
121 	*cpuset->_bits = prev_affinity_mask;
122 
123 close_handle:
124 	if (CloseHandle(thread_handle) == 0) {
125 		RTE_LOG_WIN32_ERR("SetThreadAffinityMask()");
126 		return -1;
127 	}
128 	return (ret == 0) ? -1 : 0;
129 }
130 
131 static inline int
132 pthread_create(void *threadid, const void *threadattr, void *threadfunc,
133 		void *args)
134 {
135 	RTE_SET_USED(threadattr);
136 	HANDLE hThread;
137 	hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)threadfunc,
138 		args, 0, (LPDWORD)threadid);
139 	if (hThread) {
140 		SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
141 		SetThreadPriority(hThread, THREAD_PRIORITY_NORMAL);
142 	}
143 	return ((hThread != NULL) ? 0 : E_FAIL);
144 }
145 
146 static inline int
147 pthread_detach(__rte_unused pthread_t thread)
148 {
149 	return 0;
150 }
151 
152 static inline int
153 pthread_join(__rte_unused pthread_t thread,
154 	__rte_unused void **value_ptr)
155 {
156 	return 0;
157 }
158 
159 static inline int
160 pthread_mutex_init(pthread_mutex_t *mutex,
161 		   __rte_unused pthread_mutexattr_t *attr)
162 {
163 	InitializeCriticalSection(mutex);
164 	return 0;
165 }
166 
167 static inline int
168 pthread_mutex_lock(pthread_mutex_t *mutex)
169 {
170 	EnterCriticalSection(mutex);
171 	return 0;
172 }
173 
174 static inline int
175 pthread_mutex_unlock(pthread_mutex_t *mutex)
176 {
177 	LeaveCriticalSection(mutex);
178 	return 0;
179 }
180 
181 static inline int
182 pthread_mutex_destroy(pthread_mutex_t *mutex)
183 {
184 	DeleteCriticalSection(mutex);
185 	return 0;
186 }
187 
188 #ifdef __cplusplus
189 }
190 #endif
191 
192 #endif /* _PTHREAD_H_ */
193