tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

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) */