xref: /aosp_15_r20/external/libevent/evthread_win32.c (revision 663afb9b963571284e0f0a60f257164ab54f64bf)
1*663afb9bSAndroid Build Coastguard Worker /*
2*663afb9bSAndroid Build Coastguard Worker  * Copyright 2009-2012 Niels Provos and Nick Mathewson
3*663afb9bSAndroid Build Coastguard Worker  *
4*663afb9bSAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
5*663afb9bSAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions
6*663afb9bSAndroid Build Coastguard Worker  * are met:
7*663afb9bSAndroid Build Coastguard Worker  * 1. Redistributions of source code must retain the above copyright
8*663afb9bSAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer.
9*663afb9bSAndroid Build Coastguard Worker  * 2. Redistributions in binary form must reproduce the above copyright
10*663afb9bSAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer in the
11*663afb9bSAndroid Build Coastguard Worker  *    documentation and/or other materials provided with the distribution.
12*663afb9bSAndroid Build Coastguard Worker  * 3. The name of the author may not be used to endorse or promote products
13*663afb9bSAndroid Build Coastguard Worker  *    derived from this software without specific prior written permission.
14*663afb9bSAndroid Build Coastguard Worker  *
15*663afb9bSAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16*663afb9bSAndroid Build Coastguard Worker  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17*663afb9bSAndroid Build Coastguard Worker  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18*663afb9bSAndroid Build Coastguard Worker  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19*663afb9bSAndroid Build Coastguard Worker  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20*663afb9bSAndroid Build Coastguard Worker  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21*663afb9bSAndroid Build Coastguard Worker  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22*663afb9bSAndroid Build Coastguard Worker  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23*663afb9bSAndroid Build Coastguard Worker  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24*663afb9bSAndroid Build Coastguard Worker  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*663afb9bSAndroid Build Coastguard Worker  */
26*663afb9bSAndroid Build Coastguard Worker #include "event2/event-config.h"
27*663afb9bSAndroid Build Coastguard Worker #include "evconfig-private.h"
28*663afb9bSAndroid Build Coastguard Worker 
29*663afb9bSAndroid Build Coastguard Worker #ifdef _WIN32
30*663afb9bSAndroid Build Coastguard Worker #ifndef _WIN32_WINNT
31*663afb9bSAndroid Build Coastguard Worker /* Minimum required for InitializeCriticalSectionAndSpinCount */
32*663afb9bSAndroid Build Coastguard Worker #define _WIN32_WINNT 0x0403
33*663afb9bSAndroid Build Coastguard Worker #endif
34*663afb9bSAndroid Build Coastguard Worker #include <winsock2.h>
35*663afb9bSAndroid Build Coastguard Worker #define WIN32_LEAN_AND_MEAN
36*663afb9bSAndroid Build Coastguard Worker #include <windows.h>
37*663afb9bSAndroid Build Coastguard Worker #undef WIN32_LEAN_AND_MEAN
38*663afb9bSAndroid Build Coastguard Worker #include <sys/locking.h>
39*663afb9bSAndroid Build Coastguard Worker #endif
40*663afb9bSAndroid Build Coastguard Worker 
41*663afb9bSAndroid Build Coastguard Worker struct event_base;
42*663afb9bSAndroid Build Coastguard Worker #include "event2/thread.h"
43*663afb9bSAndroid Build Coastguard Worker 
44*663afb9bSAndroid Build Coastguard Worker #include "mm-internal.h"
45*663afb9bSAndroid Build Coastguard Worker #include "evthread-internal.h"
46*663afb9bSAndroid Build Coastguard Worker #include "time-internal.h"
47*663afb9bSAndroid Build Coastguard Worker 
48*663afb9bSAndroid Build Coastguard Worker #define SPIN_COUNT 2000
49*663afb9bSAndroid Build Coastguard Worker 
50*663afb9bSAndroid Build Coastguard Worker static void *
evthread_win32_lock_create(unsigned locktype)51*663afb9bSAndroid Build Coastguard Worker evthread_win32_lock_create(unsigned locktype)
52*663afb9bSAndroid Build Coastguard Worker {
53*663afb9bSAndroid Build Coastguard Worker 	CRITICAL_SECTION *lock = mm_malloc(sizeof(CRITICAL_SECTION));
54*663afb9bSAndroid Build Coastguard Worker 	if (!lock)
55*663afb9bSAndroid Build Coastguard Worker 		return NULL;
56*663afb9bSAndroid Build Coastguard Worker 	if (InitializeCriticalSectionAndSpinCount(lock, SPIN_COUNT) == 0) {
57*663afb9bSAndroid Build Coastguard Worker 		mm_free(lock);
58*663afb9bSAndroid Build Coastguard Worker 		return NULL;
59*663afb9bSAndroid Build Coastguard Worker 	}
60*663afb9bSAndroid Build Coastguard Worker 	return lock;
61*663afb9bSAndroid Build Coastguard Worker }
62*663afb9bSAndroid Build Coastguard Worker 
63*663afb9bSAndroid Build Coastguard Worker static void
evthread_win32_lock_free(void * lock_,unsigned locktype)64*663afb9bSAndroid Build Coastguard Worker evthread_win32_lock_free(void *lock_, unsigned locktype)
65*663afb9bSAndroid Build Coastguard Worker {
66*663afb9bSAndroid Build Coastguard Worker 	CRITICAL_SECTION *lock = lock_;
67*663afb9bSAndroid Build Coastguard Worker 	DeleteCriticalSection(lock);
68*663afb9bSAndroid Build Coastguard Worker 	mm_free(lock);
69*663afb9bSAndroid Build Coastguard Worker }
70*663afb9bSAndroid Build Coastguard Worker 
71*663afb9bSAndroid Build Coastguard Worker static int
evthread_win32_lock(unsigned mode,void * lock_)72*663afb9bSAndroid Build Coastguard Worker evthread_win32_lock(unsigned mode, void *lock_)
73*663afb9bSAndroid Build Coastguard Worker {
74*663afb9bSAndroid Build Coastguard Worker 	CRITICAL_SECTION *lock = lock_;
75*663afb9bSAndroid Build Coastguard Worker 	if ((mode & EVTHREAD_TRY)) {
76*663afb9bSAndroid Build Coastguard Worker 		return ! TryEnterCriticalSection(lock);
77*663afb9bSAndroid Build Coastguard Worker 	} else {
78*663afb9bSAndroid Build Coastguard Worker 		EnterCriticalSection(lock);
79*663afb9bSAndroid Build Coastguard Worker 		return 0;
80*663afb9bSAndroid Build Coastguard Worker 	}
81*663afb9bSAndroid Build Coastguard Worker }
82*663afb9bSAndroid Build Coastguard Worker 
83*663afb9bSAndroid Build Coastguard Worker static int
evthread_win32_unlock(unsigned mode,void * lock_)84*663afb9bSAndroid Build Coastguard Worker evthread_win32_unlock(unsigned mode, void *lock_)
85*663afb9bSAndroid Build Coastguard Worker {
86*663afb9bSAndroid Build Coastguard Worker 	CRITICAL_SECTION *lock = lock_;
87*663afb9bSAndroid Build Coastguard Worker 	LeaveCriticalSection(lock);
88*663afb9bSAndroid Build Coastguard Worker 	return 0;
89*663afb9bSAndroid Build Coastguard Worker }
90*663afb9bSAndroid Build Coastguard Worker 
91*663afb9bSAndroid Build Coastguard Worker static unsigned long
evthread_win32_get_id(void)92*663afb9bSAndroid Build Coastguard Worker evthread_win32_get_id(void)
93*663afb9bSAndroid Build Coastguard Worker {
94*663afb9bSAndroid Build Coastguard Worker 	return (unsigned long) GetCurrentThreadId();
95*663afb9bSAndroid Build Coastguard Worker }
96*663afb9bSAndroid Build Coastguard Worker 
97*663afb9bSAndroid Build Coastguard Worker #ifdef WIN32_HAVE_CONDITION_VARIABLES
98*663afb9bSAndroid Build Coastguard Worker static void WINAPI (*InitializeConditionVariable_fn)(PCONDITION_VARIABLE)
99*663afb9bSAndroid Build Coastguard Worker 	= NULL;
100*663afb9bSAndroid Build Coastguard Worker static BOOL WINAPI (*SleepConditionVariableCS_fn)(
101*663afb9bSAndroid Build Coastguard Worker 	PCONDITION_VARIABLE, PCRITICAL_SECTION, DWORD) = NULL;
102*663afb9bSAndroid Build Coastguard Worker static void WINAPI (*WakeAllConditionVariable_fn)(PCONDITION_VARIABLE) = NULL;
103*663afb9bSAndroid Build Coastguard Worker static void WINAPI (*WakeConditionVariable_fn)(PCONDITION_VARIABLE) = NULL;
104*663afb9bSAndroid Build Coastguard Worker 
105*663afb9bSAndroid Build Coastguard Worker static int
evthread_win32_condvar_init(void)106*663afb9bSAndroid Build Coastguard Worker evthread_win32_condvar_init(void)
107*663afb9bSAndroid Build Coastguard Worker {
108*663afb9bSAndroid Build Coastguard Worker 	HANDLE lib;
109*663afb9bSAndroid Build Coastguard Worker 
110*663afb9bSAndroid Build Coastguard Worker 	lib = GetModuleHandle(TEXT("kernel32.dll"));
111*663afb9bSAndroid Build Coastguard Worker 	if (lib == NULL)
112*663afb9bSAndroid Build Coastguard Worker 		return 0;
113*663afb9bSAndroid Build Coastguard Worker 
114*663afb9bSAndroid Build Coastguard Worker #define LOAD(name)				\
115*663afb9bSAndroid Build Coastguard Worker 	name##_fn = GetProcAddress(lib, #name)
116*663afb9bSAndroid Build Coastguard Worker 	LOAD(InitializeConditionVariable);
117*663afb9bSAndroid Build Coastguard Worker 	LOAD(SleepConditionVariableCS);
118*663afb9bSAndroid Build Coastguard Worker 	LOAD(WakeAllConditionVariable);
119*663afb9bSAndroid Build Coastguard Worker 	LOAD(WakeConditionVariable);
120*663afb9bSAndroid Build Coastguard Worker 
121*663afb9bSAndroid Build Coastguard Worker 	return InitializeConditionVariable_fn && SleepConditionVariableCS_fn &&
122*663afb9bSAndroid Build Coastguard Worker 	    WakeAllConditionVariable_fn && WakeConditionVariable_fn;
123*663afb9bSAndroid Build Coastguard Worker }
124*663afb9bSAndroid Build Coastguard Worker 
125*663afb9bSAndroid Build Coastguard Worker /* XXXX Even if we can build this, we don't necessarily want to: the functions
126*663afb9bSAndroid Build Coastguard Worker  * in question didn't exist before Vista, so we'd better LoadProc them. */
127*663afb9bSAndroid Build Coastguard Worker static void *
evthread_win32_condvar_alloc(unsigned condflags)128*663afb9bSAndroid Build Coastguard Worker evthread_win32_condvar_alloc(unsigned condflags)
129*663afb9bSAndroid Build Coastguard Worker {
130*663afb9bSAndroid Build Coastguard Worker 	CONDITION_VARIABLE *cond = mm_malloc(sizeof(CONDITION_VARIABLE));
131*663afb9bSAndroid Build Coastguard Worker 	if (!cond)
132*663afb9bSAndroid Build Coastguard Worker 		return NULL;
133*663afb9bSAndroid Build Coastguard Worker 	InitializeConditionVariable_fn(cond);
134*663afb9bSAndroid Build Coastguard Worker 	return cond;
135*663afb9bSAndroid Build Coastguard Worker }
136*663afb9bSAndroid Build Coastguard Worker 
137*663afb9bSAndroid Build Coastguard Worker static void
evthread_win32_condvar_free(void * cond_)138*663afb9bSAndroid Build Coastguard Worker evthread_win32_condvar_free(void *cond_)
139*663afb9bSAndroid Build Coastguard Worker {
140*663afb9bSAndroid Build Coastguard Worker 	CONDITION_VARIABLE *cond = cond_;
141*663afb9bSAndroid Build Coastguard Worker 	/* There doesn't _seem_ to be a cleaup fn here... */
142*663afb9bSAndroid Build Coastguard Worker 	mm_free(cond);
143*663afb9bSAndroid Build Coastguard Worker }
144*663afb9bSAndroid Build Coastguard Worker 
145*663afb9bSAndroid Build Coastguard Worker static int
evthread_win32_condvar_signal(void * cond,int broadcast)146*663afb9bSAndroid Build Coastguard Worker evthread_win32_condvar_signal(void *cond, int broadcast)
147*663afb9bSAndroid Build Coastguard Worker {
148*663afb9bSAndroid Build Coastguard Worker 	CONDITION_VARIABLE *cond = cond_;
149*663afb9bSAndroid Build Coastguard Worker 	if (broadcast)
150*663afb9bSAndroid Build Coastguard Worker 		WakeAllConditionVariable_fn(cond);
151*663afb9bSAndroid Build Coastguard Worker 	else
152*663afb9bSAndroid Build Coastguard Worker 		WakeConditionVariable_fn(cond);
153*663afb9bSAndroid Build Coastguard Worker 	return 0;
154*663afb9bSAndroid Build Coastguard Worker }
155*663afb9bSAndroid Build Coastguard Worker 
156*663afb9bSAndroid Build Coastguard Worker static int
evthread_win32_condvar_wait(void * cond_,void * lock_,const struct timeval * tv)157*663afb9bSAndroid Build Coastguard Worker evthread_win32_condvar_wait(void *cond_, void *lock_, const struct timeval *tv)
158*663afb9bSAndroid Build Coastguard Worker {
159*663afb9bSAndroid Build Coastguard Worker 	CONDITION_VARIABLE *cond = cond_;
160*663afb9bSAndroid Build Coastguard Worker 	CRITICAL_SECTION *lock = lock_;
161*663afb9bSAndroid Build Coastguard Worker 	DWORD ms, err;
162*663afb9bSAndroid Build Coastguard Worker 	BOOL result;
163*663afb9bSAndroid Build Coastguard Worker 
164*663afb9bSAndroid Build Coastguard Worker 	if (tv)
165*663afb9bSAndroid Build Coastguard Worker 		ms = evutil_tv_to_msec_(tv);
166*663afb9bSAndroid Build Coastguard Worker 	else
167*663afb9bSAndroid Build Coastguard Worker 		ms = INFINITE;
168*663afb9bSAndroid Build Coastguard Worker 	result = SleepConditionVariableCS_fn(cond, lock, ms);
169*663afb9bSAndroid Build Coastguard Worker 	if (result) {
170*663afb9bSAndroid Build Coastguard Worker 		if (GetLastError() == WAIT_TIMEOUT)
171*663afb9bSAndroid Build Coastguard Worker 			return 1;
172*663afb9bSAndroid Build Coastguard Worker 		else
173*663afb9bSAndroid Build Coastguard Worker 			return -1;
174*663afb9bSAndroid Build Coastguard Worker 	} else {
175*663afb9bSAndroid Build Coastguard Worker 		return 0;
176*663afb9bSAndroid Build Coastguard Worker 	}
177*663afb9bSAndroid Build Coastguard Worker }
178*663afb9bSAndroid Build Coastguard Worker #endif
179*663afb9bSAndroid Build Coastguard Worker 
180*663afb9bSAndroid Build Coastguard Worker struct evthread_win32_cond {
181*663afb9bSAndroid Build Coastguard Worker 	HANDLE event;
182*663afb9bSAndroid Build Coastguard Worker 
183*663afb9bSAndroid Build Coastguard Worker 	CRITICAL_SECTION lock;
184*663afb9bSAndroid Build Coastguard Worker 	int n_waiting;
185*663afb9bSAndroid Build Coastguard Worker 	int n_to_wake;
186*663afb9bSAndroid Build Coastguard Worker 	int generation;
187*663afb9bSAndroid Build Coastguard Worker };
188*663afb9bSAndroid Build Coastguard Worker 
189*663afb9bSAndroid Build Coastguard Worker static void *
evthread_win32_cond_alloc(unsigned flags)190*663afb9bSAndroid Build Coastguard Worker evthread_win32_cond_alloc(unsigned flags)
191*663afb9bSAndroid Build Coastguard Worker {
192*663afb9bSAndroid Build Coastguard Worker 	struct evthread_win32_cond *cond;
193*663afb9bSAndroid Build Coastguard Worker 	if (!(cond = mm_malloc(sizeof(struct evthread_win32_cond))))
194*663afb9bSAndroid Build Coastguard Worker 		return NULL;
195*663afb9bSAndroid Build Coastguard Worker 	if (InitializeCriticalSectionAndSpinCount(&cond->lock, SPIN_COUNT)==0) {
196*663afb9bSAndroid Build Coastguard Worker 		mm_free(cond);
197*663afb9bSAndroid Build Coastguard Worker 		return NULL;
198*663afb9bSAndroid Build Coastguard Worker 	}
199*663afb9bSAndroid Build Coastguard Worker 	if ((cond->event = CreateEvent(NULL,TRUE,FALSE,NULL)) == NULL) {
200*663afb9bSAndroid Build Coastguard Worker 		DeleteCriticalSection(&cond->lock);
201*663afb9bSAndroid Build Coastguard Worker 		mm_free(cond);
202*663afb9bSAndroid Build Coastguard Worker 		return NULL;
203*663afb9bSAndroid Build Coastguard Worker 	}
204*663afb9bSAndroid Build Coastguard Worker 	cond->n_waiting = cond->n_to_wake = cond->generation = 0;
205*663afb9bSAndroid Build Coastguard Worker 	return cond;
206*663afb9bSAndroid Build Coastguard Worker }
207*663afb9bSAndroid Build Coastguard Worker 
208*663afb9bSAndroid Build Coastguard Worker static void
evthread_win32_cond_free(void * cond_)209*663afb9bSAndroid Build Coastguard Worker evthread_win32_cond_free(void *cond_)
210*663afb9bSAndroid Build Coastguard Worker {
211*663afb9bSAndroid Build Coastguard Worker 	struct evthread_win32_cond *cond = cond_;
212*663afb9bSAndroid Build Coastguard Worker 	DeleteCriticalSection(&cond->lock);
213*663afb9bSAndroid Build Coastguard Worker 	CloseHandle(cond->event);
214*663afb9bSAndroid Build Coastguard Worker 	mm_free(cond);
215*663afb9bSAndroid Build Coastguard Worker }
216*663afb9bSAndroid Build Coastguard Worker 
217*663afb9bSAndroid Build Coastguard Worker static int
evthread_win32_cond_signal(void * cond_,int broadcast)218*663afb9bSAndroid Build Coastguard Worker evthread_win32_cond_signal(void *cond_, int broadcast)
219*663afb9bSAndroid Build Coastguard Worker {
220*663afb9bSAndroid Build Coastguard Worker 	struct evthread_win32_cond *cond = cond_;
221*663afb9bSAndroid Build Coastguard Worker 	EnterCriticalSection(&cond->lock);
222*663afb9bSAndroid Build Coastguard Worker 	if (broadcast)
223*663afb9bSAndroid Build Coastguard Worker 		cond->n_to_wake = cond->n_waiting;
224*663afb9bSAndroid Build Coastguard Worker 	else
225*663afb9bSAndroid Build Coastguard Worker 		++cond->n_to_wake;
226*663afb9bSAndroid Build Coastguard Worker 	cond->generation++;
227*663afb9bSAndroid Build Coastguard Worker 	SetEvent(cond->event);
228*663afb9bSAndroid Build Coastguard Worker 	LeaveCriticalSection(&cond->lock);
229*663afb9bSAndroid Build Coastguard Worker 	return 0;
230*663afb9bSAndroid Build Coastguard Worker }
231*663afb9bSAndroid Build Coastguard Worker 
232*663afb9bSAndroid Build Coastguard Worker static int
evthread_win32_cond_wait(void * cond_,void * lock_,const struct timeval * tv)233*663afb9bSAndroid Build Coastguard Worker evthread_win32_cond_wait(void *cond_, void *lock_, const struct timeval *tv)
234*663afb9bSAndroid Build Coastguard Worker {
235*663afb9bSAndroid Build Coastguard Worker 	struct evthread_win32_cond *cond = cond_;
236*663afb9bSAndroid Build Coastguard Worker 	CRITICAL_SECTION *lock = lock_;
237*663afb9bSAndroid Build Coastguard Worker 	int generation_at_start;
238*663afb9bSAndroid Build Coastguard Worker 	int waiting = 1;
239*663afb9bSAndroid Build Coastguard Worker 	int result = -1;
240*663afb9bSAndroid Build Coastguard Worker 	DWORD ms = INFINITE, ms_orig = INFINITE, startTime, endTime;
241*663afb9bSAndroid Build Coastguard Worker 	if (tv)
242*663afb9bSAndroid Build Coastguard Worker 		ms_orig = ms = evutil_tv_to_msec_(tv);
243*663afb9bSAndroid Build Coastguard Worker 
244*663afb9bSAndroid Build Coastguard Worker 	EnterCriticalSection(&cond->lock);
245*663afb9bSAndroid Build Coastguard Worker 	++cond->n_waiting;
246*663afb9bSAndroid Build Coastguard Worker 	generation_at_start = cond->generation;
247*663afb9bSAndroid Build Coastguard Worker 	LeaveCriticalSection(&cond->lock);
248*663afb9bSAndroid Build Coastguard Worker 
249*663afb9bSAndroid Build Coastguard Worker 	LeaveCriticalSection(lock);
250*663afb9bSAndroid Build Coastguard Worker 
251*663afb9bSAndroid Build Coastguard Worker 	startTime = GetTickCount();
252*663afb9bSAndroid Build Coastguard Worker 	do {
253*663afb9bSAndroid Build Coastguard Worker 		DWORD res;
254*663afb9bSAndroid Build Coastguard Worker 		res = WaitForSingleObject(cond->event, ms);
255*663afb9bSAndroid Build Coastguard Worker 		EnterCriticalSection(&cond->lock);
256*663afb9bSAndroid Build Coastguard Worker 		if (cond->n_to_wake &&
257*663afb9bSAndroid Build Coastguard Worker 		    cond->generation != generation_at_start) {
258*663afb9bSAndroid Build Coastguard Worker 			--cond->n_to_wake;
259*663afb9bSAndroid Build Coastguard Worker 			--cond->n_waiting;
260*663afb9bSAndroid Build Coastguard Worker 			result = 0;
261*663afb9bSAndroid Build Coastguard Worker 			waiting = 0;
262*663afb9bSAndroid Build Coastguard Worker 			goto out;
263*663afb9bSAndroid Build Coastguard Worker 		} else if (res != WAIT_OBJECT_0) {
264*663afb9bSAndroid Build Coastguard Worker 			result = (res==WAIT_TIMEOUT) ? 1 : -1;
265*663afb9bSAndroid Build Coastguard Worker 			--cond->n_waiting;
266*663afb9bSAndroid Build Coastguard Worker 			waiting = 0;
267*663afb9bSAndroid Build Coastguard Worker 			goto out;
268*663afb9bSAndroid Build Coastguard Worker 		} else if (ms != INFINITE) {
269*663afb9bSAndroid Build Coastguard Worker 			endTime = GetTickCount();
270*663afb9bSAndroid Build Coastguard Worker 			if (startTime + ms_orig <= endTime) {
271*663afb9bSAndroid Build Coastguard Worker 				result = 1; /* Timeout */
272*663afb9bSAndroid Build Coastguard Worker 				--cond->n_waiting;
273*663afb9bSAndroid Build Coastguard Worker 				waiting = 0;
274*663afb9bSAndroid Build Coastguard Worker 				goto out;
275*663afb9bSAndroid Build Coastguard Worker 			} else {
276*663afb9bSAndroid Build Coastguard Worker 				ms = startTime + ms_orig - endTime;
277*663afb9bSAndroid Build Coastguard Worker 			}
278*663afb9bSAndroid Build Coastguard Worker 		}
279*663afb9bSAndroid Build Coastguard Worker 		/* If we make it here, we are still waiting. */
280*663afb9bSAndroid Build Coastguard Worker 		if (cond->n_to_wake == 0) {
281*663afb9bSAndroid Build Coastguard Worker 			/* There is nobody else who should wake up; reset
282*663afb9bSAndroid Build Coastguard Worker 			 * the event. */
283*663afb9bSAndroid Build Coastguard Worker 			ResetEvent(cond->event);
284*663afb9bSAndroid Build Coastguard Worker 		}
285*663afb9bSAndroid Build Coastguard Worker 	out:
286*663afb9bSAndroid Build Coastguard Worker 		LeaveCriticalSection(&cond->lock);
287*663afb9bSAndroid Build Coastguard Worker 	} while (waiting);
288*663afb9bSAndroid Build Coastguard Worker 
289*663afb9bSAndroid Build Coastguard Worker 	EnterCriticalSection(lock);
290*663afb9bSAndroid Build Coastguard Worker 
291*663afb9bSAndroid Build Coastguard Worker 	EnterCriticalSection(&cond->lock);
292*663afb9bSAndroid Build Coastguard Worker 	if (!cond->n_waiting)
293*663afb9bSAndroid Build Coastguard Worker 		ResetEvent(cond->event);
294*663afb9bSAndroid Build Coastguard Worker 	LeaveCriticalSection(&cond->lock);
295*663afb9bSAndroid Build Coastguard Worker 
296*663afb9bSAndroid Build Coastguard Worker 	return result;
297*663afb9bSAndroid Build Coastguard Worker }
298*663afb9bSAndroid Build Coastguard Worker 
299*663afb9bSAndroid Build Coastguard Worker int
evthread_use_windows_threads(void)300*663afb9bSAndroid Build Coastguard Worker evthread_use_windows_threads(void)
301*663afb9bSAndroid Build Coastguard Worker {
302*663afb9bSAndroid Build Coastguard Worker 	struct evthread_lock_callbacks cbs = {
303*663afb9bSAndroid Build Coastguard Worker 		EVTHREAD_LOCK_API_VERSION,
304*663afb9bSAndroid Build Coastguard Worker 		EVTHREAD_LOCKTYPE_RECURSIVE,
305*663afb9bSAndroid Build Coastguard Worker 		evthread_win32_lock_create,
306*663afb9bSAndroid Build Coastguard Worker 		evthread_win32_lock_free,
307*663afb9bSAndroid Build Coastguard Worker 		evthread_win32_lock,
308*663afb9bSAndroid Build Coastguard Worker 		evthread_win32_unlock
309*663afb9bSAndroid Build Coastguard Worker 	};
310*663afb9bSAndroid Build Coastguard Worker 
311*663afb9bSAndroid Build Coastguard Worker 
312*663afb9bSAndroid Build Coastguard Worker 	struct evthread_condition_callbacks cond_cbs = {
313*663afb9bSAndroid Build Coastguard Worker 		EVTHREAD_CONDITION_API_VERSION,
314*663afb9bSAndroid Build Coastguard Worker 		evthread_win32_cond_alloc,
315*663afb9bSAndroid Build Coastguard Worker 		evthread_win32_cond_free,
316*663afb9bSAndroid Build Coastguard Worker 		evthread_win32_cond_signal,
317*663afb9bSAndroid Build Coastguard Worker 		evthread_win32_cond_wait
318*663afb9bSAndroid Build Coastguard Worker 	};
319*663afb9bSAndroid Build Coastguard Worker #ifdef WIN32_HAVE_CONDITION_VARIABLES
320*663afb9bSAndroid Build Coastguard Worker 	struct evthread_condition_callbacks condvar_cbs = {
321*663afb9bSAndroid Build Coastguard Worker 		EVTHREAD_CONDITION_API_VERSION,
322*663afb9bSAndroid Build Coastguard Worker 		evthread_win32_condvar_alloc,
323*663afb9bSAndroid Build Coastguard Worker 		evthread_win32_condvar_free,
324*663afb9bSAndroid Build Coastguard Worker 		evthread_win32_condvar_signal,
325*663afb9bSAndroid Build Coastguard Worker 		evthread_win32_condvar_wait
326*663afb9bSAndroid Build Coastguard Worker 	};
327*663afb9bSAndroid Build Coastguard Worker #endif
328*663afb9bSAndroid Build Coastguard Worker 
329*663afb9bSAndroid Build Coastguard Worker 	evthread_set_lock_callbacks(&cbs);
330*663afb9bSAndroid Build Coastguard Worker 	evthread_set_id_callback(evthread_win32_get_id);
331*663afb9bSAndroid Build Coastguard Worker #ifdef WIN32_HAVE_CONDITION_VARIABLES
332*663afb9bSAndroid Build Coastguard Worker 	if (evthread_win32_condvar_init()) {
333*663afb9bSAndroid Build Coastguard Worker 		evthread_set_condition_callbacks(&condvar_cbs);
334*663afb9bSAndroid Build Coastguard Worker 		return 0;
335*663afb9bSAndroid Build Coastguard Worker 	}
336*663afb9bSAndroid Build Coastguard Worker #endif
337*663afb9bSAndroid Build Coastguard Worker 	evthread_set_condition_callbacks(&cond_cbs);
338*663afb9bSAndroid Build Coastguard Worker 
339*663afb9bSAndroid Build Coastguard Worker 	return 0;
340*663afb9bSAndroid Build Coastguard Worker }
341*663afb9bSAndroid Build Coastguard Worker 
342