From d29c0910d85c5ca14c2f49a08ddc9149d23a6a88 Mon Sep 17 00:00:00 2001 From: Ivan Maidanski Date: Tue, 15 Feb 2022 09:55:13 +0300 Subject: Do not expose AO_REAL_HEAD/NEXT_PTR implementation in header by default Now AO_REAL_HEAD_PTR() and AO_REAL_NEXT_PTR() macros definition does not depend on whether the implementation is almost or fully lock-free. These macros just call the relevant implementation-dependent API function (AO_real_head_ptr or AO_real_next_ptr, respectively). If needed, the client could define AO_REAL_PTR_AS_MACRO (prior to include atomic_ops_stack.h) to continue using implementation-dependent definition of AO_REAL_HEAD_PTR and AO_REAL_NEXT_PTR macros. * src/atomic_ops_stack.c [!AO_REAL_PTR_AS_MACRO] (AO_REAL_PTR_AS_MACRO): Define (before include atomic_ops_stack.h). * src/atomic_ops_stack.c (AO_real_head_ptr, AO_real_next_ptr): Implement. * src/atomic_ops_stack.h [AO_USE_ALMOST_LOCK_FREE] (AO_stack_push_explicit_aux_release): Rename argument. * src/atomic_ops_stack.h [!AO_REAL_PTR_AS_MACRO] (AO_REAL_NEXT_PTR, AO_REAL_HEAD_PTR): Redirect to AO_real_next_ptr/AO_real_head_ptr(). * src/atomic_ops_stack.h (AO_stack_init): Move declaration down (to be after AO_stack_pop). * src/atomic_ops_stack.h (AO_real_head_ptr, AO_real_next_ptr): Declare AO_API function. --- src/atomic_ops_stack.c | 14 ++++++++++++++ src/atomic_ops_stack.h | 41 +++++++++++++++++++++++------------------ 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/src/atomic_ops_stack.c b/src/atomic_ops_stack.c index 0f23fdf..364f84c 100644 --- a/src/atomic_ops_stack.c +++ b/src/atomic_ops_stack.c @@ -23,6 +23,10 @@ # define AO_BUILD #endif +#ifndef AO_REAL_PTR_AS_MACRO +# define AO_REAL_PTR_AS_MACRO +#endif + #define AO_REQUIRE_CAS #include "atomic_ops_stack.h" @@ -31,6 +35,16 @@ AO_API void AO_stack_init(AO_stack_t *list) memset((char *)list, 0, sizeof(list)); } +AO_API AO_t *AO_real_head_ptr(const AO_stack_t *list) +{ + return AO_REAL_HEAD_PTR(*list); +} + +AO_API AO_t *AO_real_next_ptr(AO_t next) +{ + return AO_REAL_NEXT_PTR(next); +} + /* This function call must be a part of a do-while loop with a CAS */ /* designating the condition of the loop (see the use cases below). */ #ifdef AO_THREAD_SANITIZER diff --git a/src/atomic_ops_stack.h b/src/atomic_ops_stack.h index ef54d16..a1dc60d 100644 --- a/src/atomic_ops_stack.h +++ b/src/atomic_ops_stack.h @@ -122,38 +122,38 @@ typedef union AO__stack { #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 */ - /* stack elements. Link fields hold an AO_t, which is not */ - /* necessarily a real pointer. This converts the AO_t to a */ - /* real (AO_t *) which is either NULL, or points at the link */ - /* field in the next node. */ -# define AO_REAL_NEXT_PTR(x) (AO_t *)((x) & ~AO_BIT_MASK) - /* 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_push_explicit_aux_release(volatile AO_t *list, AO_t *new_element, AO_stack_aux *); AO_API AO_t * AO_stack_pop_explicit_aux_acquire(volatile AO_t *list, AO_stack_aux *); +#endif /* AO_USE_ALMOST_LOCK_FREE */ + +#ifndef AO_REAL_PTR_AS_MACRO + /* The stack implementation knows only about the location of */ + /* link fields in nodes, and nothing about the rest of the */ + /* stack elements. Link fields hold an AO_t, which is not */ + /* necessarily a real pointer. This converts the AO_t to a */ + /* real (AO_t *) which is either NULL, or points at the link */ + /* field in the next node. */ +# define AO_REAL_NEXT_PTR(x) AO_real_next_ptr(x) /* 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_pa.AO_ptr) - -#else /* Use fully non-blocking data structure, wide CAS. */ +# define AO_REAL_HEAD_PTR(x) AO_real_head_ptr(&(x)) -# define AO_REAL_HEAD_PTR(x) (AO_t *)((x).AO_vp.AO_val2) +#elif defined(AO_USE_ALMOST_LOCK_FREE) +# define AO_REAL_NEXT_PTR(x) (AO_t *)((x) & ~AO_BIT_MASK) +# define AO_REAL_HEAD_PTR(x) AO_REAL_NEXT_PTR((x).AO_pa.AO_ptr) +#else # define AO_REAL_NEXT_PTR(x) (AO_t *)(x) - -#endif /* !AO_USE_ALMOST_LOCK_FREE */ - -AO_API void AO_stack_init(AO_stack_t *list); +# define AO_REAL_HEAD_PTR(x) (AO_t *)((x).AO_vp.AO_val2 /* ptr */) +#endif /* AO_REAL_PTR_AS_MACRO && !AO_USE_ALMOST_LOCK_FREE */ AO_API void AO_stack_push_release(AO_stack_t *list, AO_t *new_element); #define AO_HAVE_stack_push_release @@ -167,6 +167,11 @@ AO_API AO_t *AO_stack_pop_acquire(AO_stack_t *list); #define AO_stack_pop(l) AO_stack_pop_acquire(l) #define AO_HAVE_stack_pop +AO_API void AO_stack_init(AO_stack_t *list); + +AO_API AO_t *AO_real_head_ptr(const AO_stack_t *list); +AO_API AO_t *AO_real_next_ptr(AO_t /* next */); + #ifdef __cplusplus } /* extern "C" */ #endif -- cgit v1.2.1