threads.h (5386B)
1 /* Copyright (c) 2003-2004, Roger Dingledine 2 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. 3 * Copyright (c) 2007-2021, 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" 16 #include "lib/testsupport/testsupport.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 CONDITION_VARIABLE cond; 46 #else 47 #error no known condition implementation. 48 #endif /* defined(USE_PTHREADS) || ... */ 49 } tor_cond_t; 50 51 tor_cond_t *tor_cond_new(void); 52 void tor_cond_free_(tor_cond_t *cond); 53 #define tor_cond_free(c) FREE_AND_NULL(tor_cond_t, tor_cond_free_, (c)) 54 int tor_cond_init(tor_cond_t *cond); 55 void tor_cond_uninit(tor_cond_t *cond); 56 int tor_cond_wait(tor_cond_t *cond, tor_mutex_t *mutex, 57 const struct timeval *tv); 58 void tor_cond_signal_one(tor_cond_t *cond); 59 void tor_cond_signal_all(tor_cond_t *cond); 60 61 typedef struct tor_threadlocal_t { 62 #ifdef _WIN32 63 DWORD index; 64 #else 65 pthread_key_t key; 66 #endif 67 } tor_threadlocal_t; 68 69 /** Initialize a thread-local variable. 70 * 71 * After you call this function on a tor_threadlocal_t, you can call 72 * tor_threadlocal_set to change the current value of this variable for the 73 * current thread, and tor_threadlocal_get to retrieve the current value for 74 * the current thread. Each thread has its own value. 75 **/ 76 int tor_threadlocal_init(tor_threadlocal_t *threadlocal); 77 /** 78 * Release all resource associated with a thread-local variable. 79 */ 80 void tor_threadlocal_destroy(tor_threadlocal_t *threadlocal); 81 /** 82 * Return the current value of a thread-local variable for this thread. 83 * 84 * It's undefined behavior to use this function if the threadlocal hasn't 85 * been initialized, or has been destroyed. 86 */ 87 void *tor_threadlocal_get(tor_threadlocal_t *threadlocal); 88 /** 89 * Change the current value of a thread-local variable for this thread to 90 * <b>value</b>. 91 * 92 * It's undefined behavior to use this function if the threadlocal hasn't 93 * been initialized, or has been destroyed. 94 */ 95 void tor_threadlocal_set(tor_threadlocal_t *threadlocal, void *value); 96 97 /** 98 * Atomic counter type; holds a size_t value. 99 */ 100 #ifdef HAVE_WORKING_STDATOMIC 101 typedef struct atomic_counter_t { 102 atomic_size_t val; 103 } atomic_counter_t; 104 #ifndef COCCI 105 #define ATOMIC_LINKAGE static 106 #endif 107 #else /* !defined(HAVE_WORKING_STDATOMIC) */ 108 typedef struct atomic_counter_t { 109 tor_mutex_t mutex; 110 size_t val; 111 } atomic_counter_t; 112 #define ATOMIC_LINKAGE 113 #endif /* defined(HAVE_WORKING_STDATOMIC) */ 114 115 ATOMIC_LINKAGE void atomic_counter_init(atomic_counter_t *counter); 116 ATOMIC_LINKAGE void atomic_counter_destroy(atomic_counter_t *counter); 117 ATOMIC_LINKAGE void atomic_counter_add(atomic_counter_t *counter, size_t add); 118 ATOMIC_LINKAGE void atomic_counter_sub(atomic_counter_t *counter, size_t sub); 119 ATOMIC_LINKAGE size_t atomic_counter_get(atomic_counter_t *counter); 120 ATOMIC_LINKAGE size_t atomic_counter_exchange(atomic_counter_t *counter, 121 size_t newval); 122 #undef ATOMIC_LINKAGE 123 124 #ifdef HAVE_WORKING_STDATOMIC 125 /** Initialize a new atomic counter with the value 0 */ 126 static inline void 127 atomic_counter_init(atomic_counter_t *counter) 128 { 129 atomic_init(&counter->val, 0); 130 } 131 /** Clean up all resources held by an atomic counter. 132 * 133 * This usage note applies to the compat_threads implementation of 134 * atomic_counter_destroy(): 135 * Destroying a locked mutex is undefined behaviour. Global mutexes may be 136 * locked when they are passed to this function, because multiple threads can 137 * still access them. So we can either: 138 * - destroy on shutdown, and re-initialise when tor re-initialises, or 139 * - skip destroying and re-initialisation, using a sentinel variable. 140 * See #31735 for details. 141 */ 142 static inline void 143 atomic_counter_destroy(atomic_counter_t *counter) 144 { 145 (void)counter; 146 } 147 /** Add a value to an atomic counter. */ 148 static inline void 149 atomic_counter_add(atomic_counter_t *counter, size_t add) 150 { 151 (void) atomic_fetch_add(&counter->val, add); 152 } 153 /** Subtract a value from an atomic counter. */ 154 static inline void 155 atomic_counter_sub(atomic_counter_t *counter, size_t sub) 156 { 157 (void) atomic_fetch_sub(&counter->val, sub); 158 } 159 /** Return the current value of an atomic counter */ 160 static inline size_t 161 atomic_counter_get(atomic_counter_t *counter) 162 { 163 return atomic_load(&counter->val); 164 } 165 /** Replace the value of an atomic counter; return the old one. */ 166 static inline size_t 167 atomic_counter_exchange(atomic_counter_t *counter, size_t newval) 168 { 169 return atomic_exchange(&counter->val, newval); 170 } 171 172 #else /* !defined(HAVE_WORKING_STDATOMIC) */ 173 #endif /* defined(HAVE_WORKING_STDATOMIC) */ 174 175 #endif /* !defined(TOR_COMPAT_THREADS_H) */