DarkPlaces
Game engine based on the Quake 1 engine by id Software, developed by LadyHavoc
 
thread_win.c
Go to the documentation of this file.
1#include "quakedef.h"
2#include "thread.h"
3#include <process.h>
4
5int Thread_Init(void)
6{
7#ifdef THREADDISABLE
8 Con_Printf("Threading disabled in this build\n");
9#endif
10 return 0;
11}
12
14{
15}
16
18{
19#ifdef THREADDISABLE
20 return false;
21#else
22 return true;
23#endif
24}
25
26void *_Thread_CreateMutex(const char *filename, int fileline)
27{
28 void *mutex = (void *)CreateMutex(NULL, FALSE, NULL);
29#ifdef THREADDEBUG
30 Sys_Printf("%p mutex create %s:%i\n" , mutex, filename, fileline);
31#endif
32 return mutex;
33}
34
35void _Thread_DestroyMutex(void *mutex, const char *filename, int fileline)
36{
37#ifdef THREADDEBUG
38 Sys_Printf("%p mutex destroy %s:%i\n", mutex, filename, fileline);
39#endif
40 CloseHandle(mutex);
41}
42
43int _Thread_LockMutex(void *mutex, const char *filename, int fileline)
44{
45#ifdef THREADDEBUG
46 Sys_Printf("%p mutex lock %s:%i\n" , mutex, filename, fileline);
47#endif
48 return (WaitForSingleObject(mutex, INFINITE) == WAIT_FAILED) ? -1 : 0;
49}
50
51int _Thread_UnlockMutex(void *mutex, const char *filename, int fileline)
52{
53#ifdef THREADDEBUG
54 Sys_Printf("%p mutex unlock %s:%i\n" , mutex, filename, fileline);
55#endif
56 return (ReleaseMutex(mutex) == false) ? -1 : 0;
57}
58
59typedef struct thread_semaphore_s
60{
61 HANDLE semaphore;
62 volatile LONG value;
63}
65
67{
68 thread_semaphore_t *s = (thread_semaphore_t *)calloc(sizeof(*s), 1);
69 s->semaphore = CreateSemaphore(NULL, v, 32768, NULL);
70 s->value = v;
71 return s;
72}
73
75{
76 CloseHandle(s->semaphore);
77 free(s);
78}
79
80static int Thread_WaitSemaphore(thread_semaphore_t *s, unsigned int msec)
81{
82 int r = WaitForSingleObject(s->semaphore, msec);
83 if (r == WAIT_OBJECT_0)
84 {
85 InterlockedDecrement(&s->value);
86 return 0;
87 }
88 if (r == WAIT_TIMEOUT)
89 return 1;
90 return -1;
91}
92
94{
95 InterlockedIncrement(&s->value);
96 if (ReleaseSemaphore(s->semaphore, 1, NULL))
97 return 0;
98 InterlockedDecrement(&s->value);
99 return -1;
100}
101
102typedef struct thread_cond_s
103{
104 HANDLE mutex;
109}
111
112void *_Thread_CreateCond(const char *filename, int fileline)
113{
114 thread_cond_t *c = (thread_cond_t *)calloc(sizeof(*c), 1);
115 c->mutex = CreateMutex(NULL, FALSE, NULL);
118 c->waiting = 0;
119 c->signals = 0;
120#ifdef THREADDEBUG
121 Sys_Printf("%p cond create %s:%i\n" , c, filename, fileline);
122#endif
123 return c;
124}
125
126void _Thread_DestroyCond(void *cond, const char *filename, int fileline)
127{
128 thread_cond_t *c = (thread_cond_t *)cond;
129#ifdef THREADDEBUG
130 Sys_Printf("%p cond destroy %s:%i\n" , cond, filename, fileline);
131#endif
134 CloseHandle(c->mutex);
135}
136
137int _Thread_CondSignal(void *cond, const char *filename, int fileline)
138{
139 thread_cond_t *c = (thread_cond_t *)cond;
140 int n;
141#ifdef THREADDEBUG
142 Sys_Printf("%p cond signal %s:%i\n" , cond, filename, fileline);
143#endif
144 WaitForSingleObject(c->mutex, INFINITE);
145 n = c->waiting - c->signals;
146 if (n > 0)
147 {
148 c->signals++;
150 }
151 ReleaseMutex(c->mutex);
152 if (n > 0)
153 Thread_WaitSemaphore(c->done, INFINITE);
154 return 0;
155}
156
157int _Thread_CondBroadcast(void *cond, const char *filename, int fileline)
158{
159 thread_cond_t *c = (thread_cond_t *)cond;
160 int i = 0;
161 int n = 0;
162#ifdef THREADDEBUG
163 Sys_Printf("%p cond broadcast %s:%i\n" , cond, filename, fileline);
164#endif
165 WaitForSingleObject(c->mutex, INFINITE);
166 n = c->waiting - c->signals;
167 if (n > 0)
168 {
169 c->signals += n;
170 for (i = 0;i < n;i++)
172 }
173 ReleaseMutex(c->mutex);
174 for (i = 0;i < n;i++)
175 Thread_WaitSemaphore(c->done, INFINITE);
176 return 0;
177}
178
179int _Thread_CondWait(void *cond, void *mutex, const char *filename, int fileline)
180{
181 thread_cond_t *c = (thread_cond_t *)cond;
182 int waitresult;
183#ifdef THREADDEBUG
184 Sys_Printf("%p cond wait %s:%i\n" , cond, filename, fileline);
185#endif
186
187 WaitForSingleObject(c->mutex, INFINITE);
188 c->waiting++;
189 ReleaseMutex(c->mutex);
190
191 ReleaseMutex(mutex);
192
193 waitresult = Thread_WaitSemaphore(c->sem, INFINITE);
194 WaitForSingleObject(c->mutex, INFINITE);
195 if (c->signals > 0)
196 {
197 if (waitresult > 0)
198 Thread_WaitSemaphore(c->sem, INFINITE);
200 c->signals--;
201 }
202 c->waiting--;
203 ReleaseMutex(c->mutex);
204
205 WaitForSingleObject(mutex, INFINITE);
206 return waitresult;
207}
208
209typedef struct threadwrapper_s
210{
211 HANDLE handle;
212 unsigned int threadid;
214 int (*fn)(void *);
215 void *data;
216}
218
219unsigned int __stdcall Thread_WrapperFunc(void *d)
220{
222 w->result = w->fn(w->data);
223 _endthreadex(w->result);
224 return w->result;
225}
226
227void *_Thread_CreateThread(int (*fn)(void *), void *data, const char *filename, int fileline)
228{
229 threadwrapper_t *w = (threadwrapper_t *)calloc(sizeof(*w), 1);
230#ifdef THREADDEBUG
231 Sys_Printf("%p thread create %s:%i\n" , w, filename, fileline);
232#endif
233 w->fn = fn;
234 w->data = data;
235 w->threadid = 0;
236 w->result = 0;
237 w->handle = (HANDLE)_beginthreadex(NULL, 0, Thread_WrapperFunc, (void *)w, 0, &w->threadid);
238 return (void *)w;
239}
240
241int _Thread_WaitThread(void *d, int retval, const char *filename, int fileline)
242{
244#ifdef THREADDEBUG
245 Sys_Printf("%p thread wait %s:%i\n" , w, filename, fileline);
246#endif
247 WaitForSingleObject(w->handle, INFINITE);
248 CloseHandle(w->handle);
249 retval = w->result;
250 free(w);
251 return retval;
252}
253
254// standard barrier implementation using conds and mutexes
255// see: http://www.howforge.com/implementing-barrier-in-pthreads
256typedef struct {
257 unsigned int needed;
258 unsigned int called;
259 void *mutex;
260 void *cond;
261} barrier_t;
262
263void *_Thread_CreateBarrier(unsigned int count, const char *filename, int fileline)
264{
265 volatile barrier_t *b = (volatile barrier_t *) Z_Malloc(sizeof(barrier_t));
266#ifdef THREADDEBUG
267 Sys_Printf("%p barrier create(%d) %s:%i\n", b, count, filename, fileline);
268#endif
269 b->needed = count;
270 b->called = 0;
271 b->mutex = Thread_CreateMutex();
272 b->cond = Thread_CreateCond();
273 return (void *) b;
274}
275
276void _Thread_DestroyBarrier(void *barrier, const char *filename, int fileline)
277{
278 volatile barrier_t *b = (volatile barrier_t *) barrier;
279#ifdef THREADDEBUG
280 Sys_Printf("%p barrier destroy %s:%i\n", b, filename, fileline);
281#endif
282 Thread_DestroyMutex(b->mutex);
283 Thread_DestroyCond(b->cond);
284}
285
286void _Thread_WaitBarrier(void *barrier, const char *filename, int fileline)
287{
288 volatile barrier_t *b = (volatile barrier_t *) barrier;
289#ifdef THREADDEBUG
290 Sys_Printf("%p barrier wait %s:%i\n", b, filename, fileline);
291#endif
292 Thread_LockMutex(b->mutex);
293 b->called++;
294 if (b->called == b->needed) {
295 b->called = 0;
296 Thread_CondBroadcast(b->cond);
297 } else {
298 do {
299 Thread_CondWait(b->cond, b->mutex);
300 } while(b->called);
301 }
302 Thread_UnlockMutex(b->mutex);
303}
void Con_Printf(const char *fmt,...)
Prints to all appropriate console targets.
Definition console.c:1514
const float FALSE
#define n(x, y)
static int(ZEXPORT *qz_inflate)(z_stream *strm
GLubyte GLubyte GLubyte GLubyte w
Definition glquake.h:782
const GLdouble * v
Definition glquake.h:762
GLenum GLenum GLsizei count
Definition glquake.h:656
GLsizeiptr const GLvoid * data
Definition glquake.h:639
int i
#define NULL
Definition qtypes.h:12
bool qbool
Definition qtypes.h:9
dp_FragColor r
dp_FragColor b
thread_semaphore_t * done
Definition thread_win.c:108
thread_semaphore_t * sem
Definition thread_win.c:107
volatile LONG value
Definition thread_win.c:62
unsigned int threadid
Definition thread_win.c:212
void Sys_Printf(const char *fmt,...)
used to report failures inside Con_Printf()
Definition sys_shared.c:652
#define Thread_CondBroadcast(cond)
Definition thread.h:22
#define Thread_DestroyMutex(m)
Definition thread.h:16
#define Thread_DestroyCond(cond)
Definition thread.h:20
#define Thread_CreateMutex()
Definition thread.h:15
#define Thread_LockMutex(m)
Definition thread.h:17
#define Thread_CreateCond()
Definition thread.h:19
#define Thread_UnlockMutex(m)
Definition thread.h:18
#define Thread_CondWait(cond, mutex)
Definition thread.h:23
int _Thread_WaitThread(void *d, int retval, const char *filename, int fileline)
Definition thread_win.c:241
void * _Thread_CreateBarrier(unsigned int count, const char *filename, int fileline)
Definition thread_win.c:263
int _Thread_CondWait(void *cond, void *mutex, const char *filename, int fileline)
Definition thread_win.c:179
int Thread_Init(void)
Definition thread_win.c:5
void * _Thread_CreateMutex(const char *filename, int fileline)
Definition thread_win.c:26
void _Thread_WaitBarrier(void *barrier, const char *filename, int fileline)
Definition thread_win.c:286
int _Thread_UnlockMutex(void *mutex, const char *filename, int fileline)
Definition thread_win.c:51
qbool Thread_HasThreads(void)
Definition thread_win.c:17
void * _Thread_CreateThread(int(*fn)(void *), void *data, const char *filename, int fileline)
Definition thread_win.c:227
int _Thread_LockMutex(void *mutex, const char *filename, int fileline)
Definition thread_win.c:43
void * _Thread_CreateCond(const char *filename, int fileline)
Definition thread_win.c:112
int _Thread_CondSignal(void *cond, const char *filename, int fileline)
Definition thread_win.c:137
void _Thread_DestroyCond(void *cond, const char *filename, int fileline)
Definition thread_win.c:126
void Thread_Shutdown(void)
Definition thread_win.c:13
unsigned int __stdcall Thread_WrapperFunc(void *d)
Definition thread_win.c:219
static int Thread_WaitSemaphore(thread_semaphore_t *s, unsigned int msec)
Definition thread_win.c:80
void _Thread_DestroyBarrier(void *barrier, const char *filename, int fileline)
Definition thread_win.c:276
static int Thread_PostSemaphore(thread_semaphore_t *s)
Definition thread_win.c:93
static void Thread_DestroySemaphore(thread_semaphore_t *s)
Definition thread_win.c:74
static thread_semaphore_t * Thread_CreateSemaphore(unsigned int v)
Definition thread_win.c:66
void _Thread_DestroyMutex(void *mutex, const char *filename, int fileline)
Definition thread_win.c:35
int _Thread_CondBroadcast(void *cond, const char *filename, int fileline)
Definition thread_win.c:157
#define Z_Malloc(size)
Definition zone.h:161