windows: Do not check if having clock_gettime()
[strongswan.git] / src / libstrongswan / threading / windows / thread.c
1 /*
2 * Copyright (C) 2013 Martin Willi
3 * Copyright (C) 2013 revosec AG
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "thread.h"
17
18 #include <utils/debug.h>
19 #include <threading/spinlock.h>
20 #include <threading/thread.h>
21 #include <collections/hashtable.h>
22 #include <collections/array.h>
23
24
25 typedef struct private_thread_t private_thread_t;
26
27 struct private_thread_t {
28
29 /**
30 * Public interface.
31 */
32 thread_t public;
33
34 /**
35 * GetCurrentThreadId() of thread
36 */
37 DWORD id;
38
39 /**
40 * Printable thread id returned by thread_current_id()
41 */
42 u_int tid;
43
44 /**
45 * Windows thread handle
46 */
47 HANDLE handle;
48
49 /**
50 * Main function of this thread (NULL for the main thread).
51 */
52 thread_main_t main;
53
54 /**
55 * Argument for the main function.
56 */
57 void *arg;
58
59 /**
60 * Thread return value
61 */
62 void *ret;
63
64 /**
65 * Stack of cleanup handlers, as cleanup_t
66 */
67 array_t *cleanup;
68
69 /**
70 * Thread specific values for this thread
71 */
72 hashtable_t *tls;
73
74 /**
75 * Thread terminated?
76 */
77 bool terminated;
78
79 /**
80 * Thread detached?
81 */
82 bool detached;
83
84 /**
85 * Is thread in cancellable state
86 */
87 bool cancelability;
88
89 /**
90 * Has the thread been cancelled by thread->cancel()?
91 */
92 bool canceled;
93
94 /**
95 * Did we schedule an APC to docancel()?
96 */
97 bool cancel_pending;
98
99 /**
100 * Active condition variable thread is waiting in, if any
101 */
102 CONDITION_VARIABLE *condvar;
103 };
104
105 /**
106 * Global list of threads, GetCurrentThreadId() => private_thread_t
107 */
108 static hashtable_t *threads;
109
110 /**
111 * Lock for threads table
112 */
113 static spinlock_t *threads_lock;
114
115 /**
116 * Counter to assign printable thread IDs
117 */
118 static u_int threads_ids = 0;
119
120 /**
121 * Forward declaration
122 */
123 static private_thread_t *create_internal(DWORD id);
124
125 /**
126 * Set leak detective state
127 */
128 static inline bool set_leak_detective(bool state)
129 {
130 #ifdef LEAK_DETECTIVE
131 if (lib && lib->leak_detective)
132 {
133 return lib->leak_detective->set_state(lib->leak_detective, state);
134 }
135 #endif
136 return FALSE;
137 }
138
139 /**
140 * Store thread in index
141 */
142 static void put_thread(private_thread_t *this)
143 {
144 bool old;
145
146 old = set_leak_detective(FALSE);
147 threads_lock->lock(threads_lock);
148
149 this = threads->put(threads, (void*)(uintptr_t)this->id, this);
150
151 threads_lock->unlock(threads_lock);
152 set_leak_detective(old);
153 }
154
155 /**
156 * Remove thread from index
157 */
158 static void remove_thread(private_thread_t *this)
159 {
160 bool old;
161
162 old = set_leak_detective(FALSE);
163 threads_lock->lock(threads_lock);
164
165 threads->remove(threads, (void*)(uintptr_t)this->id);
166
167 threads_lock->unlock(threads_lock);
168 set_leak_detective(old);
169 }
170
171 /**
172 * Get thread data for calling thread
173 */
174 static private_thread_t *get_current_thread()
175 {
176 private_thread_t *this;
177
178 threads_lock->lock(threads_lock);
179
180 this = threads->get(threads, (void*)(uintptr_t)GetCurrentThreadId());
181
182 threads_lock->unlock(threads_lock);
183
184 if (!this)
185 {
186 this = create_internal(GetCurrentThreadId());
187 put_thread(this);
188 }
189
190 return this;
191 }
192
193 /**
194 * See header.
195 */
196 void* thread_tls_put(void *key, void *value)
197 {
198 private_thread_t *thread;
199 bool old;
200
201 thread = get_current_thread();
202
203 old = set_leak_detective(FALSE);
204 value = thread->tls->put(thread->tls, key, value);
205 set_leak_detective(old);
206
207 return value;
208 }
209
210 /**
211 * See header.
212 */
213 void* thread_tls_get(void *key)
214 {
215 private_thread_t *thread;
216 void *value;
217 bool old;
218
219 thread = get_current_thread();
220
221 old = set_leak_detective(FALSE);
222 value = thread->tls->get(thread->tls, key);
223 set_leak_detective(old);
224
225 return value;
226 }
227
228 /**
229 * See header.
230 */
231 void* thread_tls_remove(void *key)
232 {
233 private_thread_t *thread;
234 void *value;
235 bool old;
236
237 thread = get_current_thread();
238
239 old = set_leak_detective(FALSE);
240 threads_lock->lock(threads_lock);
241 value = thread->tls->remove(thread->tls, key);
242 threads_lock->unlock(threads_lock);
243 set_leak_detective(old);
244
245 return value;
246 }
247
248 /**
249 * See header.
250 */
251 void thread_tls_remove_all(void *key)
252 {
253 private_thread_t *thread;
254 enumerator_t *enumerator;
255 void *value;
256 bool old;
257
258 old = set_leak_detective(FALSE);
259 threads_lock->lock(threads_lock);
260
261 enumerator = threads->create_enumerator(threads);
262 while (enumerator->enumerate(enumerator, NULL, &thread))
263 {
264 value = thread->tls->remove(thread->tls, key);
265 if (value)
266 {
267 set_leak_detective(old);
268 thread_tls_cleanup(value);
269 set_leak_detective(FALSE);
270 }
271 }
272 enumerator->destroy(enumerator);
273
274 threads_lock->unlock(threads_lock);
275 set_leak_detective(old);
276 }
277
278 /**
279 * Thread cleanup data
280 */
281 typedef struct {
282 /** Cleanup callback function */
283 thread_cleanup_t cb;
284 /** Argument provided to the cleanup function */
285 void *arg;
286 } cleanup_t;
287
288 /**
289 * Invoke pushed/tls cleanup handlers
290 */
291 static void docleanup(private_thread_t *this)
292 {
293 enumerator_t *enumerator;
294 cleanup_t cleanup, *tls;
295 bool old;
296
297 old = set_leak_detective(FALSE);
298
299 while (array_remove(this->cleanup, -1, &cleanup))
300 {
301 set_leak_detective(old);
302 cleanup.cb(cleanup.arg);
303 set_leak_detective(FALSE);
304 }
305
306 threads_lock->lock(threads_lock);
307 enumerator = this->tls->create_enumerator(this->tls);
308 while (enumerator->enumerate(enumerator, NULL, &tls))
309 {
310 this->tls->remove_at(this->tls, enumerator);
311
312 set_leak_detective(old);
313 thread_tls_cleanup(tls);
314 set_leak_detective(FALSE);
315 }
316 enumerator->destroy(enumerator);
317 threads_lock->unlock(threads_lock);
318
319 set_leak_detective(old);
320 }
321
322 /**
323 * Clean up and destroy a thread
324 */
325 static void destroy(private_thread_t *this)
326 {
327 bool old;
328
329 docleanup(this);
330
331 old = set_leak_detective(FALSE);
332
333 array_destroy(this->cleanup);
334 this->tls->destroy(this->tls);
335 if (this->handle)
336 {
337 CloseHandle(this->handle);
338 }
339 free(this);
340
341 set_leak_detective(old);
342 }
343
344 /**
345 * End a thread, destroy when detached
346 */
347 static void end_thread(private_thread_t *this)
348 {
349 if (this->detached)
350 {
351 remove_thread(this);
352 destroy(this);
353 }
354 else
355 {
356 this->terminated = TRUE;
357 docleanup(this);
358 }
359 }
360
361 /**
362 * See header.
363 */
364 void thread_set_active_condvar(CONDITION_VARIABLE *condvar)
365 {
366 private_thread_t *thread;
367
368 thread = get_current_thread();
369
370 threads_lock->lock(threads_lock);
371 thread->condvar = condvar;
372 threads_lock->unlock(threads_lock);
373
374 /* this is a cancellation point, as condvar wait is one */
375 SleepEx(0, TRUE);
376 }
377
378 /**
379 * APC to cancel a thread
380 */
381 static void docancel(private_thread_t *this)
382 {
383 /* make sure cancel() does not access this anymore */
384 threads_lock->lock(threads_lock);
385 threads_lock->unlock(threads_lock);
386
387 end_thread(this);
388 ExitThread(0);
389 }
390
391 METHOD(thread_t, cancel, void,
392 private_thread_t *this)
393 {
394 this->canceled = TRUE;
395 if (this->cancelability)
396 {
397 threads_lock->lock(threads_lock);
398 if (!this->cancel_pending)
399 {
400 this->cancel_pending = TRUE;
401 QueueUserAPC((void*)docancel, this->handle, (uintptr_t)this);
402 if (this->condvar)
403 {
404 WakeAllConditionVariable(this->condvar);
405 }
406 }
407 threads_lock->unlock(threads_lock);
408 }
409 }
410
411 METHOD(thread_t, kill_, void,
412 private_thread_t *this, int sig)
413 {
414 }
415
416 METHOD(thread_t, detach, void,
417 private_thread_t *this)
418 {
419 this->detached = TRUE;
420 }
421
422 METHOD(thread_t, join, void*,
423 private_thread_t *this)
424 {
425 void *ret;
426
427 if (this->detached)
428 {
429 return NULL;
430 }
431
432 while (!this->terminated)
433 {
434 /* join is a cancellation point, use alertable wait */
435 WaitForSingleObjectEx(this->handle, INFINITE, TRUE);
436 }
437
438 ret = this->ret;
439
440 remove_thread(this);
441 destroy(this);
442
443 return ret;
444 }
445
446 /**
447 * Main function wrapper for threads
448 */
449 static DWORD thread_cb(private_thread_t *this)
450 {
451 /* Enable cancelability once the thread starts. We must check for any
452 * pending cancellation request an queue the APC that gets executed
453 * at the first cancellation point. */
454 this->cancelability = TRUE;
455 if (this->canceled)
456 {
457 cancel(this);
458 }
459
460 this->ret = this->main(this->arg);
461
462 end_thread(this);
463
464 return 0;
465 }
466
467 /**
468 * Create an internal thread object.
469 */
470 static private_thread_t *create_internal(DWORD id)
471 {
472 private_thread_t *this;
473 bool old;
474
475 old = set_leak_detective(FALSE);
476
477 INIT(this,
478 .public = {
479 .cancel = _cancel,
480 .kill = _kill_,
481 .detach = _detach,
482 .join = _join,
483 },
484 .cleanup = array_create(sizeof(cleanup_t), 0),
485 .tls = hashtable_create(hashtable_hash_ptr, hashtable_equals_ptr, 4),
486 .id = id,
487 .cancelability = TRUE,
488 );
489
490 set_leak_detective(old);
491
492 threads_lock->lock(threads_lock);
493 this->tid = threads_ids++;
494 threads_lock->unlock(threads_lock);
495
496 if (id)
497 {
498 this->handle = OpenThread(THREAD_ALL_ACCESS, FALSE, id);
499 }
500 return this;
501 }
502
503 /**
504 * Described in header.
505 */
506 thread_t *thread_create(thread_main_t main, void *arg)
507 {
508 private_thread_t *this;
509
510 this = create_internal(0);
511
512 this->main = main;
513 this->arg = arg;
514 /* not cancellable until started */
515 this->cancelability = FALSE;
516
517 this->handle = CreateThread(NULL, 0, (void*)thread_cb, this,
518 CREATE_SUSPENDED, &this->id);
519 if (!this->handle)
520 {
521 destroy(this);
522 return NULL;
523 }
524
525 put_thread(this);
526
527 DBG2(DBG_LIB, "created thread %u", this->id);
528
529 ResumeThread(this->handle);
530
531 return &this->public;
532 }
533
534 /**
535 * Described in header.
536 */
537 thread_t *thread_current()
538 {
539 return &get_current_thread()->public;
540 }
541
542 /**
543 * Described in header.
544 */
545 u_int thread_current_id()
546 {
547 return get_current_thread()->tid;
548 }
549
550 /**
551 * Described in header.
552 */
553 void thread_cleanup_push(thread_cleanup_t cb, void *arg)
554 {
555 private_thread_t *this;
556 cleanup_t cleanup = {
557 .cb = cb,
558 .arg = arg,
559 };
560 bool old;
561
562 this = get_current_thread();
563
564 old = set_leak_detective(FALSE);
565 array_insert(this->cleanup, -1, &cleanup);
566 set_leak_detective(old);
567 }
568
569 /**
570 * Described in header
571 */
572 void thread_cleanup_pop(bool execute)
573 {
574 private_thread_t *this;
575 cleanup_t cleanup = {};
576 bool old;
577
578 this = get_current_thread();
579
580 old = set_leak_detective(FALSE);
581 array_remove(this->cleanup, -1, &cleanup);
582 set_leak_detective(old);
583
584 if (execute)
585 {
586 cleanup.cb(cleanup.arg);
587 }
588 }
589
590 /**
591 * Described in header.
592 */
593 bool thread_cancelability(bool enable)
594 {
595 private_thread_t *this;
596 bool old;
597
598 this = get_current_thread();
599 old = this->cancelability;
600 this->cancelability = enable;
601
602 if (enable && !old && this->canceled)
603 {
604 cancel(this);
605 }
606 return old;
607 }
608
609 /**
610 * Described in header.
611 */
612 void thread_cancellation_point()
613 {
614 bool old;
615
616 old = thread_cancelability(TRUE);
617 SleepEx(0, TRUE);
618 thread_cancelability(old);
619 }
620
621 /**
622 * Described in header.
623 */
624 void thread_exit(void *val)
625 {
626 private_thread_t *this;
627
628 this = get_current_thread();
629 this->ret = val;
630
631 end_thread(this);
632 ExitThread(0);
633 }
634
635 /*
636 * Described in header.
637 */
638 void threads_init()
639 {
640 threads_lock = spinlock_create();
641 threads = hashtable_create(hashtable_hash_ptr, hashtable_equals_ptr, 4);
642
643 /* reset counter should we initialize more than once */
644 threads_ids = 0;
645
646 put_thread(create_internal(GetCurrentThreadId()));
647 }
648
649 /**
650 * Described in header.
651 */
652 void threads_deinit()
653 {
654 private_thread_t *this;
655
656 this = threads->remove(threads, (void*)(uintptr_t)GetCurrentThreadId());
657 destroy(this);
658
659 threads_lock->destroy(threads_lock);
660 threads->destroy(threads);
661 }