summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Maidanski <ivmai@mail.ru>2022-02-15 09:48:31 +0300
committerIvan Maidanski <ivmai@mail.ru>2022-02-15 13:05:58 +0300
commitb2d599ba43ad12c2f631ad31c47d993ca208b0e1 (patch)
tree8f7f7b93274896b028a1ac4f110f5736364945ef
parent2d62edfd534102ed0f0c7878e92dea07dc76dc3e (diff)
downloadlibatomic_ops-b2d599ba43ad12c2f631ad31c47d993ca208b0e1.tar.gz
Define AO_stack_t uniformly
Now AO_stack_t definition does not depend on whether the implementation is almost or fully lock-free. * src/atomic_ops_stack.c [USE_ALMOST_LOCK_FREE] (AO_stack_push_release, AO_stack_pop_acquire): Update access to list after changing its type to a union. * src/atomic_ops_stack.c [!USE_ALMOST_LOCK_FREE] (version, ptr, AO_stack_pop_acquire, AO_stack_push_release): Likewise. * src/atomic_ops_stack.h (AO_REAL_HEAD_PTR): Likewise. * src/atomic_ops_stack.c [!USE_ALMOST_LOCK_FREE && (!AO_HAVE_compare_double_and_swap_double || AO_STACK_PREFER_CAS_DOUBLE) && AO_HAVE_compare_and_swap_double] (AO_stack_push_release): Rename version local variable to cversion. * src/atomic_ops_stack.c [!USE_ALMOST_LOCK_FREE] (ptr, version): Undefine (after last use). * src/atomic_ops_stack.h [!AO_HAVE_double_t]: Move include standard_ao_double_t.h upper to be before ifdef USE_ALMOST_LOCK_FREE. * src/atomic_ops_stack.h [!AO_BL_SIZE] (AO_BL_SIZE): Refine comment. * src/atomic_ops_stack.h (AO_BL_SIZE, AO_N_BITS, AO_BIT_MASK): Define even if not USE_ALMOST_LOCK_FREE. * src/atomic_ops_stack.h (AO__stack_ptr_aux): New struct type. * src/atomic_ops_stack.h (AO_stack_t): Change to union; define identically regardless of USE_ALMOST_LOCK_FREE; improve comment. * src/atomic_ops_stack.h (AO_STACK_INITIALIZER): Define identically regardless of USE_ALMOST_LOCK_FREE; add comment.
-rw-r--r--src/atomic_ops_stack.c28
-rw-r--r--src/atomic_ops_stack.h98
2 files changed, 63 insertions, 63 deletions
diff --git a/src/atomic_ops_stack.c b/src/atomic_ops_stack.c
index 28eba64..0f23fdf 100644
--- a/src/atomic_ops_stack.c
+++ b/src/atomic_ops_stack.c
@@ -222,12 +222,14 @@ AO_API void AO_stack_init(AO_stack_t *list)
AO_API void AO_stack_push_release(AO_stack_t *list, AO_t *x)
{
- AO_stack_push_explicit_aux_release(&list->AO_ptr, x, &list->AO_aux);
+ AO_stack_push_explicit_aux_release(&list->AO_pa.AO_ptr, x,
+ &list->AO_pa.AO_aux);
}
AO_API AO_t *AO_stack_pop_acquire(AO_stack_t *list)
{
- return AO_stack_pop_explicit_aux_acquire(&list->AO_ptr, &list->AO_aux);
+ return AO_stack_pop_explicit_aux_acquire(&list->AO_pa.AO_ptr,
+ &list->AO_pa.AO_aux);
}
#else /* ! USE_ALMOST_LOCK_FREE */
@@ -254,8 +256,8 @@ AO_API void AO_stack_init(AO_stack_t *list)
# endif /* !AO_THREAD_SANITIZER */
/* Better names for fields in AO_stack_t. */
-# define ptr AO_val2
-# define version AO_val1
+# define version AO_vp.AO_val1
+# define ptr AO_vp.AO_val2
# if defined(AO_HAVE_compare_double_and_swap_double) \
&& !(defined(AO_STACK_PREFER_CAS_DOUBLE) \
@@ -303,9 +305,9 @@ AO_API void AO_stack_init(AO_stack_t *list)
if (NULL == cptr)
return NULL;
next = load_before_cas((AO_t *)cptr);
- } while (AO_EXPECT_FALSE(!AO_compare_double_and_swap_double_release(list,
- cversion, (AO_t)cptr,
- cversion+1, (AO_t)next)));
+ } while (AO_EXPECT_FALSE(!AO_compare_double_and_swap_double_release(
+ &list->AO_vp, cversion, (AO_t)cptr,
+ cversion+1, (AO_t)next)));
return cptr;
}
@@ -319,17 +321,17 @@ AO_API void AO_stack_init(AO_stack_t *list)
/* for an unchanged version number, not an unchanged pointer. */
AO_API void AO_stack_push_release(AO_stack_t *list, AO_t *element)
{
- AO_t version;
+ AO_t cversion;
do {
AO_t next_ptr;
/* Again version must be loaded first, for different reason. */
- version = AO_load_acquire(&list->version);
+ cversion = AO_load_acquire(&list->version);
next_ptr = AO_load(&list->ptr);
store_before_cas(element, next_ptr);
- } while (!AO_compare_and_swap_double_release(list, version, version+1,
- (AO_t)element));
+ } while (!AO_compare_and_swap_double_release(&list->AO_vp, cversion,
+ cversion+1, (AO_t)element));
}
AO_API AO_t *AO_stack_pop_acquire(AO_stack_t *list)
@@ -344,10 +346,12 @@ AO_API void AO_stack_init(AO_stack_t *list)
if (NULL == cptr)
return NULL;
next = load_before_cas(cptr);
- } while (!AO_compare_double_and_swap_double_release(list,
+ } while (!AO_compare_double_and_swap_double_release(&list->AO_vp,
cversion, (AO_t)cptr, cversion+1, next));
return cptr;
}
# endif /* AO_HAVE_compare_and_swap_double */
+# undef ptr
+# undef version
#endif /* ! USE_ALMOST_LOCK_FREE */
diff --git a/src/atomic_ops_stack.h b/src/atomic_ops_stack.h
index 642026e..ef54d16 100644
--- a/src/atomic_ops_stack.h
+++ b/src/atomic_ops_stack.h
@@ -31,6 +31,12 @@
#include "atomic_ops.h"
+#ifndef AO_HAVE_double_t
+ /* Can happen if we are using CAS emulation, since we do not want to */
+ /* force that here, in case other atomic_ops clients do not want it. */
+# include "atomic_ops/sysdeps/standard_ao_double_t.h"
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -73,31 +79,49 @@
* compare-and-swap operations are available.
*/
-#ifdef AO_USE_ALMOST_LOCK_FREE
+/* AO_stack_aux should be treated as opaque. It is fully defined */
+/* here, so it can be allocated, and also to facilitate debugging. */
+/* Note: changing the value of AO_BL_SIZE leads to the ABI change. */
+#ifndef AO_BL_SIZE
+# define AO_BL_SIZE 2
+#endif
- /* The number of low order pointer bits we can use for a small */
- /* version number. */
-# if defined(__LP64__) || defined(_LP64) || defined(_WIN64)
-# define AO_N_BITS 3
-# else
-# define AO_N_BITS 2
-# endif
+/* The number of low order pointer bits we can use for a small */
+/* version number. */
+#if defined(__LP64__) || defined(_LP64) || defined(_WIN64)
+# define AO_N_BITS 3
+#else
+# define AO_N_BITS 2
+#endif
-# define AO_BIT_MASK ((1 << AO_N_BITS) - 1)
+#define AO_BIT_MASK ((1 << AO_N_BITS) - 1)
+
+#if AO_BL_SIZE > (1 << AO_N_BITS)
+# error AO_BL_SIZE too big
+#endif
- /* AO_stack_aux should be treated as opaque. It is fully defined */
- /* here, so it can be allocated, and to facilitate debugging. */
-# ifndef AO_BL_SIZE
-# define AO_BL_SIZE 2
-# endif
+typedef struct AO__stack_aux {
+ volatile AO_t AO_stack_bl[AO_BL_SIZE];
+} AO_stack_aux;
-# if AO_BL_SIZE > (1 << AO_N_BITS)
-# error AO_BL_SIZE too big
-# endif
+struct AO__stack_ptr_aux {
+ volatile AO_t AO_ptr;
+ AO_stack_aux AO_aux;
+};
- typedef struct AO__stack_aux {
- volatile AO_t AO_stack_bl[AO_BL_SIZE];
- } AO_stack_aux;
+/* The AO stack type. Should be treated as opaque. */
+/* Note: AO_stack_t variables are not intended to be local ones, */
+/* otherwise it is the client responsibility to ensure they have */
+/* double-word alignment. */
+typedef union AO__stack {
+ struct AO__stack_ptr_aux AO_pa;
+ volatile AO_double_t AO_vp;
+} AO_stack_t;
+
+/* The static initializer of the AO stack type. */
+#define AO_STACK_INITIALIZER { /* .AO_pa= */ { 0, { {0} } } }
+
+#ifdef AO_USE_ALMOST_LOCK_FREE
/* The stack implementation knows only about the location of */
/* link fields in nodes, and nothing about the rest of the */
@@ -110,6 +134,7 @@
/* The following two routines should not normally be used directly. */
/* We make them visible here for the rare cases in which it makes */
/* sense to share the AO_stack_aux between stacks. */
+
AO_API void
AO_stack_push_explicit_aux_release(volatile AO_t *list, AO_t *x,
AO_stack_aux *);
@@ -117,42 +142,13 @@
AO_API AO_t *
AO_stack_pop_explicit_aux_acquire(volatile AO_t *list, AO_stack_aux *);
- /* And now AO_stack_t for the real interface: */
-
- typedef struct AO__stack {
- volatile AO_t AO_ptr;
- AO_stack_aux AO_aux;
- } AO_stack_t;
-
-# define AO_STACK_INITIALIZER {0,{{0}}}
-
/* Convert an AO_stack_t to a pointer to the link field in */
/* the first element. */
-# define AO_REAL_HEAD_PTR(x) AO_REAL_NEXT_PTR((x).AO_ptr)
+# define AO_REAL_HEAD_PTR(x) AO_REAL_NEXT_PTR((x).AO_pa.AO_ptr)
#else /* Use fully non-blocking data structure, wide CAS. */
-# ifndef AO_HAVE_double_t
- /* Can happen if we are using CAS emulation, since we don't want to */
- /* force that here, in case other atomic_ops clients don't want it. */
-# ifdef __cplusplus
- } /* extern "C" */
-# endif
-# include "atomic_ops/sysdeps/standard_ao_double_t.h"
-# ifdef __cplusplus
- extern "C" {
-# endif
-# endif
-
- typedef volatile AO_double_t AO_stack_t;
- /* AO_val1 is version, AO_val2 is pointer. */
- /* Note: AO_stack_t variables are not intended to be local ones, */
- /* otherwise it is the client responsibility to ensure they have */
- /* double-word alignment. */
-
-# define AO_STACK_INITIALIZER AO_DOUBLE_T_INITIALIZER
-
-# define AO_REAL_HEAD_PTR(x) (AO_t *)((x).AO_val2)
+# define AO_REAL_HEAD_PTR(x) (AO_t *)((x).AO_vp.AO_val2)
# define AO_REAL_NEXT_PTR(x) (AO_t *)(x)
#endif /* !AO_USE_ALMOST_LOCK_FREE */