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. */
|
/** A generic lock structure for multithreaded builds. */
|
||||||
typedef struct tor_mutex_t {
|
typedef struct tor_mutex_t {
|
||||||
#if defined(USE_WIN32_THREADS)
|
#if defined(USE_WIN32_THREADS)
|
||||||
/** Windows-only: on windows, we implement locks with CRITICAL_SECTIONS. */
|
/** Windows-only: on windows, we implement locks with SRW locks. */
|
||||||
CRITICAL_SECTION mutex;
|
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)
|
#elif defined(USE_PTHREADS)
|
||||||
/** Pthreads-only: with pthreads, we implement locks with
|
/** Pthreads-only: with pthreads, we implement locks with
|
||||||
* pthread_mutex_t. */
|
* pthread_mutex_t. */
|
||||||
|
@ -9,6 +9,23 @@
|
|||||||
* \brief Implement the tor_mutex API using CRITICAL_SECTION.
|
* \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/lock/compat_mutex.h"
|
||||||
#include "lib/err/torerr.h"
|
#include "lib/err/torerr.h"
|
||||||
|
|
||||||
@ -20,27 +37,78 @@ tor_locking_init(void)
|
|||||||
void
|
void
|
||||||
tor_mutex_init(tor_mutex_t *m)
|
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
|
void
|
||||||
tor_mutex_init_nonrecursive(tor_mutex_t *m)
|
tor_mutex_init_nonrecursive(tor_mutex_t *m)
|
||||||
{
|
{
|
||||||
InitializeCriticalSection(&m->mutex);
|
m->type = NON_RECURSIVE;
|
||||||
|
InitializeSRWLock(&m->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
tor_mutex_uninit(tor_mutex_t *m)
|
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
|
void
|
||||||
tor_mutex_acquire(tor_mutex_t *m)
|
tor_mutex_acquire(tor_mutex_t *m)
|
||||||
{
|
{
|
||||||
raw_assert(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
|
void
|
||||||
tor_mutex_release(tor_mutex_t *m)
|
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
|
int
|
||||||
tor_cond_wait(tor_cond_t *cond, tor_mutex_t *lock_, const struct timeval *tv)
|
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;
|
DWORD ms = INFINITE;
|
||||||
if (tv) {
|
if (tv) {
|
||||||
ms = tv->tv_sec*1000 + (tv->tv_usec+999)/1000;
|
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) {
|
if (!ok) {
|
||||||
DWORD err = GetLastError();
|
DWORD err = GetLastError();
|
||||||
if (err == ERROR_TIMEOUT) {
|
if (err == ERROR_TIMEOUT) {
|
||||||
|
Loading…
Reference in New Issue
Block a user