diff options
Diffstat (limited to 'src/lib/lock/compat_mutex_winthreads.c')
-rw-r--r-- | src/lib/lock/compat_mutex_winthreads.c | 80 |
1 files changed, 74 insertions, 6 deletions
diff --git a/src/lib/lock/compat_mutex_winthreads.c b/src/lib/lock/compat_mutex_winthreads.c index 5fe6870a93..8a101e0d25 100644 --- a/src/lib/lock/compat_mutex_winthreads.c +++ b/src/lib/lock/compat_mutex_winthreads.c @@ -1,6 +1,6 @@ /* Copyright (c) 2003-2004, Roger Dingledine * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2020, The Tor Project, Inc. */ + * Copyright (c) 2007-2021, The Tor Project, Inc. */ /* See LICENSE for licensing information */ /** @@ -9,6 +9,23 @@ * \brief Implement the tor_mutex API using CRITICAL_SECTION. **/ +#include "orconfig.h" + +/* For SRW locks support */ +#ifndef WINVER +#error "orconfig.h didn't define WINVER" +#endif +#ifndef _WIN32_WINNT +#error "orconfig.h didn't define _WIN32_WINNT" +#endif +#if WINVER < 0x0600 +#error "winver too low" +#endif +#if _WIN32_WINNT < 0x0600 +#error "winver too low" +#endif + +#include <windows.h> #include "lib/lock/compat_mutex.h" #include "lib/err/torerr.h" @@ -20,27 +37,78 @@ tor_locking_init(void) void tor_mutex_init(tor_mutex_t *m) { - InitializeCriticalSection(&m->mutex); + m->type = RECURSIVE; + m->lock_owner = 0; + m->lock_count = 0; + InitializeSRWLock(&m->mutex); } void tor_mutex_init_nonrecursive(tor_mutex_t *m) { - InitializeCriticalSection(&m->mutex); + m->type = NON_RECURSIVE; + InitializeSRWLock(&m->mutex); } void tor_mutex_uninit(tor_mutex_t *m) { - DeleteCriticalSection(&m->mutex); + (void) m; +} + +static void +tor_mutex_acquire_recursive(tor_mutex_t *m) +{ + LONG thread_id = GetCurrentThreadId(); + // use InterlockedCompareExchange to perform an atomic read + LONG lock_owner = InterlockedCompareExchange(&m->lock_owner, 0, 0); + if (thread_id == lock_owner) { + ++m->lock_count; + return; + } + AcquireSRWLockExclusive(&m->mutex); + InterlockedExchange(&m->lock_owner, thread_id); + m->lock_count = 1; +} + +static void +tor_mutex_acquire_nonrecursive(tor_mutex_t *m) +{ + AcquireSRWLockExclusive(&m->mutex); } + void tor_mutex_acquire(tor_mutex_t *m) { raw_assert(m); - EnterCriticalSection(&m->mutex); + if (m->type == NON_RECURSIVE) { + tor_mutex_acquire_nonrecursive(m); + } else { + tor_mutex_acquire_recursive(m); + } +} + +static void +tor_mutex_release_recursive(tor_mutex_t *m) +{ + if (--m->lock_count) { + return; + } + InterlockedExchange(&m->lock_owner, 0); + ReleaseSRWLockExclusive(&m->mutex); } + +static void +tor_mutex_release_nonrecursive(tor_mutex_t *m) +{ + ReleaseSRWLockExclusive(&m->mutex); +} + void tor_mutex_release(tor_mutex_t *m) { - LeaveCriticalSection(&m->mutex); + if (m->type == NON_RECURSIVE) { + tor_mutex_release_nonrecursive(m); + } else { + tor_mutex_release_recursive(m); + } } |