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 +# if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600 +# include +# define USE_RWLOCK +# endif #endif #include #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;