aboutsummaryrefslogtreecommitdiff
path: root/src/lib/thread/compat_threads.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2018-06-28 09:14:42 -0400
committerNick Mathewson <nickm@torproject.org>2018-06-28 09:14:42 -0400
commit9cf335c9a5fe6767e90cc5cfdc1f5c95465edb10 (patch)
tree04e771dcb1c0c577b221a5a4f4b11ffa677972af /src/lib/thread/compat_threads.c
parent544ab27a949406628809869111b7288017a5bcb1 (diff)
downloadtor-9cf335c9a5fe6767e90cc5cfdc1f5c95465edb10.tar.gz
tor-9cf335c9a5fe6767e90cc5cfdc1f5c95465edb10.zip
Extract threading code into a new library.
Note that the workqueue code does *not* go here: it is logically at a higher level, since it needs to use libevent and the networking stack.
Diffstat (limited to 'src/lib/thread/compat_threads.c')
-rw-r--r--src/lib/thread/compat_threads.c109
1 files changed, 109 insertions, 0 deletions
diff --git a/src/lib/thread/compat_threads.c b/src/lib/thread/compat_threads.c
new file mode 100644
index 0000000000..1d685b2c3e
--- /dev/null
+++ b/src/lib/thread/compat_threads.c
@@ -0,0 +1,109 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2018, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file compat_threads.c
+ *
+ * \brief Cross-platform threading and inter-thread communication logic.
+ * (Platform-specific parts are written in the other compat_*threads
+ * modules.)
+ */
+
+#include "orconfig.h"
+#include <stdlib.h>
+#include "lib/thread/threads.h"
+
+#include "lib/log/torlog.h"
+#include "lib/log/util_bug.h"
+
+/** Allocate and return a new condition variable. */
+tor_cond_t *
+tor_cond_new(void)
+{
+ tor_cond_t *cond = tor_malloc(sizeof(tor_cond_t));
+ if (BUG(tor_cond_init(cond)<0))
+ tor_free(cond); // LCOV_EXCL_LINE
+ return cond;
+}
+
+/** Free all storage held in <b>c</b>. */
+void
+tor_cond_free_(tor_cond_t *c)
+{
+ if (!c)
+ return;
+ tor_cond_uninit(c);
+ tor_free(c);
+}
+
+/** Identity of the "main" thread */
+static unsigned long main_thread_id = -1;
+
+/** Start considering the current thread to be the 'main thread'. This has
+ * no effect on anything besides in_main_thread(). */
+void
+set_main_thread(void)
+{
+ main_thread_id = tor_get_thread_id();
+}
+/** Return true iff called from the main thread. */
+int
+in_main_thread(void)
+{
+ return main_thread_id == tor_get_thread_id();
+}
+
+#ifndef HAVE_STDATOMIC_H
+/** Initialize a new atomic counter with the value 0 */
+void
+atomic_counter_init(atomic_counter_t *counter)
+{
+ memset(counter, 0, sizeof(*counter));
+ tor_mutex_init_nonrecursive(&counter->mutex);
+}
+/** Clean up all resources held by an atomic counter. */
+void
+atomic_counter_destroy(atomic_counter_t *counter)
+{
+ tor_mutex_uninit(&counter->mutex);
+ memset(counter, 0, sizeof(*counter));
+}
+/** Add a value to an atomic counter. */
+void
+atomic_counter_add(atomic_counter_t *counter, size_t add)
+{
+ tor_mutex_acquire(&counter->mutex);
+ counter->val += add;
+ tor_mutex_release(&counter->mutex);
+}
+/** Subtract a value from an atomic counter. */
+void
+atomic_counter_sub(atomic_counter_t *counter, size_t sub)
+{
+ // this relies on unsigned overflow, but that's fine.
+ atomic_counter_add(counter, -sub);
+}
+/** Return the current value of an atomic counter */
+size_t
+atomic_counter_get(atomic_counter_t *counter)
+{
+ size_t val;
+ tor_mutex_acquire(&counter->mutex);
+ val = counter->val;
+ tor_mutex_release(&counter->mutex);
+ return val;
+}
+/** Replace the value of an atomic counter; return the old one. */
+size_t
+atomic_counter_exchange(atomic_counter_t *counter, size_t newval)
+{
+ size_t oldval;
+ tor_mutex_acquire(&counter->mutex);
+ oldval = counter->val;
+ counter->val = newval;
+ tor_mutex_release(&counter->mutex);
+ return oldval;
+}
+#endif /* !defined(HAVE_STDATOMIC_H) */