summaryrefslogtreecommitdiff
path: root/src/common/compat_winthreads.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2013-09-22 21:30:46 -0400
committerNick Mathewson <nickm@torproject.org>2015-01-14 10:41:53 -0500
commitc2f0d52b7fb937f3f66ef8b2b74b0fdf239b0e9b (patch)
treec0deccd74112c5d135d018099f616842431e81ee /src/common/compat_winthreads.c
parent518b0b3c5fefba2458181c7f733bc684e5466cf9 (diff)
downloadtor-c2f0d52b7fb937f3f66ef8b2b74b0fdf239b0e9b.tar.gz
tor-c2f0d52b7fb937f3f66ef8b2b74b0fdf239b0e9b.zip
Split threading-related code out of compat.c
Also, re-enable the #if'd out condition-variable code. Work queues are going to make us hack on all of this stuff a bit more closely, so it might not be a terrible idea to make it easier to hack.
Diffstat (limited to 'src/common/compat_winthreads.c')
-rw-r--r--src/common/compat_winthreads.c161
1 files changed, 161 insertions, 0 deletions
diff --git a/src/common/compat_winthreads.c b/src/common/compat_winthreads.c
new file mode 100644
index 0000000000..01332fd944
--- /dev/null
+++ b/src/common/compat_winthreads.c
@@ -0,0 +1,161 @@
+/* Copyright (c) 2003-2004, Roger Dingledine
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2015, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#include "compat.h"
+#include <windows.h>
+#include <process.h>
+#include "util.h"
+#include "container.h"
+#include "torlog.h"
+
+/** Minimalist interface to run a void function in the background. On
+ * Unix calls fork, on win32 calls beginthread. Returns -1 on failure.
+ * func should not return, but rather should call spawn_exit.
+ *
+ * NOTE: if <b>data</b> is used, it should not be allocated on the stack,
+ * since in a multithreaded environment, there is no way to be sure that
+ * the caller's stack will still be around when the called function is
+ * running.
+ */
+int
+spawn_func(void (*func)(void *), void *data)
+{
+ int rv;
+ rv = (int)_beginthread(func, 0, data);
+ if (rv == (int)-1)
+ return -1;
+ return 0;
+}
+
+
+/** End the current thread/process.
+ */
+void
+spawn_exit(void)
+{
+ _endthread();
+ //we should never get here. my compiler thinks that _endthread returns, this
+ //is an attempt to fool it.
+ tor_assert(0);
+ _exit(0);
+}
+
+
+void
+tor_mutex_init(tor_mutex_t *m)
+{
+ InitializeCriticalSection(&m->mutex);
+}
+void
+tor_mutex_uninit(tor_mutex_t *m)
+{
+ DeleteCriticalSection(&m->mutex);
+}
+void
+tor_mutex_acquire(tor_mutex_t *m)
+{
+ tor_assert(m);
+ EnterCriticalSection(&m->mutex);
+}
+void
+tor_mutex_release(tor_mutex_t *m)
+{
+ LeaveCriticalSection(&m->mutex);
+}
+unsigned long
+tor_get_thread_id(void)
+{
+ return (unsigned long)GetCurrentThreadId();
+}
+
+static DWORD cond_event_tls_index;
+struct tor_cond_t {
+ CRITICAL_SECTION mutex;
+ smartlist_t *events;
+};
+tor_cond_t *
+tor_cond_new(void)
+{
+ tor_cond_t *cond = tor_malloc_zero(sizeof(tor_cond_t));
+ InitializeCriticalSection(&cond->mutex);
+ cond->events = smartlist_new();
+ return cond;
+}
+void
+tor_cond_free(tor_cond_t *cond)
+{
+ if (!cond)
+ return;
+ DeleteCriticalSection(&cond->mutex);
+ /* XXXX notify? */
+ smartlist_free(cond->events);
+ tor_free(cond);
+}
+int
+tor_cond_wait(tor_cond_t *cond, tor_mutex_t *mutex)
+{
+ HANDLE event;
+ int r;
+ tor_assert(cond);
+ tor_assert(mutex);
+ event = TlsGetValue(cond_event_tls_index);
+ if (!event) {
+ event = CreateEvent(0, FALSE, FALSE, NULL);
+ TlsSetValue(cond_event_tls_index, event);
+ }
+ EnterCriticalSection(&cond->mutex);
+
+ tor_assert(WaitForSingleObject(event, 0) == WAIT_TIMEOUT);
+ tor_assert(!smartlist_contains(cond->events, event));
+ smartlist_add(cond->events, event);
+
+ LeaveCriticalSection(&cond->mutex);
+
+ tor_mutex_release(mutex);
+ r = WaitForSingleObject(event, INFINITE);
+ tor_mutex_acquire(mutex);
+
+ switch (r) {
+ case WAIT_OBJECT_0: /* we got the mutex normally. */
+ break;
+ case WAIT_ABANDONED: /* holding thread exited. */
+ case WAIT_TIMEOUT: /* Should never happen. */
+ tor_assert(0);
+ break;
+ case WAIT_FAILED:
+ log_warn(LD_GENERAL, "Failed to acquire mutex: %d",(int) GetLastError());
+ }
+ return 0;
+}
+void
+tor_cond_signal_one(tor_cond_t *cond)
+{
+ HANDLE event;
+ tor_assert(cond);
+
+ EnterCriticalSection(&cond->mutex);
+
+ if ((event = smartlist_pop_last(cond->events)))
+ SetEvent(event);
+
+ LeaveCriticalSection(&cond->mutex);
+}
+void
+tor_cond_signal_all(tor_cond_t *cond)
+{
+ tor_assert(cond);
+
+ EnterCriticalSection(&cond->mutex);
+ SMARTLIST_FOREACH(cond->events, HANDLE, event, SetEvent(event));
+ smartlist_clear(cond->events);
+ LeaveCriticalSection(&cond->mutex);
+}
+
+void
+tor_threads_init(void)
+{
+ cond_event_tls_index = TlsAlloc();
+ set_main_thread();
+}