Tor  0.4.3.0-alpha-dev
compat_threads.c
Go to the documentation of this file.
1 /* Copyright (c) 2003-2004, Roger Dingledine
2  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
3  * Copyright (c) 2007-2020, 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 *
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
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
52 {
54 }
55 /** Return true iff called from the main thread. */
56 int
58 {
60 }
61 
62 #ifndef HAVE_WORKING_STDATOMIC
63 /** Initialize a new atomic counter with the value 0 */
64 void
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
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
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
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 {
127  return 0;
128 }
129 
130 const subsys_fns_t sys_threads = {
131  .name = "threads",
132  .supported = true,
133  /* Threads is used by logging, which is a diagnostic feature, we want it to
134  * init right after low-level error handling and approx time. */
135  .level = -95,
136  .initialize = subsys_threads_initialize,
137 };
size_t atomic_counter_get(atomic_counter_t *counter)
void tor_mutex_release(tor_mutex_t *m)
const char * name
Definition: subsys.h:42
void tor_cond_uninit(tor_cond_t *cond)
void atomic_counter_init(atomic_counter_t *counter)
size_t atomic_counter_exchange(atomic_counter_t *counter, size_t newval)
tor_cond_t * tor_cond_new(void)
#define tor_free(p)
Definition: malloc.h:52
void tor_threads_init(void)
Declare subsystem object for threads library.
void tor_mutex_init_nonrecursive(tor_mutex_t *m)
int in_main_thread(void)
void tor_mutex_uninit(tor_mutex_t *m)
Types used to declare a subsystem.
Header for threads.c.
void atomic_counter_sub(atomic_counter_t *counter, size_t sub)
void atomic_counter_add(atomic_counter_t *counter, size_t add)
void set_main_thread(void)
int tor_cond_init(tor_cond_t *cond)
static unsigned long main_thread_id
void tor_mutex_acquire(tor_mutex_t *m)
void tor_cond_free_(tor_cond_t *c)
void atomic_counter_destroy(atomic_counter_t *counter)
Headers for log.c.
unsigned long tor_get_thread_id(void)
Macros to manage assertions, fatal and non-fatal.