X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=urcu%2Fuatomic%2Farm.h;h=95f32f3d47b497c79373c7fcbf71bb65c8aa5dda;hb=a4850cc6c0eb0a7a61086eca3076c2ea378ef65c;hp=e0016b8e3153572caac53956df86a5b612481c0c;hpb=bc2433a9853a945a825c244e9ccfe341b73b2ceb;p=userspace-rcu.git diff --git a/urcu/uatomic/arm.h b/urcu/uatomic/arm.h index e0016b8..95f32f3 100644 --- a/urcu/uatomic/arm.h +++ b/urcu/uatomic/arm.h @@ -1,7 +1,7 @@ #ifndef _URCU_ARCH_UATOMIC_ARM_H #define _URCU_ARCH_UATOMIC_ARM_H -/* +/* * Atomics for ARM. This approach is usable on kernels back to 2.6.15. * * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved. @@ -26,15 +26,29 @@ #include #include +#include #ifdef __cplusplus extern "C" { -#endif +#endif /* xchg */ -#define uatomic_xchg(addr, v) __sync_lock_test_and_set(addr, v) -#ifdef __cplusplus +/* + * Based on [1], __sync_lock_test_and_set() is not a full barrier, but + * instead only an acquire barrier. Given that uatomic_xchg() acts as + * both release and acquire barriers, we therefore need to have our own + * release barrier before this operation. + * + * [1] https://gcc.gnu.org/onlinedocs/gcc-4.1.0/gcc/Atomic-Builtins.html + */ +#define uatomic_xchg(addr, v) \ + ({ \ + cmm_smp_mb(); \ + __sync_lock_test_and_set(addr, v); \ + }) + +#ifdef __cplusplus } #endif