Merge remote-tracking branch 'tor-gitlab/mr/211'

This commit is contained in:
Alexander Færøy 2020-12-18 14:22:23 +00:00
commit db5f7b4250
4 changed files with 92 additions and 9 deletions

4
changes/ticket17927 Normal file
View File

@ -0,0 +1,4 @@
o Minor features (performance, windows):
- Use SRWLocks to implement locking on Windows. Replaces the critical
section locking implementation with the faster SRWLocks available
since Windows Vista. Closes ticket 17927. Patch by Daniel Pinto.

View File

@ -39,8 +39,15 @@
/** A generic lock structure for multithreaded builds. */
typedef struct tor_mutex_t {
#if defined(USE_WIN32_THREADS)
/** Windows-only: on windows, we implement locks with CRITICAL_SECTIONS. */
CRITICAL_SECTION mutex;
/** Windows-only: on windows, we implement locks with SRW locks. */
SRWLOCK mutex;
/** For recursive lock support (SRW locks are not recursive) */
enum mutex_type_t {
NON_RECURSIVE = 0,
RECURSIVE
} type;
LONG lock_owner; // id of the thread that owns the lock
int lock_count; // number of times the lock is held recursively
#elif defined(USE_PTHREADS)
/** Pthreads-only: with pthreads, we implement locks with
* pthread_mutex_t. */

View File

@ -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);
}
}

View File

@ -144,13 +144,17 @@ tor_threadlocal_set(tor_threadlocal_t *threadlocal, void *value)
int
tor_cond_wait(tor_cond_t *cond, tor_mutex_t *lock_, const struct timeval *tv)
{
CRITICAL_SECTION *lock = &lock_->mutex;
// recursive SRW locks are not supported because they need extra logic for
// acquiring and releasing but SleepConditionVariableSRW will use the OS
// lock relase function which lacks our extra logic
tor_assert(lock_->type == NON_RECURSIVE);
SRWLOCK *lock = &lock_->mutex;
DWORD ms = INFINITE;
if (tv) {
ms = tv->tv_sec*1000 + (tv->tv_usec+999)/1000;
}
BOOL ok = SleepConditionVariableCS(&cond->cond, lock, ms);
BOOL ok = SleepConditionVariableSRW(&cond->cond, lock, ms, 0);
if (!ok) {
DWORD err = GetLastError();
if (err == ERROR_TIMEOUT) {