diff options
author | Marat Dukhan <maratek@google.com> | 2020-03-23 10:47:42 -0700 |
---|---|---|
committer | Marat Dukhan <maratek@google.com> | 2020-03-23 10:47:42 -0700 |
commit | 832403f32df1920f2bc4678b9541668fec7238f3 (patch) | |
tree | 78a5e6a6e7bb79cc65885be665e146b1d3914666 /src | |
parent | 2e59d6fa7d1bfd3c32797bd5a838d558a9e97377 (diff) | |
download | pthreadpool-832403f32df1920f2bc4678b9541668fec7238f3.tar.gz |
Implement atomic_decrement with LL-SC on ARM/ARM64
Diffstat (limited to 'src')
-rw-r--r-- | src/threadpool-pthreads.c | 26 |
1 files changed, 19 insertions, 7 deletions
diff --git a/src/threadpool-pthreads.c b/src/threadpool-pthreads.c index 07c47f0..934e5e7 100644 --- a/src/threadpool-pthreads.c +++ b/src/threadpool-pthreads.c @@ -289,16 +289,28 @@ static void wait_worker_threads(struct pthreadpool* threadpool) { } inline static bool atomic_decrement(pthreadpool_atomic_size_t* value) { - size_t actual_value = pthreadpool_load_relaxed_size_t(value); - if (actual_value == 0) { - return false; - } - while (!pthreadpool_compare_exchange_weak_relaxed_size_t(value, &actual_value, actual_value - 1)) { + #if defined(__clang__) && (defined(__arm__) || defined(__aarch64__)) + size_t actual_value; + do { + actual_value = __builtin_arm_ldrex((const volatile size_t*) value); + if (actual_value == 0) { + __builtin_arm_clrex(); + return false; + } + } while (__builtin_arm_strex(actual_value - 1, (volatile size_t*) value) != 0); + return true; + #else + size_t actual_value = pthreadpool_load_relaxed_size_t(value); if (actual_value == 0) { return false; } - } - return true; + while (!pthreadpool_compare_exchange_weak_relaxed_size_t(value, &actual_value, actual_value - 1)) { + if (actual_value == 0) { + return false; + } + } + return true; + #endif } inline static size_t modulo_decrement(uint32_t i, uint32_t n) { |