From: Daiyuu Nobori Date: Sun, 24 Jul 2022 01:34:05 +0000 (+0900) Subject: VC++ 2008 or earlier x86 compilers do not have an inline implementation of Interlocke... X-Git-Tag: openssl-3.2.0-alpha1~2294 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2d46a44ff24173d2cf5ea2196360cb79470d49c7;p=thirdparty%2Fopenssl.git VC++ 2008 or earlier x86 compilers do not have an inline implementation of InterlockedOr64 for 32bit and will fail to run on Windows XP 32bit. See: https://docs.microsoft.com/en-us/cpp/intrinsics/interlockedor-intrinsic-functions#requirements To work around this problem, we implement a manual locking mechanism for only VC++ 2008 or earlier x86 compilers. Reviewed-by: Shane Lontis Reviewed-by: Hugo Landau (Merged from https://github.com/openssl/openssl/pull/18856) --- diff --git a/crypto/threads_win.c b/crypto/threads_win.c index d65b3826d93..b5e4d18a84d 100644 --- a/crypto/threads_win.c +++ b/crypto/threads_win.c @@ -14,6 +14,18 @@ # endif #endif +/* + * VC++ 2008 or earlier x86 compilers do not have an inline implementation + * of InterlockedOr64 for 32bit and will fail to run on Windows XP 32bit. + * https://docs.microsoft.com/en-us/cpp/intrinsics/interlockedor-intrinsic-functions#requirements + * To work around this problem, we implement a manual locking mechanism for + * only VC++ 2008 or earlier x86 compilers. + */ + +#if (defined(_MSC_VER) && defined(_M_IX86) && _MSC_VER <= 1500) +# define NO_INTERLOCKEDOR64 +#endif + #include #if defined(OPENSSL_THREADS) && !defined(CRYPTO_TDEBUG) && defined(OPENSSL_SYS_WINDOWS) @@ -207,14 +219,36 @@ int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock) int CRYPTO_atomic_or(uint64_t *val, uint64_t op, uint64_t *ret, CRYPTO_RWLOCK *lock) { +#if (defined(NO_INTERLOCKEDOR64)) + if (lock == NULL || !CRYPTO_THREAD_write_lock(lock)) + return 0; + *val |= op; + *ret = *val; + + if (!CRYPTO_THREAD_unlock(lock)) + return 0; + + return 1; +#else *ret = (uint64_t)InterlockedOr64((LONG64 volatile *)val, (LONG64)op) | op; return 1; +#endif } int CRYPTO_atomic_load(uint64_t *val, uint64_t *ret, CRYPTO_RWLOCK *lock) { +#if (defined(NO_INTERLOCKEDOR64)) + if (lock == NULL || !CRYPTO_THREAD_read_lock(lock)) + return 0; + *ret = *val; + if (!CRYPTO_THREAD_unlock(lock)) + return 0; + + return 1; +#else *ret = (uint64_t)InterlockedOr64((LONG64 volatile *)val, 0); return 1; +#endif } int openssl_init_fork_handlers(void)