tor

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

compat_threads.c (3445B)


      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 compat_threads.c
      8 *
      9 * \brief Cross-platform threading and inter-thread communication logic.
     10 *  (Platform-specific parts are written in the other compat_*threads
     11 *  modules.)
     12 */
     13 
     14 #include "orconfig.h"
     15 #include <stdlib.h>
     16 #include "lib/thread/threads.h"
     17 #include "lib/thread/thread_sys.h"
     18 
     19 #include "lib/log/log.h"
     20 #include "lib/log/util_bug.h"
     21 #include "lib/subsys/subsys.h"
     22 
     23 #include <string.h>
     24 
     25 /** Allocate and return a new condition variable. */
     26 tor_cond_t *
     27 tor_cond_new(void)
     28 {
     29  tor_cond_t *cond = tor_malloc(sizeof(tor_cond_t));
     30  if (BUG(tor_cond_init(cond)<0))
     31    tor_free(cond); // LCOV_EXCL_LINE
     32  return cond;
     33 }
     34 
     35 /** Free all storage held in <b>c</b>. */
     36 void
     37 tor_cond_free_(tor_cond_t *c)
     38 {
     39  if (!c)
     40    return;
     41  tor_cond_uninit(c);
     42  tor_free(c);
     43 }
     44 
     45 /** Identity of the "main" thread */
     46 static unsigned long main_thread_id = -1;
     47 
     48 /** Start considering the current thread to be the 'main thread'.  This has
     49 * no effect on anything besides in_main_thread(). */
     50 void
     51 set_main_thread(void)
     52 {
     53  main_thread_id = tor_get_thread_id();
     54 }
     55 /** Return true iff called from the main thread. */
     56 int
     57 in_main_thread(void)
     58 {
     59  return main_thread_id == tor_get_thread_id();
     60 }
     61 
     62 #ifndef HAVE_WORKING_STDATOMIC
     63 /** Initialize a new atomic counter with the value 0 */
     64 void
     65 atomic_counter_init(atomic_counter_t *counter)
     66 {
     67  memset(counter, 0, sizeof(*counter));
     68  tor_mutex_init_nonrecursive(&counter->mutex);
     69 }
     70 /** Clean up all resources held by an atomic counter.
     71 *
     72 * Destroying a locked mutex is undefined behaviour. Global mutexes may be
     73 * locked when they are passed to this function, because multiple threads can
     74 * still access them. So we can either:
     75 *  - destroy on shutdown, and re-initialise when tor re-initialises, or
     76 *  - skip destroying and re-initialisation, using a sentinel variable.
     77 * See #31735 for details.
     78 */
     79 void
     80 atomic_counter_destroy(atomic_counter_t *counter)
     81 {
     82  tor_mutex_uninit(&counter->mutex);
     83  memset(counter, 0, sizeof(*counter));
     84 }
     85 /** Add a value to an atomic counter. */
     86 void
     87 atomic_counter_add(atomic_counter_t *counter, size_t add)
     88 {
     89  tor_mutex_acquire(&counter->mutex);
     90  counter->val += add;
     91  tor_mutex_release(&counter->mutex);
     92 }
     93 /** Subtract a value from an atomic counter. */
     94 void
     95 atomic_counter_sub(atomic_counter_t *counter, size_t sub)
     96 {
     97  // this relies on unsigned overflow, but that's fine.
     98  atomic_counter_add(counter, -sub);
     99 }
    100 /** Return the current value of an atomic counter */
    101 size_t
    102 atomic_counter_get(atomic_counter_t *counter)
    103 {
    104  size_t val;
    105  tor_mutex_acquire(&counter->mutex);
    106  val = counter->val;
    107  tor_mutex_release(&counter->mutex);
    108  return val;
    109 }
    110 /** Replace the value of an atomic counter; return the old one. */
    111 size_t
    112 atomic_counter_exchange(atomic_counter_t *counter, size_t newval)
    113 {
    114  size_t oldval;
    115  tor_mutex_acquire(&counter->mutex);
    116  oldval = counter->val;
    117  counter->val = newval;
    118  tor_mutex_release(&counter->mutex);
    119  return oldval;
    120 }
    121 #endif /* !defined(HAVE_WORKING_STDATOMIC) */
    122 
    123 static int
    124 subsys_threads_initialize(void)
    125 {
    126  tor_threads_init();
    127  return 0;
    128 }
    129 
    130 const subsys_fns_t sys_threads = {
    131  .name = "threads",
    132  SUBSYS_DECLARE_LOCATION(),
    133  .supported = true,
    134  .level = -89,
    135  .initialize = subsys_threads_initialize,
    136 };