diff options
author | Vincent Drake <vdrake@gmail.com> | 2021-03-01 20:38:02 +0100 |
---|---|---|
committer | Matt Caswell <matt@openssl.org> | 2021-03-11 11:33:06 +0100 |
commit | f70863d9dddd3ce3420f0e07841475a7e9680ca9 (patch) | |
tree | 55364ca136417731673a005857933bdad4db3f14 /crypto/threads_win.c | |
parent | Check SSL_set1_chain error in set_cert_cb (diff) | |
download | openssl-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.c | 50 |
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; |