summaryrefslogtreecommitdiffstats
path: root/crypto/threads_win.c
diff options
context:
space:
mode:
authorDaiyuu Nobori <dnobori.gitcommit@coe.ad.jp>2022-07-24 10:34:05 +0900
committerMatt Caswell <matt@openssl.org>2022-08-12 10:30:02 +0100
commit2d46a44ff24173d2cf5ea2196360cb79470d49c7 (patch)
tree0845cf6d15630149b7e0392b68d157b72be1ce8c /crypto/threads_win.c
parent56d4ff6cd7fc200943197dff65146a8864b7df98 (diff)
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 <shane.lontis@oracle.com> Reviewed-by: Hugo Landau <hlandau@openssl.org> (Merged from https://github.com/openssl/openssl/pull/18856)
Diffstat (limited to 'crypto/threads_win.c')
-rw-r--r--crypto/threads_win.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/crypto/threads_win.c b/crypto/threads_win.c
index d65b3826d9..b5e4d18a84 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 <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)