Tor  0.4.4.0-alpha-dev
threads.h
Go to the documentation of this file.
1 /* Copyright (c) 2003-2004, Roger Dingledine
2  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3  * Copyright (c) 2007-2020, The Tor Project, Inc. */
4 /* See LICENSE for licensing information */
5 
6 /**
7  * \file threads.h
8  * \brief Header for threads.c
9  **/
10 
11 #ifndef TOR_COMPAT_THREADS_H
12 #define TOR_COMPAT_THREADS_H
13 
14 #include "orconfig.h"
15 #include "lib/cc/torint.h"
17 #include "lib/lock/compat_mutex.h"
18 
19 #if defined(HAVE_STDATOMIC_H) && defined(STDATOMIC_WORKS)
20 #define HAVE_WORKING_STDATOMIC
21 #endif
22 
23 #ifdef HAVE_WORKING_STDATOMIC
24 #include <stdatomic.h>
25 #endif
26 
27 struct timeval;
28 
29 int spawn_func(void (*func)(void *), void *data);
30 void spawn_exit(void) ATTR_NORETURN;
31 
32 unsigned long tor_get_thread_id(void);
33 void tor_threads_init(void);
34 
35 /** Conditions need nonrecursive mutexes with pthreads. */
36 #define tor_mutex_init_for_cond(m) tor_mutex_init_nonrecursive(m)
37 
38 void set_main_thread(void);
39 int in_main_thread(void);
40 
41 typedef struct tor_cond_t {
42 #ifdef USE_PTHREADS
43  pthread_cond_t cond;
44 #elif defined(USE_WIN32_THREADS)
45  HANDLE event;
46 
47  CRITICAL_SECTION lock;
48  int n_waiting;
49  int n_to_wake;
50  int generation;
51 #else
52 #error no known condition implementation.
53 #endif /* defined(USE_PTHREADS) || ... */
54 } tor_cond_t;
55 
57 void tor_cond_free_(tor_cond_t *cond);
58 #define tor_cond_free(c) FREE_AND_NULL(tor_cond_t, tor_cond_free_, (c))
59 int tor_cond_init(tor_cond_t *cond);
60 void tor_cond_uninit(tor_cond_t *cond);
61 int tor_cond_wait(tor_cond_t *cond, tor_mutex_t *mutex,
62  const struct timeval *tv);
65 
66 typedef struct tor_threadlocal_t {
67 #ifdef _WIN32
68  DWORD index;
69 #else
70  pthread_key_t key;
71 #endif
73 
74 /** Initialize a thread-local variable.
75  *
76  * After you call this function on a tor_threadlocal_t, you can call
77  * tor_threadlocal_set to change the current value of this variable for the
78  * current thread, and tor_threadlocal_get to retrieve the current value for
79  * the current thread. Each thread has its own value.
80  **/
81 int tor_threadlocal_init(tor_threadlocal_t *threadlocal);
82 /**
83  * Release all resource associated with a thread-local variable.
84  */
86 /**
87  * Return the current value of a thread-local variable for this thread.
88  *
89  * It's undefined behavior to use this function if the threadlocal hasn't
90  * been initialized, or has been destroyed.
91  */
92 void *tor_threadlocal_get(tor_threadlocal_t *threadlocal);
93 /**
94  * Change the current value of a thread-local variable for this thread to
95  * <b>value</b>.
96  *
97  * It's undefined behavior to use this function if the threadlocal hasn't
98  * been initialized, or has been destroyed.
99  */
100 void tor_threadlocal_set(tor_threadlocal_t *threadlocal, void *value);
101 
102 /**
103  * Atomic counter type; holds a size_t value.
104  */
105 #ifdef HAVE_WORKING_STDATOMIC
106 typedef struct atomic_counter_t {
107  atomic_size_t val;
109 #ifndef COCCI
110 #define ATOMIC_LINKAGE static
111 #endif
112 #else /* !defined(HAVE_WORKING_STDATOMIC) */
113 typedef struct atomic_counter_t {
114  tor_mutex_t mutex;
115  size_t val;
117 #define ATOMIC_LINKAGE
118 #endif /* defined(HAVE_WORKING_STDATOMIC) */
119 
120 ATOMIC_LINKAGE void atomic_counter_init(atomic_counter_t *counter);
121 ATOMIC_LINKAGE void atomic_counter_destroy(atomic_counter_t *counter);
122 ATOMIC_LINKAGE void atomic_counter_add(atomic_counter_t *counter, size_t add);
123 ATOMIC_LINKAGE void atomic_counter_sub(atomic_counter_t *counter, size_t sub);
124 ATOMIC_LINKAGE size_t atomic_counter_get(atomic_counter_t *counter);
125 ATOMIC_LINKAGE size_t atomic_counter_exchange(atomic_counter_t *counter,
126  size_t newval);
127 #undef ATOMIC_LINKAGE
128 
129 #ifdef HAVE_WORKING_STDATOMIC
130 /** Initialize a new atomic counter with the value 0 */
131 static inline void
133 {
134  atomic_init(&counter->val, 0);
135 }
136 /** Clean up all resources held by an atomic counter.
137  *
138  * This usage note applies to the compat_threads implementation of
139  * atomic_counter_destroy():
140  * Destroying a locked mutex is undefined behaviour. Global mutexes may be
141  * locked when they are passed to this function, because multiple threads can
142  * still access them. So we can either:
143  * - destroy on shutdown, and re-initialise when tor re-initialises, or
144  * - skip destroying and re-initialisation, using a sentinel variable.
145  * See #31735 for details.
146  */
147 static inline void
149 {
150  (void)counter;
151 }
152 /** Add a value to an atomic counter. */
153 static inline void
154 atomic_counter_add(atomic_counter_t *counter, size_t add)
155 {
156  (void) atomic_fetch_add(&counter->val, add);
157 }
158 /** Subtract a value from an atomic counter. */
159 static inline void
160 atomic_counter_sub(atomic_counter_t *counter, size_t sub)
161 {
162  (void) atomic_fetch_sub(&counter->val, sub);
163 }
164 /** Return the current value of an atomic counter */
165 static inline size_t
167 {
168  return atomic_load(&counter->val);
169 }
170 /** Replace the value of an atomic counter; return the old one. */
171 static inline size_t
172 atomic_counter_exchange(atomic_counter_t *counter, size_t newval)
173 {
174  return atomic_exchange(&counter->val, newval);
175 }
176 
177 #else /* !defined(HAVE_WORKING_STDATOMIC) */
178 #endif /* defined(HAVE_WORKING_STDATOMIC) */
179 
180 #endif /* !defined(TOR_COMPAT_THREADS_H) */
tor_cond_free_
void tor_cond_free_(tor_cond_t *cond)
Definition: compat_threads.c:37
atomic_counter_init
ATOMIC_LINKAGE void atomic_counter_init(atomic_counter_t *counter)
Definition: compat_threads.c:65
atomic_counter_destroy
ATOMIC_LINKAGE void atomic_counter_destroy(atomic_counter_t *counter)
Definition: compat_threads.c:80
tor_cond_signal_one
void tor_cond_signal_one(tor_cond_t *cond)
Definition: compat_pthreads.c:215
tor_cond_signal_all
void tor_cond_signal_all(tor_cond_t *cond)
Definition: compat_pthreads.c:221
torint.h
Integer definitions used throughout Tor.
tor_cond_uninit
void tor_cond_uninit(tor_cond_t *cond)
Definition: compat_pthreads.c:150
tor_threadlocal_destroy
void tor_threadlocal_destroy(tor_threadlocal_t *threadlocal)
Definition: compat_pthreads.c:234
tor_threads_init
void tor_threads_init(void)
Definition: compat_pthreads.c:255
tor_threadlocal_set
void tor_threadlocal_set(tor_threadlocal_t *threadlocal, void *value)
Definition: compat_pthreads.c:247
tor_mutex_t
Definition: compat_mutex.h:40
tor_cond_init
int tor_cond_init(tor_cond_t *cond)
Definition: compat_pthreads.c:114
tor_threadlocal_init
int tor_threadlocal_init(tor_threadlocal_t *threadlocal)
Definition: compat_pthreads.c:227
atomic_counter_get
ATOMIC_LINKAGE size_t atomic_counter_get(atomic_counter_t *counter)
Definition: compat_threads.c:102
tor_threadlocal_get
void * tor_threadlocal_get(tor_threadlocal_t *threadlocal)
Definition: compat_pthreads.c:241
tor_threadlocal_t
Definition: threads.h:66
set_main_thread
void set_main_thread(void)
Definition: compat_threads.c:51
tor_get_thread_id
unsigned long tor_get_thread_id(void)
Definition: compat_pthreads.c:100
atomic_counter_add
ATOMIC_LINKAGE void atomic_counter_add(atomic_counter_t *counter, size_t add)
Definition: compat_threads.c:87
spawn_exit
void spawn_exit(void) ATTR_NORETURN
Definition: compat_pthreads.c:93
in_main_thread
int in_main_thread(void)
Definition: compat_threads.c:57
tor_cond_t
Definition: threads.h:41
spawn_func
int spawn_func(void(*func)(void *), void *data)
Definition: compat_pthreads.c:72
compat_mutex.h
Header for compat_mutex.c.
timeval
Definition: compat_time.h:151
testsupport.h
Macros to implement mocking and selective exposure for the test code.
tor_cond_new
tor_cond_t * tor_cond_new(void)
Definition: compat_threads.c:27
atomic_counter_t
Definition: threads.h:113
atomic_counter_exchange
ATOMIC_LINKAGE size_t atomic_counter_exchange(atomic_counter_t *counter, size_t newval)
Definition: compat_threads.c:112
atomic_counter_sub
ATOMIC_LINKAGE void atomic_counter_sub(atomic_counter_t *counter, size_t sub)
Definition: compat_threads.c:95
tor_cond_wait
int tor_cond_wait(tor_cond_t *cond, tor_mutex_t *mutex, const struct timeval *tv)
Definition: compat_pthreads.c:167