aboutsummaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2015-08-18 08:56:31 -0400
committerNick Mathewson <nickm@torproject.org>2015-08-18 08:56:31 -0400
commiteafae7f677364175e384d0e2c79f05e7d300049d (patch)
treec91e6744961a2c38cdec3ce559199b4834c548c5 /src/common
parentfe4c0a187dcc6ec8a14175dfc4c62334221d4239 (diff)
parent087cf882c6a9ef6b9617d21ef26c19c47a4fc660 (diff)
downloadtor-eafae7f677364175e384d0e2c79f05e7d300049d.tar.gz
tor-eafae7f677364175e384d0e2c79f05e7d300049d.zip
Merge branch 'decouple_controller_events_squashed'
Diffstat (limited to 'src/common')
-rw-r--r--src/common/compat_pthreads.c27
-rw-r--r--src/common/compat_threads.h36
-rw-r--r--src/common/compat_winthreads.c43
3 files changed, 106 insertions, 0 deletions
diff --git a/src/common/compat_pthreads.c b/src/common/compat_pthreads.c
index b78ab3d871..4b32fc93d2 100644
--- a/src/common/compat_pthreads.c
+++ b/src/common/compat_pthreads.c
@@ -275,6 +275,33 @@ tor_cond_signal_all(tor_cond_t *cond)
pthread_cond_broadcast(&cond->cond);
}
+int
+tor_threadlocal_init(tor_threadlocal_t *threadlocal)
+{
+ int err = pthread_key_create(&threadlocal->key, NULL);
+ return err ? -1 : 0;
+}
+
+void
+tor_threadlocal_destroy(tor_threadlocal_t *threadlocal)
+{
+ pthread_key_delete(threadlocal->key);
+ memset(threadlocal, 0, sizeof(tor_threadlocal_t));
+}
+
+void *
+tor_threadlocal_get(tor_threadlocal_t *threadlocal)
+{
+ return pthread_getspecific(threadlocal->key);
+}
+
+void
+tor_threadlocal_set(tor_threadlocal_t *threadlocal, void *value)
+{
+ int err = pthread_setspecific(threadlocal->key, value);
+ tor_assert(err == 0);
+}
+
/** Set up common structures for use by threading. */
void
tor_threads_init(void)
diff --git a/src/common/compat_threads.h b/src/common/compat_threads.h
index acf3083f37..71562ba3ef 100644
--- a/src/common/compat_threads.h
+++ b/src/common/compat_threads.h
@@ -111,5 +111,41 @@ typedef struct alert_sockets_s {
int alert_sockets_create(alert_sockets_t *socks_out, uint32_t flags);
void alert_sockets_close(alert_sockets_t *socks);
+typedef struct tor_threadlocal_s {
+#ifdef _WIN32
+ DWORD index;
+#else
+ pthread_key_t key;
+#endif
+} tor_threadlocal_t;
+
+/** Initialize a thread-local variable.
+ *
+ * After you call this function on a tor_threadlocal_t, you can call
+ * tor_threadlocal_set to change the current value of this variable for the
+ * current thread, and tor_threadlocal_get to retrieve the current value for
+ * the current thread. Each thread has its own value.
+ **/
+int tor_threadlocal_init(tor_threadlocal_t *threadlocal);
+/**
+ * Release all resource associated with a thread-local variable.
+ */
+void tor_threadlocal_destroy(tor_threadlocal_t *threadlocal);
+/**
+ * Return the current value of a thread-local variable for this thread.
+ *
+ * It's undefined behavior to use this function if the threadlocal hasn't
+ * been initialized, or has been destroyed.
+ */
+void *tor_threadlocal_get(tor_threadlocal_t *threadlocal);
+/**
+ * Change the current value of a thread-local variable for this thread to
+ * <b>value</b>.
+ *
+ * It's undefined behavior to use this function if the threadlocal hasn't
+ * been initialized, or has been destroyed.
+ */
+void tor_threadlocal_set(tor_threadlocal_t *threadlocal, void *value);
+
#endif
diff --git a/src/common/compat_winthreads.c b/src/common/compat_winthreads.c
index 465ef3ebed..9a87daa871 100644
--- a/src/common/compat_winthreads.c
+++ b/src/common/compat_winthreads.c
@@ -125,6 +125,49 @@ tor_cond_signal_all(tor_cond_t *cond)
}
int
+tor_threadlocal_init(tor_threadlocal_t *threadlocal)
+{
+ threadlocal->index = TlsAlloc();
+ return (threadlocal->index == TLS_OUT_OF_INDEXES) ? -1 : 0;
+}
+
+void
+tor_threadlocal_destroy(tor_threadlocal_t *threadlocal)
+{
+ TlsFree(threadlocal->index);
+ memset(threadlocal, 0, sizeof(tor_threadlocal_t));
+}
+
+void *
+tor_threadlocal_get(tor_threadlocal_t *threadlocal)
+{
+ void *value = TlsGetValue(threadlocal->index);
+ if (value == NULL) {
+ DWORD err = GetLastError();
+ if (err != ERROR_SUCCESS) {
+ char *msg = format_win32_error(err);
+ log_err(LD_GENERAL, "Error retrieving thread-local value: %s", msg);
+ tor_free(msg);
+ tor_assert(err == ERROR_SUCCESS);
+ }
+ }
+ return value;
+}
+
+void
+tor_threadlocal_set(tor_threadlocal_t *threadlocal, void *value)
+{
+ BOOL ok = TlsSetValue(threadlocal->index, value);
+ if (!ok) {
+ DWORD err = GetLastError();
+ char *msg = format_win32_error(err);
+ log_err(LD_GENERAL, "Error adjusting thread-local value: %s", msg);
+ tor_free(msg);
+ tor_assert(ok);
+ }
+}
+
+int
tor_cond_wait(tor_cond_t *cond, tor_mutex_t *lock_, const struct timeval *tv)
{
CRITICAL_SECTION *lock = &lock_->mutex;