aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMarat Dukhan <maratek@google.com>2020-03-23 10:47:42 -0700
committerMarat Dukhan <maratek@google.com>2020-03-23 10:47:42 -0700
commit832403f32df1920f2bc4678b9541668fec7238f3 (patch)
tree78a5e6a6e7bb79cc65885be665e146b1d3914666 /src
parent2e59d6fa7d1bfd3c32797bd5a838d558a9e97377 (diff)
downloadpthreadpool-832403f32df1920f2bc4678b9541668fec7238f3.tar.gz
Implement atomic_decrement with LL-SC on ARM/ARM64
Diffstat (limited to 'src')
-rw-r--r--src/threadpool-pthreads.c26
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) {