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 };