mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-11 05:33:47 +01:00
Merge remote-tracking branch 'tor-gitlab/mr/211'
This commit is contained in:
commit
db5f7b4250
4
changes/ticket17927
Normal file
4
changes/ticket17927
Normal 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.
|
@ -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. */
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user