compat_pthreads.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. /* Copyright (c) 2003-2004, Roger Dingledine
  2. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
  3. * Copyright (c) 2007-2018, The Tor Project, Inc. */
  4. /* See LICENSE for licensing information */
  5. /**
  6. * \file compat_pthreads.c
  7. *
  8. * \brief Implementation for the pthreads-based multithreading backend
  9. * functions.
  10. */
  11. #include "orconfig.h"
  12. #include "lib/thread/threads.h"
  13. #include "lib/wallclock/timeval.h"
  14. #include "lib/log/log.h"
  15. #include "lib/log/util_bug.h"
  16. #include <sys/time.h>
  17. #include <pthread.h>
  18. #include <signal.h>
  19. #include <time.h>
  20. #include <errno.h>
  21. #include <string.h>
  22. /** Wraps a void (*)(void*) function and its argument so we can
  23. * invoke them in a way pthreads would expect.
  24. */
  25. typedef struct tor_pthread_data_t {
  26. void (*func)(void *);
  27. void *data;
  28. } tor_pthread_data_t;
  29. /** Given a tor_pthread_data_t <b>_data</b>, call _data-&gt;func(d-&gt;data)
  30. * and free _data. Used to make sure we can call functions the way pthread
  31. * expects. */
  32. static void *
  33. tor_pthread_helper_fn(void *_data)
  34. {
  35. tor_pthread_data_t *data = _data;
  36. void (*func)(void*);
  37. void *arg;
  38. /* mask signals to worker threads to avoid SIGPIPE, etc */
  39. sigset_t sigs;
  40. /* We're in a subthread; don't handle any signals here. */
  41. sigfillset(&sigs);
  42. pthread_sigmask(SIG_SETMASK, &sigs, NULL);
  43. func = data->func;
  44. arg = data->data;
  45. tor_free(_data);
  46. func(arg);
  47. return NULL;
  48. }
  49. /**
  50. * A pthread attribute to make threads start detached.
  51. */
  52. static pthread_attr_t attr_detached;
  53. /** True iff we've called tor_threads_init() */
  54. static int threads_initialized = 0;
  55. /** Minimalist interface to run a void function in the background. On
  56. * Unix calls pthread_create, on win32 calls beginthread. Returns -1 on
  57. * failure.
  58. * func should not return, but rather should call spawn_exit.
  59. *
  60. * NOTE: if <b>data</b> is used, it should not be allocated on the stack,
  61. * since in a multithreaded environment, there is no way to be sure that
  62. * the caller's stack will still be around when the called function is
  63. * running.
  64. */
  65. int
  66. spawn_func(void (*func)(void *), void *data)
  67. {
  68. pthread_t thread;
  69. tor_pthread_data_t *d;
  70. if (PREDICT_UNLIKELY(!threads_initialized)) {
  71. tor_threads_init();
  72. }
  73. d = tor_malloc(sizeof(tor_pthread_data_t));
  74. d->data = data;
  75. d->func = func;
  76. if (pthread_create(&thread, &attr_detached, tor_pthread_helper_fn, d)) {
  77. tor_free(d);
  78. return -1;
  79. }
  80. return 0;
  81. }
  82. /** End the current thread/process.
  83. */
  84. void
  85. spawn_exit(void)
  86. {
  87. pthread_exit(NULL);
  88. }
  89. /** Return an integer representing this thread. */
  90. unsigned long
  91. tor_get_thread_id(void)
  92. {
  93. union {
  94. pthread_t thr;
  95. unsigned long id;
  96. } r;
  97. r.thr = pthread_self();
  98. return r.id;
  99. }
  100. /* Conditions. */
  101. /** Initialize an already-allocated condition variable. */
  102. int
  103. tor_cond_init(tor_cond_t *cond)
  104. {
  105. pthread_condattr_t condattr;
  106. memset(cond, 0, sizeof(tor_cond_t));
  107. /* Default condition attribute. Might be used if clock monotonic is
  108. * available else this won't affect anything. */
  109. if (pthread_condattr_init(&condattr)) {
  110. return -1;
  111. }
  112. #if defined(HAVE_CLOCK_GETTIME)
  113. #if defined(HAVE_PTHREAD_CONDATTR_SETCLOCK) && \
  114. defined(CLOCK_MONOTONIC)
  115. /* Use monotonic time so when we timedwait() on it, any clock adjustment
  116. * won't affect the timeout value. */
  117. if (pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC)) {
  118. return -1;
  119. }
  120. #define USE_COND_CLOCK CLOCK_MONOTONIC
  121. #else /* !(defined(HAVE_PTHREAD_CONDATTR_SETCLOCK) && ...) */
  122. /* On OSX Sierra, there is no pthread_condattr_setclock, so we are stuck
  123. * with the realtime clock.
  124. */
  125. #define USE_COND_CLOCK CLOCK_REALTIME
  126. #endif /* defined(HAVE_PTHREAD_CONDATTR_SETCLOCK) && ... */
  127. #endif /* defined(HAVE_CLOCK_GETTIME) */
  128. if (pthread_cond_init(&cond->cond, &condattr)) {
  129. return -1;
  130. }
  131. return 0;
  132. }
  133. /** Release all resources held by <b>cond</b>, but do not free <b>cond</b>
  134. * itself. */
  135. void
  136. tor_cond_uninit(tor_cond_t *cond)
  137. {
  138. if (pthread_cond_destroy(&cond->cond)) {
  139. // LCOV_EXCL_START
  140. log_warn(LD_GENERAL,"Error freeing condition: %s", strerror(errno));
  141. return;
  142. // LCOV_EXCL_STOP
  143. }
  144. }
  145. /** Wait until one of the tor_cond_signal functions is called on <b>cond</b>.
  146. * (If <b>tv</b> is set, and that amount of time passes with no signal to
  147. * <b>cond</b>, return anyway. All waiters on the condition must wait holding
  148. * the same <b>mutex</b>. All signallers should hold that mutex. The mutex
  149. * needs to have been allocated with tor_mutex_init_for_cond().
  150. *
  151. * Returns 0 on success, -1 on failure, 1 on timeout. */
  152. int
  153. tor_cond_wait(tor_cond_t *cond, tor_mutex_t *mutex, const struct timeval *tv)
  154. {
  155. int r;
  156. if (tv == NULL) {
  157. while (1) {
  158. r = pthread_cond_wait(&cond->cond, &mutex->mutex);
  159. if (r == EINTR) {
  160. /* EINTR should be impossible according to POSIX, but POSIX, like the
  161. * Pirate's Code, is apparently treated "more like what you'd call
  162. * guidelines than actual rules." */
  163. continue; // LCOV_EXCL_LINE
  164. }
  165. return r ? -1 : 0;
  166. }
  167. } else {
  168. struct timeval tvnow, tvsum;
  169. struct timespec ts;
  170. while (1) {
  171. #if defined(HAVE_CLOCK_GETTIME) && defined(USE_COND_CLOCK)
  172. if (clock_gettime(USE_COND_CLOCK, &ts) < 0) {
  173. return -1;
  174. }
  175. tvnow.tv_sec = ts.tv_sec;
  176. tvnow.tv_usec = (int)(ts.tv_nsec / 1000);
  177. timeradd(tv, &tvnow, &tvsum);
  178. #else /* !(defined(HAVE_CLOCK_GETTIME) && defined(USE_COND_CLOCK)) */
  179. if (gettimeofday(&tvnow, NULL) < 0)
  180. return -1;
  181. timeradd(tv, &tvnow, &tvsum);
  182. #endif /* defined(HAVE_CLOCK_GETTIME) && defined(USE_COND_CLOCK) */
  183. ts.tv_sec = tvsum.tv_sec;
  184. ts.tv_nsec = tvsum.tv_usec * 1000;
  185. r = pthread_cond_timedwait(&cond->cond, &mutex->mutex, &ts);
  186. if (r == 0)
  187. return 0;
  188. else if (r == ETIMEDOUT)
  189. return 1;
  190. else if (r == EINTR)
  191. continue;
  192. else
  193. return -1;
  194. }
  195. }
  196. }
  197. /** Wake up one of the waiters on <b>cond</b>. */
  198. void
  199. tor_cond_signal_one(tor_cond_t *cond)
  200. {
  201. pthread_cond_signal(&cond->cond);
  202. }
  203. /** Wake up all of the waiters on <b>cond</b>. */
  204. void
  205. tor_cond_signal_all(tor_cond_t *cond)
  206. {
  207. pthread_cond_broadcast(&cond->cond);
  208. }
  209. int
  210. tor_threadlocal_init(tor_threadlocal_t *threadlocal)
  211. {
  212. int err = pthread_key_create(&threadlocal->key, NULL);
  213. return err ? -1 : 0;
  214. }
  215. void
  216. tor_threadlocal_destroy(tor_threadlocal_t *threadlocal)
  217. {
  218. pthread_key_delete(threadlocal->key);
  219. memset(threadlocal, 0, sizeof(tor_threadlocal_t));
  220. }
  221. void *
  222. tor_threadlocal_get(tor_threadlocal_t *threadlocal)
  223. {
  224. return pthread_getspecific(threadlocal->key);
  225. }
  226. void
  227. tor_threadlocal_set(tor_threadlocal_t *threadlocal, void *value)
  228. {
  229. int err = pthread_setspecific(threadlocal->key, value);
  230. tor_assert(err == 0);
  231. }
  232. /** Set up common structures for use by threading. */
  233. void
  234. tor_threads_init(void)
  235. {
  236. if (!threads_initialized) {
  237. tor_locking_init();
  238. const int ret1 = pthread_attr_init(&attr_detached);
  239. tor_assert(ret1 == 0);
  240. #ifndef PTHREAD_CREATE_DETACHED
  241. #define PTHREAD_CREATE_DETACHED 1
  242. #endif
  243. const int ret2 =
  244. pthread_attr_setdetachstate(&attr_detached, PTHREAD_CREATE_DETACHED);
  245. tor_assert(ret2 == 0);
  246. threads_initialized = 1;
  247. set_main_thread();
  248. }
  249. }