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 */
17 /** Wraps a void (*)(void*) function and its argument so we can
18 * invoke them in a way pthreads would expect.
20 typedef struct tor_pthread_data_t
{
24 /** Given a tor_pthread_data_t <b>_data</b>, call _data->func(d->data)
25 * and free _data. Used to make sure we can call functions the way pthread
28 tor_pthread_helper_fn(void *_data
)
30 tor_pthread_data_t
*data
= _data
;
33 /* mask signals to worker threads to avoid SIGPIPE, etc */
35 /* We're in a subthread; don't handle any signals here. */
37 pthread_sigmask(SIG_SETMASK
, &sigs
, NULL
);
46 * A pthread attribute to make threads start detached.
48 static pthread_attr_t attr_detached
;
49 /** True iff we've called tor_threads_init() */
50 static int threads_initialized
= 0;
52 /** Minimalist interface to run a void function in the background. On
53 * Unix calls fork, on win32 calls beginthread. Returns -1 on failure.
54 * func should not return, but rather should call spawn_exit.
56 * NOTE: if <b>data</b> is used, it should not be allocated on the stack,
57 * since in a multithreaded environment, there is no way to be sure that
58 * the caller's stack will still be around when the called function is
62 spawn_func(void (*func
)(void *), void *data
)
65 tor_pthread_data_t
*d
;
66 if (PREDICT_UNLIKELY(!threads_initialized
))
68 d
= tor_malloc(sizeof(tor_pthread_data_t
));
71 if (pthread_create(&thread
,&attr_detached
,tor_pthread_helper_fn
,d
))
76 /** End the current thread/process.
84 /** A mutex attribute that we're going to use to tell pthreads that we want
85 * "recursive" mutexes (i.e., once we can re-lock if we're already holding
87 static pthread_mutexattr_t attr_recursive
;
89 /** Initialize <b>mutex</b> so it can be locked. Every mutex must be set
90 * up with tor_mutex_init() or tor_mutex_new(); not both. */
92 tor_mutex_init(tor_mutex_t
*mutex
)
95 if (PREDICT_UNLIKELY(!threads_initialized
))
97 err
= pthread_mutex_init(&mutex
->mutex
, &attr_recursive
);
98 if (PREDICT_UNLIKELY(err
)) {
99 log_err(LD_GENERAL
, "Error %d creating a mutex.", err
);
100 tor_fragile_assert();
104 /** As tor_mutex_init, but initialize a mutex suitable that may be
105 * non-recursive, if the OS supports that. */
107 tor_mutex_init_nonrecursive(tor_mutex_t
*mutex
)
110 if (PREDICT_UNLIKELY(!threads_initialized
))
112 err
= pthread_mutex_init(&mutex
->mutex
, NULL
);
113 if (PREDICT_UNLIKELY(err
)) {
114 log_err(LD_GENERAL
, "Error %d creating a mutex.", err
);
115 tor_fragile_assert();
119 /** Wait until <b>m</b> is free, then acquire it. */
121 tor_mutex_acquire(tor_mutex_t
*m
)
125 err
= pthread_mutex_lock(&m
->mutex
);
126 if (PREDICT_UNLIKELY(err
)) {
127 log_err(LD_GENERAL
, "Error %d locking a mutex.", err
);
128 tor_fragile_assert();
131 /** Release the lock <b>m</b> so another thread can have it. */
133 tor_mutex_release(tor_mutex_t
*m
)
137 err
= pthread_mutex_unlock(&m
->mutex
);
138 if (PREDICT_UNLIKELY(err
)) {
139 log_err(LD_GENERAL
, "Error %d unlocking a mutex.", err
);
140 tor_fragile_assert();
143 /** Clean up the mutex <b>m</b> so that it no longer uses any system
144 * resources. Does not free <b>m</b>. This function must only be called on
145 * mutexes from tor_mutex_init(). */
147 tor_mutex_uninit(tor_mutex_t
*m
)
151 err
= pthread_mutex_destroy(&m
->mutex
);
152 if (PREDICT_UNLIKELY(err
)) {
153 log_err(LD_GENERAL
, "Error %d destroying a mutex.", err
);
154 tor_fragile_assert();
157 /** Return an integer representing this thread. */
159 tor_get_thread_id(void)
165 r
.thr
= pthread_self();
171 /** Initialize an already-allocated condition variable. */
173 tor_cond_init(tor_cond_t
*cond
)
175 pthread_condattr_t condattr
;
177 memset(cond
, 0, sizeof(tor_cond_t
));
178 /* Default condition attribute. Might be used if clock monotonic is
179 * available else this won't affect anything. */
180 if (pthread_condattr_init(&condattr
)) {
184 #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
185 /* Use monotonic time so when we timedwait() on it, any clock adjustment
186 * won't affect the timeout value. */
187 if (pthread_condattr_setclock(&condattr
, CLOCK_MONOTONIC
)) {
191 if (pthread_cond_init(&cond
->cond
, &condattr
)) {
197 /** Release all resources held by <b>cond</b>, but do not free <b>cond</b>
200 tor_cond_uninit(tor_cond_t
*cond
)
202 if (pthread_cond_destroy(&cond
->cond
)) {
203 log_warn(LD_GENERAL
,"Error freeing condition: %s", strerror(errno
));
207 /** Wait until one of the tor_cond_signal functions is called on <b>cond</b>.
208 * (If <b>tv</b> is set, and that amount of time passes with no signal to
209 * <b>cond</b>, return anyway. All waiters on the condition must wait holding
210 * the same <b>mutex</b>. All signallers should hold that mutex. The mutex
211 * needs to have been allocated with tor_mutex_init_for_cond().
213 * Returns 0 on success, -1 on failure, 1 on timeout. */
215 tor_cond_wait(tor_cond_t
*cond
, tor_mutex_t
*mutex
, const struct timeval
*tv
)
220 r
= pthread_cond_wait(&cond
->cond
, &mutex
->mutex
);
222 /* EINTR should be impossible according to POSIX, but POSIX, like the
223 * Pirate's Code, is apparently treated "more like what you'd call
224 * guidelines than actual rules." */
230 struct timeval tvnow
, tvsum
;
233 #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
234 if (clock_gettime(CLOCK_MONOTONIC
, &ts
) < 0) {
237 tvnow
.tv_sec
= ts
.tv_sec
;
238 tvnow
.tv_usec
= ts
.tv_nsec
/ 1000;
239 timeradd(tv
, &tvnow
, &tvsum
);
241 if (gettimeofday(&tvnow
, NULL
) < 0)
243 timeradd(tv
, &tvnow
, &tvsum
);
244 #endif /* HAVE_CLOCK_GETTIME, CLOCK_MONOTONIC */
246 ts
.tv_sec
= tvsum
.tv_sec
;
247 ts
.tv_nsec
= tvsum
.tv_usec
* 1000;
249 r
= pthread_cond_timedwait(&cond
->cond
, &mutex
->mutex
, &ts
);
252 else if (r
== ETIMEDOUT
)
261 /** Wake up one of the waiters on <b>cond</b>. */
263 tor_cond_signal_one(tor_cond_t
*cond
)
265 pthread_cond_signal(&cond
->cond
);
267 /** Wake up all of the waiters on <b>cond</b>. */
269 tor_cond_signal_all(tor_cond_t
*cond
)
271 pthread_cond_broadcast(&cond
->cond
);
274 /** Set up common structures for use by threading. */
276 tor_threads_init(void)
278 if (!threads_initialized
) {
280 pthread_mutexattr_init(&attr_recursive
);
281 pthread_mutexattr_settype(&attr_recursive
, PTHREAD_MUTEX_RECURSIVE
);
282 ret
= pthread_attr_init(&attr_detached
);
283 tor_assert(ret
== 0);
284 #ifndef PTHREAD_CREATE_DETACHED
285 #define PTHREAD_CREATE_DETACHED 1
287 ret
= pthread_attr_setdetachstate(&attr_detached
, PTHREAD_CREATE_DETACHED
);
288 tor_assert(ret
== 0);
289 threads_initialized
= 1;