diff options
-rw-r--r-- | src/atomic_ops_stack.c | 14 | ||||
-rw-r--r-- | 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 |