diff options
author | Nick Mathewson <nickm@torproject.org> | 2013-09-22 21:30:46 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2015-01-14 10:41:53 -0500 |
commit | c2f0d52b7fb937f3f66ef8b2b74b0fdf239b0e9b (patch) | |
tree | c0deccd74112c5d135d018099f616842431e81ee /src/common/compat_winthreads.c | |
parent | 518b0b3c5fefba2458181c7f733bc684e5466cf9 (diff) | |
download | tor-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.c | 161 |
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(); +} |