aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarat Dukhan <maratek@google.com>2020-12-05 17:54:08 -0800
committerMarat Dukhan <maratek@google.com>2020-12-05 17:57:34 -0800
commit6c76abee85c7bf2b0c9be2d05bc97b4e5d109d16 (patch)
treeb3f3593cbfb7954ebcdfb7bd2efccb293a8a0161
parentfa75e65a58a5c70c09c30d17a1fe1c1dff1093ae (diff)
downloadpthreadpool-6c76abee85c7bf2b0c9be2d05bc97b4e5d109d16.tar.gz
Support pre-C11 GCC intrinsics for atomics
-rw-r--r--src/threadpool-atomics.h104
1 files changed, 104 insertions, 0 deletions
diff --git a/src/threadpool-atomics.h b/src/threadpool-atomics.h
index e6e4233..366a8db 100644
--- a/src/threadpool-atomics.h
+++ b/src/threadpool-atomics.h
@@ -247,6 +247,110 @@
static inline void pthreadpool_fence_release() {
atomic_thread_fence(memory_order_release);
}
+#elif defined(__GNUC__)
+ typedef uint32_t volatile pthreadpool_atomic_uint32_t;
+ typedef size_t volatile 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 *address;
+ }
+
+ static inline size_t pthreadpool_load_relaxed_size_t(
+ pthreadpool_atomic_size_t* address)
+ {
+ return *address;
+ }
+
+ static inline void* pthreadpool_load_relaxed_void_p(
+ pthreadpool_atomic_void_p* address)
+ {
+ return *address;
+ }
+
+ static inline uint32_t pthreadpool_load_acquire_uint32_t(
+ pthreadpool_atomic_uint32_t* address)
+ {
+ return *address;
+ }
+
+ static inline size_t pthreadpool_load_acquire_size_t(
+ pthreadpool_atomic_size_t* address)
+ {
+ return *address;
+ }
+
+ static inline void pthreadpool_store_relaxed_uint32_t(
+ pthreadpool_atomic_uint32_t* address,
+ uint32_t value)
+ {
+ *address = value;
+ }
+
+ static inline void pthreadpool_store_relaxed_size_t(
+ pthreadpool_atomic_size_t* address,
+ size_t value)
+ {
+ *address = value;
+ }
+
+ static inline void pthreadpool_store_relaxed_void_p(
+ pthreadpool_atomic_void_p* address,
+ void* value)
+ {
+ *address = value;
+ }
+
+ static inline void pthreadpool_store_release_uint32_t(
+ pthreadpool_atomic_uint32_t* address,
+ uint32_t value)
+ {
+ *address = value;
+ }
+
+ static inline void pthreadpool_store_release_size_t(
+ pthreadpool_atomic_size_t* address,
+ size_t value)
+ {
+ *address = value;
+ }
+
+ static inline size_t pthreadpool_decrement_fetch_relaxed_size_t(
+ pthreadpool_atomic_size_t* address)
+ {
+ return __sync_sub_and_fetch(address, 1);
+ }
+
+ static inline size_t pthreadpool_decrement_fetch_release_size_t(
+ pthreadpool_atomic_size_t* address)
+ {
+ return __sync_sub_and_fetch(address, 1);
+ }
+
+ static inline bool pthreadpool_try_decrement_relaxed_size_t(
+ pthreadpool_atomic_size_t* value)
+ {
+ size_t actual_value = *value;
+ while (actual_value != 0) {
+ const size_t new_value = actual_value - 1;
+ const size_t expected_value = actual_value;
+ actual_value = __sync_val_compare_and_swap(value, expected_value, new_value);
+ if (actual_value == expected_value) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ static inline void pthreadpool_fence_acquire() {
+ __sync_synchronize();
+ }
+
+ static inline void pthreadpool_fence_release() {
+ __sync_synchronize();
+ }
#elif defined(_MSC_VER) && defined(_M_X64)
typedef volatile uint32_t pthreadpool_atomic_uint32_t;
typedef volatile size_t pthreadpool_atomic_size_t;