summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHans Boehm <boehm@acm.org>2016-08-15 11:32:33 +0300
committerIvan Maidanski <ivmai@mail.ru>2016-08-15 11:32:33 +0300
commit85dd735949d712fa5db4bde0f0fc74f15a624222 (patch)
treeeca7106b4a660a2f93e50ccce4912abf96d07894 /src
parentdbb03137bf0ed891c4ebe981fa4ae20ab0a3aaeb (diff)
downloadlibatomic_ops-85dd735949d712fa5db4bde0f0fc74f15a624222.tar.gz
Fix store-load ordering in AO_stack_pop_explicit_aux_acquire (PowerPC)
Issue #15. The core issue is that AO_stack_pop_explicit_aux_acquire really needs to ensure that the store to the blacklist via AO_compare_and_swap_acquire becomes visible before the load to check the list head. This effectively needs store-load ordering. Currently the only ordering here is imposed by the _acquire on the compare_and_swap. On PowerPC that turns into an lwsync, which is too weak to enforce store to load ordering. This patch should fix the issue. But this is suboptimal on x86, and we may want to make the fence conditional on "not x86", where the CAS already includes sufficient ordering. (With C++11 atomics, this would also be tricky and probably involve making a bunch of accesses seq_cst.) * src/atomic_ops_stack.c [AO_USE_ALMOST_LOCK_FREE] (AO_stack_pop_explicit_aux_acquire): Call AO_compare_and_swap instead of AO_compare_and_swap_acquire; call AO_nop_full just before (first != AO_load(list)).
Diffstat (limited to 'src')
-rw-r--r--src/atomic_ops_stack.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/src/atomic_ops_stack.c b/src/atomic_ops_stack.c
index 642bac0..55e5711 100644
--- a/src/atomic_ops_stack.c
+++ b/src/atomic_ops_stack.c
@@ -133,7 +133,7 @@ AO_stack_pop_explicit_aux_acquire(volatile AO_t *list, AO_stack_aux * a)
for (i = 0; ; )
{
if (PRECHECK(a -> AO_stack_bl[i])
- AO_compare_and_swap_acquire(a->AO_stack_bl+i, 0, first))
+ AO_compare_and_swap(a->AO_stack_bl+i, 0, first))
break;
++i;
if ( i >= AO_BL_SIZE )
@@ -151,6 +151,7 @@ AO_stack_pop_explicit_aux_acquire(volatile AO_t *list, AO_stack_aux * a)
/* We need to make sure that first is still the first entry on the */
/* list. Otherwise it's possible that a reinsertion of it was */
/* already started before we added the black list entry. */
+ AO_nop_full(); /* TODO: Suboptimal on x86 */
# if defined(__alpha__) && (__GNUC__ == 4)
if (first != AO_load(list))
/* Workaround __builtin_expect bug found in */