summaryrefslogtreecommitdiffstats
path: root/crypto/threads_win.c
diff options
context:
space:
mode:
authorVincent Drake <vdrake@gmail.com>2021-03-01 20:38:02 +0100
committerMatt Caswell <matt@openssl.org>2021-03-11 11:33:06 +0100
commitf70863d9dddd3ce3420f0e07841475a7e9680ca9 (patch)
tree55364ca136417731673a005857933bdad4db3f14 /crypto/threads_win.c
parentCheck SSL_set1_chain error in set_cert_cb (diff)
downloadopenssl-f70863d9dddd3ce3420f0e07841475a7e9680ca9.tar.xz
openssl-f70863d9dddd3ce3420f0e07841475a7e9680ca9.zip
Use read/write locking on Windows
Fixes #13914 The "SRWLock" synchronization primitive is available in Windows Vista and later. CRYPTO_THREAD functions now use SRWLock functions when the target operating system supports them. Reviewed-by: Paul Dale <pauli@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/14381)
Diffstat (limited to 'crypto/threads_win.c')
-rw-r--r--crypto/threads_win.c50
1 files changed, 48 insertions, 2 deletions
diff --git a/crypto/threads_win.c b/crypto/threads_win.c
index ef68fe2d24..34c8964aa6 100644
--- a/crypto/threads_win.c
+++ b/crypto/threads_win.c
@@ -9,29 +9,49 @@
#if defined(_WIN32)
# include <windows.h>
+# if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600
+# include <synchapi.h>
+# define USE_RWLOCK
+# endif
#endif
#include <openssl/crypto.h>
#if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) && defined(OPENSSL_SYS_WINDOWS)
+# ifdef USE_RWLOCK
+typedef struct {
+ SRWLOCK lock;
+ int exclusive;
+} CRYPTO_win_rwlock;
+# endif
+
CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void)
{
CRYPTO_RWLOCK *lock;
+# ifdef USE_RWLOCK
+ CRYPTO_win_rwlock *rwlock;
+
+ if ((lock = OPENSSL_zalloc(sizeof(CRYPTO_win_rwlock))) == NULL)
+ return NULL;
+ rwlock = lock;
+ InitializeSRWLock(&rwlock->lock);
+# else
if ((lock = OPENSSL_zalloc(sizeof(CRITICAL_SECTION))) == NULL) {
/* Don't set error, to avoid recursion blowup. */
return NULL;
}
-# if !defined(_WIN32_WCE)
+# if !defined(_WIN32_WCE)
/* 0x400 is the spin count value suggested in the documentation */
if (!InitializeCriticalSectionAndSpinCount(lock, 0x400)) {
OPENSSL_free(lock);
return NULL;
}
-# else
+# else
InitializeCriticalSection(lock);
+# endif
# endif
return lock;
@@ -39,19 +59,43 @@ CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void)
int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock)
{
+# ifdef USE_RWLOCK
+ CRYPTO_win_rwlock *rwlock = lock;
+
+ AcquireSRWLockShared(&rwlock->lock);
+# else
EnterCriticalSection(lock);
+# endif
return 1;
}
int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock)
{
+# ifdef USE_RWLOCK
+ CRYPTO_win_rwlock *rwlock = lock;
+
+ AcquireSRWLockExclusive(&rwlock->lock);
+ rwlock->exclusive = 1;
+# else
EnterCriticalSection(lock);
+# endif
return 1;
}
int CRYPTO_THREAD_unlock(CRYPTO_RWLOCK *lock)
{
+# ifdef USE_RWLOCK
+ CRYPTO_win_rwlock *rwlock = lock;
+
+ if (rwlock->exclusive) {
+ rwlock->exclusive = 0;
+ ReleaseSRWLockExclusive(&rwlock->lock);
+ } else {
+ ReleaseSRWLockShared(&rwlock->lock);
+ }
+# else
LeaveCriticalSection(lock);
+# endif
return 1;
}
@@ -60,7 +104,9 @@ void CRYPTO_THREAD_lock_free(CRYPTO_RWLOCK *lock)
if (lock == NULL)
return;
+# ifndef USE_RWLOCK
DeleteCriticalSection(lock);
+# endif
OPENSSL_free(lock);
return;