Line data Source code
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 49001 : atomic_counter_init(atomic_counter_t *counter) 128 : { 129 49001 : atomic_init(&counter->val, 0); 130 49001 : } 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 800 : atomic_counter_add(atomic_counter_t *counter, size_t add) 150 : { 151 800 : (void) atomic_fetch_add(&counter->val, add); 152 800 : } 153 : /** Subtract a value from an atomic counter. */ 154 : static inline void 155 800 : atomic_counter_sub(atomic_counter_t *counter, size_t sub) 156 : { 157 800 : (void) atomic_fetch_sub(&counter->val, sub); 158 800 : } 159 : /** Return the current value of an atomic counter */ 160 : static inline size_t 161 520 : atomic_counter_get(atomic_counter_t *counter) 162 : { 163 520 : return atomic_load(&counter->val); 164 : } 165 : /** Replace the value of an atomic counter; return the old one. */ 166 : static inline size_t 167 5766 : atomic_counter_exchange(atomic_counter_t *counter, size_t newval) 168 : { 169 5766 : 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) */