compat_winthreads.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /* Copyright (c) 2003-2004, Roger Dingledine
  2. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  3. * Copyright (c) 2007-2015, The Tor Project, Inc. */
  4. /* See LICENSE for licensing information */
  5. #include "compat.h"
  6. #include <windows.h>
  7. #include <process.h>
  8. #include "util.h"
  9. #include "container.h"
  10. #include "torlog.h"
  11. /** Minimalist interface to run a void function in the background. On
  12. * Unix calls fork, on win32 calls beginthread. Returns -1 on failure.
  13. * func should not return, but rather should call spawn_exit.
  14. *
  15. * NOTE: if <b>data</b> is used, it should not be allocated on the stack,
  16. * since in a multithreaded environment, there is no way to be sure that
  17. * the caller's stack will still be around when the called function is
  18. * running.
  19. */
  20. int
  21. spawn_func(void (*func)(void *), void *data)
  22. {
  23. int rv;
  24. rv = (int)_beginthread(func, 0, data);
  25. if (rv == (int)-1)
  26. return -1;
  27. return 0;
  28. }
  29. /** End the current thread/process.
  30. */
  31. void
  32. spawn_exit(void)
  33. {
  34. _endthread();
  35. //we should never get here. my compiler thinks that _endthread returns, this
  36. //is an attempt to fool it.
  37. tor_assert(0);
  38. _exit(0);
  39. }
  40. void
  41. tor_mutex_init(tor_mutex_t *m)
  42. {
  43. InitializeCriticalSection(&m->mutex);
  44. }
  45. void
  46. tor_mutex_uninit(tor_mutex_t *m)
  47. {
  48. DeleteCriticalSection(&m->mutex);
  49. }
  50. void
  51. tor_mutex_acquire(tor_mutex_t *m)
  52. {
  53. tor_assert(m);
  54. EnterCriticalSection(&m->mutex);
  55. }
  56. void
  57. tor_mutex_release(tor_mutex_t *m)
  58. {
  59. LeaveCriticalSection(&m->mutex);
  60. }
  61. unsigned long
  62. tor_get_thread_id(void)
  63. {
  64. return (unsigned long)GetCurrentThreadId();
  65. }
  66. static DWORD cond_event_tls_index;
  67. struct tor_cond_t {
  68. CRITICAL_SECTION mutex;
  69. smartlist_t *events;
  70. };
  71. tor_cond_t *
  72. tor_cond_new(void)
  73. {
  74. tor_cond_t *cond = tor_malloc_zero(sizeof(tor_cond_t));
  75. InitializeCriticalSection(&cond->mutex);
  76. cond->events = smartlist_new();
  77. return cond;
  78. }
  79. void
  80. tor_cond_free(tor_cond_t *cond)
  81. {
  82. if (!cond)
  83. return;
  84. DeleteCriticalSection(&cond->mutex);
  85. /* XXXX notify? */
  86. smartlist_free(cond->events);
  87. tor_free(cond);
  88. }
  89. int
  90. tor_cond_wait(tor_cond_t *cond, tor_mutex_t *mutex)
  91. {
  92. HANDLE event;
  93. int r;
  94. tor_assert(cond);
  95. tor_assert(mutex);
  96. event = TlsGetValue(cond_event_tls_index);
  97. if (!event) {
  98. event = CreateEvent(0, FALSE, FALSE, NULL);
  99. TlsSetValue(cond_event_tls_index, event);
  100. }
  101. EnterCriticalSection(&cond->mutex);
  102. tor_assert(WaitForSingleObject(event, 0) == WAIT_TIMEOUT);
  103. tor_assert(!smartlist_contains(cond->events, event));
  104. smartlist_add(cond->events, event);
  105. LeaveCriticalSection(&cond->mutex);
  106. tor_mutex_release(mutex);
  107. r = WaitForSingleObject(event, INFINITE);
  108. tor_mutex_acquire(mutex);
  109. switch (r) {
  110. case WAIT_OBJECT_0: /* we got the mutex normally. */
  111. break;
  112. case WAIT_ABANDONED: /* holding thread exited. */
  113. case WAIT_TIMEOUT: /* Should never happen. */
  114. tor_assert(0);
  115. break;
  116. case WAIT_FAILED:
  117. log_warn(LD_GENERAL, "Failed to acquire mutex: %d",(int) GetLastError());
  118. }
  119. return 0;
  120. }
  121. void
  122. tor_cond_signal_one(tor_cond_t *cond)
  123. {
  124. HANDLE event;
  125. tor_assert(cond);
  126. EnterCriticalSection(&cond->mutex);
  127. if ((event = smartlist_pop_last(cond->events)))
  128. SetEvent(event);
  129. LeaveCriticalSection(&cond->mutex);
  130. }
  131. void
  132. tor_cond_signal_all(tor_cond_t *cond)
  133. {
  134. tor_assert(cond);
  135. EnterCriticalSection(&cond->mutex);
  136. SMARTLIST_FOREACH(cond->events, HANDLE, event, SetEvent(event));
  137. smartlist_clear(cond->events);
  138. LeaveCriticalSection(&cond->mutex);
  139. }
  140. void
  141. tor_threads_init(void)
  142. {
  143. cond_event_tls_index = TlsAlloc();
  144. set_main_thread();
  145. }