blob: f7721912f9088bf84224943aa836a69356949f18 [file] [log] [blame]
Austin Schuh3333ec72022-12-29 16:21:06 -08001/**
2Copyright John Schember <john@nachtimwald.com>
3
4Permission is hereby granted, free of charge, to any person obtaining a copy of
5this software and associated documentation files (the "Software"), to deal in
6the Software without restriction, including without limitation the rights to
7use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8of the Software, and to permit persons to whom the Software is furnished to do
9so, subject to the following conditions:
10
11The above copyright notice and this permission notice shall be included in all
12copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20SOFTWARE.
21 */
22
23#include "common/pthreads_cross.h"
24#include <time.h>
25
26#ifdef _WIN32
27
28typedef struct {
29 SRWLOCK lock;
30 bool exclusive;
31} pthread_rwlock_t;
32
33int pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr);
34int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
35int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
36int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
37int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
38int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
39int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
40
41int pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *arg)
42{
43 (void) attr;
44
45 if (thread == NULL || start_routine == NULL)
46 return 1;
47
48 *thread = (HANDLE) CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)start_routine, arg, 0, NULL);
49 if (*thread == NULL)
50 return 1;
51 return 0;
52}
53
54int pthread_join(pthread_t thread, void **value_ptr)
55{
56 (void)value_ptr;
57 WaitForSingleObject(thread, INFINITE);
58 CloseHandle(thread);
59 return 0;
60}
61
62int pthread_detach(pthread_t thread)
63{
64 CloseHandle(thread);
65 return 0;
66}
67
68int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *attr)
69{
70 (void)attr;
71
72 if (mutex == NULL)
73 return 1;
74
75 InitializeCriticalSection(mutex);
76 return 0;
77}
78
79int pthread_mutex_destroy(pthread_mutex_t *mutex)
80{
81 if (mutex == NULL)
82 return 1;
83 DeleteCriticalSection(mutex);
84 return 0;
85}
86
87int pthread_mutex_lock(pthread_mutex_t *mutex)
88{
89 if (mutex == NULL)
90 return 1;
91 EnterCriticalSection(mutex);
92 return 0;
93}
94
95int pthread_mutex_unlock(pthread_mutex_t *mutex)
96{
97 if (mutex == NULL)
98 return 1;
99 LeaveCriticalSection(mutex);
100 return 0;
101}
102
103int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *attr)
104{
105 (void)attr;
106 if (cond == NULL)
107 return 1;
108 InitializeConditionVariable(cond);
109 return 0;
110}
111
112int pthread_cond_destroy(pthread_cond_t *cond)
113{
114 /* Windows does not have a destroy for conditionals */
115 (void)cond;
116 return 0;
117}
118
119int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
120{
121 if (cond == NULL || mutex == NULL)
122 return 1;
123 return pthread_cond_timedwait(cond, mutex, NULL);
124}
125
126int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
127 const struct timespec *abstime)
128{
129 if (cond == NULL || mutex == NULL)
130 return 1;
131 if (!SleepConditionVariableCS(cond, mutex, timespec_to_ms(abstime)))
132 return 1;
133 return 0;
134}
135
136int pthread_cond_signal(pthread_cond_t *cond)
137{
138 if (cond == NULL)
139 return 1;
140 WakeConditionVariable(cond);
141 return 0;
142}
143
144int pthread_cond_broadcast(pthread_cond_t *cond)
145{
146 if (cond == NULL)
147 return 1;
148 WakeAllConditionVariable(cond);
149 return 0;
150}
151
152int pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr)
153{
154 (void)attr;
155 if (rwlock == NULL)
156 return 1;
157 InitializeSRWLock(&(rwlock->lock));
158 rwlock->exclusive = false;
159 return 0;
160}
161
162int pthread_rwlock_destroy(pthread_rwlock_t *rwlock)
163{
164 (void)rwlock;
165 return 0;
166}
167
168int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock)
169{
170 if (rwlock == NULL)
171 return 1;
172 AcquireSRWLockShared(&(rwlock->lock));
173 return 0;
174}
175
176int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock)
177{
178 if (rwlock == NULL)
179 return 1;
180 return !TryAcquireSRWLockShared(&(rwlock->lock));
181}
182
183int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock)
184{
185 if (rwlock == NULL)
186 return 1;
187 AcquireSRWLockExclusive(&(rwlock->lock));
188 rwlock->exclusive = true;
189 return 0;
190}
191
192int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock)
193{
194 BOOLEAN ret;
195
196 if (rwlock == NULL)
197 return 1;
198
199 ret = TryAcquireSRWLockExclusive(&(rwlock->lock));
200 if (ret)
201 rwlock->exclusive = true;
202 return ret;
203}
204
205int pthread_rwlock_unlock(pthread_rwlock_t *rwlock)
206{
207 if (rwlock == NULL)
208 return 1;
209
210 if (rwlock->exclusive) {
211 rwlock->exclusive = false;
212 ReleaseSRWLockExclusive(&(rwlock->lock));
213 } else {
214 ReleaseSRWLockShared(&(rwlock->lock));
215 }
216 return 0;
217}
218
219int sched_yield() {
220 return (int)SwitchToThread();
221}
222
223void ms_to_timespec(struct timespec *ts, unsigned int ms)
224{
225 if (ts == NULL)
226 return;
227 ts->tv_sec = (ms / 1000) + time(NULL);
228 ts->tv_nsec = (ms % 1000) * 1000000;
229}
230
231unsigned int timespec_to_ms(const struct timespec *abstime)
232{
233 DWORD t;
234
235 if (abstime == NULL)
236 return INFINITE;
237
238 t = ((abstime->tv_sec - time(NULL)) * 1000) + (abstime->tv_nsec / 1000000);
239 if (t < 0)
240 t = 1;
241 return t;
242}
243
244unsigned int pcthread_get_num_procs()
245{
246 SYSTEM_INFO sysinfo;
247
248 GetSystemInfo(&sysinfo);
249 return sysinfo.dwNumberOfProcessors;
250}
251
252#else
253
254#include <unistd.h>
255unsigned int pcthread_get_num_procs()
256{
257 return (unsigned int)sysconf(_SC_NPROCESSORS_ONLN);
258}
259#endif