diff options
author | Vincent Drake <vdrake@gmail.com> | 2021-03-01 14:38:02 -0500 |
---|---|---|
committer | Matt Caswell <matt@openssl.org> | 2021-03-11 10:33:06 +0000 |
commit | f70863d9dddd3ce3420f0e07841475a7e9680ca9 (patch) | |
tree | 55364ca136417731673a005857933bdad4db3f14 | |
parent | 1aa7ecd0d3f6d9c3739cf2e2d87673a3be03b352 (diff) |
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)
-rw-r--r-- | CHANGES.md | 5 | ||||
-rw-r--r-- | crypto/threads_win.c | 50 |
2 files changed, 53 insertions, 2 deletions
diff --git a/CHANGES.md b/CHANGES.md index a547b40829..bdac54c10f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -23,6 +23,11 @@ OpenSSL 3.0 ### Changes between 1.1.1 and 3.0 [xx XXX xxxx] + * Windows thread synchronization uses read/write primitives (SRWLock) when + supported by the OS, otherwise CriticalSection continues to be used. + + *Vincent Drake* + * Add filter BIO BIO_f_readbuffer() that allows BIO_tell() and BIO_seek() to work on read only BIO source/sinks that do not support these functions. This allows piping or redirection of a file BIO using stdin to be buffered 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; |