]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
VC++ 2008 or earlier x86 compilers do not have an inline implementation of Interlocke...
authorDaiyuu Nobori <dnobori.gitcommit@coe.ad.jp>
Sun, 24 Jul 2022 01:34:05 +0000 (10:34 +0900)
committerMatt Caswell <matt@openssl.org>
Fri, 12 Aug 2022 09:30:02 +0000 (10:30 +0100)
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 <shane.lontis@oracle.com>
Reviewed-by: Hugo Landau <hlandau@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/18856)

crypto/threads_win.c

index d65b3826d93a274adf9cbd67cb9524744031ae2b..b5e4d18a84d846629d7b5c7ea3b3cb7c91452c26 100644 (file)
 # 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 <openssl/crypto.h>
 
 #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)