[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[tor-commits] [tor/master] Use SRWLocks to implement locking on Windows #17927



commit 877dbfc0561dfc5297cf446fe653cc3095d20b46
Author: Daniel Pinto <danielpinto52@xxxxxxxxx>
Date:   Thu Nov 12 19:40:07 2020 +0000

    Use SRWLocks to implement locking on Windows #17927
    
    Replace the Windows locking implementation which used critical
    sections with the faster SRWLocks available since Vista.
---
 changes/ticket17927                    |  4 ++
 src/lib/lock/compat_mutex.h            | 11 ++++-
 src/lib/lock/compat_mutex_winthreads.c | 76 +++++++++++++++++++++++++++++++---
 src/lib/thread/compat_winthreads.c     |  8 +++-
 4 files changed, 90 insertions(+), 9 deletions(-)

diff --git a/changes/ticket17927 b/changes/ticket17927
new file mode 100644
index 0000000000..532416dac4
--- /dev/null
+++ b/changes/ticket17927
@@ -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.
diff --git a/src/lib/lock/compat_mutex.h b/src/lib/lock/compat_mutex.h
index 5631993cc4..14bdf70ce5 100644
--- a/src/lib/lock/compat_mutex.h
+++ b/src/lib/lock/compat_mutex.h
@@ -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;
+  DWORD 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. */
diff --git a/src/lib/lock/compat_mutex_winthreads.c b/src/lib/lock/compat_mutex_winthreads.c
index 5fe6870a93..03cf5082e0 100644
--- a/src/lib/lock/compat_mutex_winthreads.c
+++ b/src/lib/lock/compat_mutex_winthreads.c
@@ -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,76 @@ 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)
+{
+  DWORD thread_id = GetCurrentThreadId();
+  if (thread_id == m->lock_owner) {
+    ++m->lock_count;
+    return;
+  }
+  AcquireSRWLockExclusive(&m->mutex);
+  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;
+  }
+  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);
+  }
 }
diff --git a/src/lib/thread/compat_winthreads.c b/src/lib/thread/compat_winthreads.c
index fcc9c0279b..a6213aa46a 100644
--- a/src/lib/thread/compat_winthreads.c
+++ b/src/lib/thread/compat_winthreads.c
@@ -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) {



_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits