aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarat Dukhan <maratek@gmail.com>2020-04-10 18:39:37 -0700
committerMarat Dukhan <maratek@gmail.com>2020-04-10 18:39:37 -0700
commit4ac9270e4b6ecf03f18e3d0ed2028aac2c988911 (patch)
tree78aff84074c0321bdfba4af1fe3dd73176fc4c13
parentddd479bcd8ba87094132ecf438dd76eb08ee3b0d (diff)
downloadpthreadpool-4ac9270e4b6ecf03f18e3d0ed2028aac2c988911.tar.gz
Support Windows on ARM/ARM64
-rw-r--r--src/threadpool-atomics.h200
-rw-r--r--src/threadpool-utils.h4
-rw-r--r--src/windows.c6
3 files changed, 197 insertions, 13 deletions
diff --git a/src/threadpool-atomics.h b/src/threadpool-atomics.h
index 0b3459b..e2fbe6a 100644
--- a/src/threadpool-atomics.h
+++ b/src/threadpool-atomics.h
@@ -7,7 +7,9 @@
/* MSVC-specific headers */
#ifdef _MSC_VER
#include <intrin.h>
- #include <immintrin.h>
+ #if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64)
+ #include <immintrin.h>
+ #endif
#endif
@@ -168,7 +170,7 @@
static inline size_t pthreadpool_decrement_fetch_relaxed_size_t(
pthreadpool_atomic_size_t* address)
{
- return (size_t) _InterlockedDecrement64((__int64 volatile*) address);
+ return (size_t) _InterlockedDecrement64((volatile __int64*) address);
}
static inline bool pthreadpool_try_decrement_relaxed_size_t(
@@ -179,7 +181,7 @@
const size_t new_value = actual_value - 1;
const size_t expected_value = actual_value;
actual_value = _InterlockedCompareExchange64(
- (__int64 volatile*) value, (__int64) new_value, (__int64) expected_value);
+ (volatile __int64*) value, (__int64) new_value, (__int64) expected_value);
if (actual_value == expected_value) {
return true;
}
@@ -259,7 +261,7 @@
static inline size_t pthreadpool_decrement_fetch_relaxed_size_t(
pthreadpool_atomic_size_t* address)
{
- return (size_t) _InterlockedDecrement((long volatile*) address);
+ return (size_t) _InterlockedDecrement((volatile long*) address);
}
static inline bool pthreadpool_try_decrement_relaxed_size_t(
@@ -270,7 +272,7 @@
const size_t new_value = actual_value - 1;
const size_t expected_value = actual_value;
actual_value = _InterlockedCompareExchange(
- (long volatile*) value, (long) new_value, (long) expected_value);
+ (volatile long*) value, (long) new_value, (long) expected_value);
if (actual_value == expected_value) {
return true;
}
@@ -285,7 +287,191 @@
static inline void pthreadpool_fence_release() {
_mm_sfence();
}
-#else
+#elif defined(_MSC_VER) && defined(_M_ARM64)
+ typedef volatile uint32_t pthreadpool_atomic_uint32_t;
+ typedef volatile size_t pthreadpool_atomic_size_t;
+ typedef void *volatile pthreadpool_atomic_void_p;
+
+ static inline uint32_t pthreadpool_load_relaxed_uint32_t(
+ pthreadpool_atomic_uint32_t* address)
+ {
+ return (uint32_t) __iso_volatile_load32((const volatile __int32*) address);
+ }
+
+ static inline size_t pthreadpool_load_relaxed_size_t(
+ pthreadpool_atomic_size_t* address)
+ {
+ return (size_t) __iso_volatile_load64((const volatile __int64*) address);
+ }
+
+ static inline void* pthreadpool_load_relaxed_void_p(
+ pthreadpool_atomic_void_p* address)
+ {
+ return (void*) __iso_volatile_load64((const volatile __int64*) address);
+ }
+
+ static inline void pthreadpool_store_relaxed_uint32_t(
+ pthreadpool_atomic_uint32_t* address,
+ uint32_t value)
+ {
+ __iso_volatile_store32((volatile __int32*) address, (__int32) value);
+ }
+
+ static inline void pthreadpool_store_relaxed_size_t(
+ pthreadpool_atomic_size_t* address,
+ size_t value)
+ {
+ __iso_volatile_store64((volatile __int64*) address, (__int64) value);
+ }
+
+ static inline void pthreadpool_store_relaxed_void_p(
+ pthreadpool_atomic_void_p* address,
+ void* value)
+ {
+ __iso_volatile_store64((volatile __int64*) address, (__int64) value);
+ }
+
+ static inline void pthreadpool_store_release_uint32_t(
+ pthreadpool_atomic_uint32_t* address,
+ uint32_t value)
+ {
+ _WriteBarrier();
+ __stlr32((unsigned __int32 volatile*) address, (unsigned __int32) value);
+ }
+
+ static inline void pthreadpool_store_release_size_t(
+ pthreadpool_atomic_size_t* address,
+ size_t value)
+ {
+ _WriteBarrier();
+ __stlr64((unsigned __int64 volatile*) address, (unsigned __int64) value);
+ }
+
+ static inline size_t pthreadpool_decrement_fetch_relaxed_size_t(
+ pthreadpool_atomic_size_t* address)
+ {
+ return (size_t) _InterlockedDecrement64_nf((volatile __int64*) address);
+ }
+
+ static inline bool pthreadpool_try_decrement_relaxed_size_t(
+ pthreadpool_atomic_size_t* value)
+ {
+ size_t actual_value = (size_t) __iso_volatile_load64((const volatile __int64*) value);
+ while (actual_value != 0) {
+ const size_t new_value = actual_value - 1;
+ const size_t expected_value = actual_value;
+ actual_value = _InterlockedCompareExchange64_nf(
+ (volatile __int64*) value, (__int64) new_value, (__int64) expected_value);
+ if (actual_value == expected_value) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ static inline void pthreadpool_fence_acquire() {
+ __dmb(_ARM64_BARRIER_ISHLD);
+ _ReadBarrier();
+ }
+
+ static inline void pthreadpool_fence_release() {
+ _WriteBarrier();
+ __dmb(_ARM64_BARRIER_ISH);
+ }
+#elif defined(_MSC_VER) && defined(_M_ARM)
+ typedef volatile uint32_t pthreadpool_atomic_uint32_t;
+ typedef volatile size_t pthreadpool_atomic_size_t;
+ typedef void *volatile pthreadpool_atomic_void_p;
+
+ static inline uint32_t pthreadpool_load_relaxed_uint32_t(
+ pthreadpool_atomic_uint32_t* address)
+ {
+ return (uint32_t) __iso_volatile_load32((const volatile __int32*) address);
+ }
+
+ static inline size_t pthreadpool_load_relaxed_size_t(
+ pthreadpool_atomic_size_t* address)
+ {
+ return (size_t) __iso_volatile_load32((const volatile __int32*) address);
+ }
+
+ static inline void* pthreadpool_load_relaxed_void_p(
+ pthreadpool_atomic_void_p* address)
+ {
+ return (void*) __iso_volatile_load32((const volatile __int32*) address);
+ }
+
+ static inline void pthreadpool_store_relaxed_uint32_t(
+ pthreadpool_atomic_uint32_t* address,
+ uint32_t value)
+ {
+ __iso_volatile_store32((volatile __int32*) address, (__int32) value);
+ }
+
+ static inline void pthreadpool_store_relaxed_size_t(
+ pthreadpool_atomic_size_t* address,
+ size_t value)
+ {
+ __iso_volatile_store32((volatile __int32*) address, (__int32) value);
+ }
+
+ static inline void pthreadpool_store_relaxed_void_p(
+ pthreadpool_atomic_void_p* address,
+ void* value)
+ {
+ __iso_volatile_store32((volatile __int32*) address, (__int32) value);
+ }
+
+ static inline void pthreadpool_store_release_uint32_t(
+ pthreadpool_atomic_uint32_t* address,
+ uint32_t value)
+ {
+ _WriteBarrier();
+ __dmb(_ARM_BARRIER_ISH);
+ __iso_volatile_store32((volatile __int32*) address, (__int32) value);
+ }
+
+ static inline void pthreadpool_store_release_size_t(
+ pthreadpool_atomic_size_t* address,
+ size_t value)
+ {
+ _WriteBarrier();
+ __dmb(_ARM_BARRIER_ISH);
+ __iso_volatile_store32((volatile __int32*) address, (__int32) value);
+ }
+
+ static inline size_t pthreadpool_decrement_fetch_relaxed_size_t(
+ pthreadpool_atomic_size_t* address)
+ {
+ return (size_t) _InterlockedDecrement_nf((volatile long*) address);
+ }
+
+ static inline bool pthreadpool_try_decrement_relaxed_size_t(
+ pthreadpool_atomic_size_t* value)
+ {
+ size_t actual_value = (size_t) __iso_volatile_load32((const volatile __int32*) value);
+ while (actual_value != 0) {
+ const size_t new_value = actual_value - 1;
+ const size_t expected_value = actual_value;
+ actual_value = _InterlockedCompareExchange_nf(
+ (volatile long*) value, (long) new_value, (long) expected_value);
+ if (actual_value == expected_value) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ static inline void pthreadpool_fence_acquire() {
+ __dmb(_ARM_BARRIER_ISH);
+ _ReadBarrier();
+ }
+
+ static inline void pthreadpool_fence_release() {
+ _WriteBarrier();
+ __dmb(_ARM_BARRIER_ISH);
+ }
+#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
#include <stdatomic.h>
typedef _Atomic(uint32_t) pthreadpool_atomic_uint32_t;
@@ -384,4 +570,6 @@
static inline void pthreadpool_fence_release() {
atomic_thread_fence(memory_order_release);
}
+#else
+ #error "Platform-specific implementation of threadpool-atomics.h required"
#endif
diff --git a/src/threadpool-utils.h b/src/threadpool-utils.h
index e1e96c5..24fee43 100644
--- a/src/threadpool-utils.h
+++ b/src/threadpool-utils.h
@@ -11,7 +11,9 @@
/* MSVC-specific headers */
#if defined(_MSC_VER) && _MSC_VER >= 1920
#include <intrin.h>
- #include <immintrin.h>
+ #if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64)
+ #include <immintrin.h>
+ #endif
#endif
diff --git a/src/windows.c b/src/windows.c
index 144da9d..e68b250 100644
--- a/src/windows.c
+++ b/src/windows.c
@@ -11,12 +11,6 @@
/* Windows headers */
#include <windows.h>
-/* MSVC-specific headers */
-#ifdef _MSC_VER
- #include <intrin.h>
- #include <immintrin.h>
-#endif
-
/* Public library header */
#include <pthreadpool.h>