Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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