#ifndef AO_STACK_H
#define AO_STACK_H
#include "atomic_ops.h"
#ifndef AO_HAVE_double_t
# include "atomic_ops/sysdeps/standard_ao_double_t.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifdef AO_USE_ALMOST_LOCK_FREE
#elif defined(AO_HAVE_compare_double_and_swap_double) \
&& !defined(AO_FAT_POINTER) && !defined(AO_STACK_USE_CPTR)
# define AO_STACK_IS_LOCK_FREE
#elif !defined(AO_HAVE_compare_and_swap)
# define AO_STACK_IS_LOCK_FREE
#else
# define AO_USE_ALMOST_LOCK_FREE
#endif
#ifndef AO_BL_SIZE
# define AO_BL_SIZE 2
#endif
#if defined(AO_FAT_POINTER) && defined(__LP64__)
# define AO_N_BITS 4
#elif defined(__LP64__) || defined(_LP64) || defined(_WIN64) \
|| defined(AO_FAT_POINTER)
# define AO_N_BITS 3
#else
# define AO_N_BITS 2
#endif
#define AO_BIT_MASK ((1 << AO_N_BITS) - 1)
#if AO_BL_SIZE > (1 << AO_N_BITS)
# error AO_BL_SIZE too big
#endif
#ifndef AO_STACK_ATTR_ALLIGNED
# if AO_BL_SIZE == 1
# define AO_STACK_ATTR_ALLIGNED
# elif AO_GNUC_PREREQ(3, 1)
# define AO_STACK_LOG_BL_SZP1 (AO_BL_SIZE > 7 ? 4 : AO_BL_SIZE > 3 ? 3 : 2)
# define AO_STACK_ATTR_ALLIGNED \
__attribute__((__aligned__(sizeof(void*) << AO_STACK_LOG_BL_SZP1)))
# elif defined(_MSC_VER) && _MSC_VER >= 1400
# if AO_N_BITS > 2 && AO_BL_SIZE > 7
# define AO_STACK_ALLIGN_N 128
# elif (AO_N_BITS > 2 && AO_BL_SIZE > 3) || AO_BL_SIZE > 7
# define AO_STACK_ALLIGN_N 64
# elif AO_N_BITS > 2 || AO_BL_SIZE > 3
# define AO_STACK_ALLIGN_N 32
# else
# define AO_STACK_ALLIGN_N 16
# endif
# define AO_STACK_ATTR_ALLIGNED __declspec(align(AO_STACK_ALLIGN_N))
# else
# define AO_STACK_ATTR_ALLIGNED
# endif
#endif
#if defined(__e2k__) && defined(AO_FAT_POINTER) || defined(AO_STACK_USE_CPTR)
typedef char *AO_internal_ptr_t;
# ifndef AO_STACK_USE_CPTR
# define AO_STACK_USE_CPTR
# endif
#else
typedef AO_uintptr_t AO_internal_ptr_t;
#endif
typedef struct AO__stack_aux {
AO_internal_ptr_t volatile AO_stack_bl[AO_BL_SIZE];
} AO_stack_aux;
struct AO__stack_ptr_aux {
AO_internal_ptr_t volatile AO_ptr;
AO_stack_aux AO_aux;
};
typedef union AO__stack {
AO_STACK_ATTR_ALLIGNED struct AO__stack_ptr_aux AO_pa;
volatile AO_double_t AO_vp;
} AO_stack_t;
#define AO_STACK_INITIALIZER { { 0, { {0} } } }
#ifdef AO_USE_ALMOST_LOCK_FREE
AO_API void AO_stack_push_explicit_aux_release(
volatile AO_uintptr_t * ,
AO_uintptr_t * ,
AO_stack_aux *);
AO_API AO_uintptr_t *AO_stack_pop_explicit_aux_acquire(
volatile AO_uintptr_t * ,
AO_stack_aux *);
#endif
#ifndef AO_REAL_PTR_AS_MACRO
# define AO_REAL_NEXT_PTR(x) AO_stack_next_ptr_d(&(x))
# define AO_REAL_HEAD_PTR(x) AO_stack_head_ptr(&(x))
#elif defined(AO_USE_ALMOST_LOCK_FREE)
# ifdef AO_STACK_USE_CPTR
# define AO_REAL_NEXT_PTR(x) \
((AO_uintptr_t *)AO_real_next_ptr_i(*(const AO_internal_ptr_t *)&(x)))
AO_INLINE AO_internal_ptr_t
AO_real_next_ptr_i(AO_internal_ptr_t next)
{
return next - ((unsigned)(AO_uintptr_t)next & AO_BIT_MASK);
}
# else
# define AO_REAL_NEXT_PTR(x) \
(AO_uintptr_t *)((x) & ~(AO_uintptr_t)AO_BIT_MASK)
# endif
# define AO_REAL_HEAD_PTR(x) \
AO_REAL_NEXT_PTR(*(volatile AO_uintptr_t *)&(&(x))->AO_pa.AO_ptr)
#else
# define AO_REAL_NEXT_PTR(x) ((AO_t *)*(&(x)))
# define AO_REAL_HEAD_PTR(x) (AO_t *)((&(x))->AO_vp.AO_val2 )
#endif
AO_API void AO_stack_push_release(AO_stack_t *,
AO_uintptr_t * );
#define AO_HAVE_stack_push_release
#define AO_stack_push(l, e) AO_stack_push_release(l, e)
#define AO_HAVE_stack_push
AO_API AO_uintptr_t *AO_stack_pop_acquire(AO_stack_t *);
#define AO_HAVE_stack_pop_acquire
#define AO_stack_pop(l) AO_stack_pop_acquire(l)
#define AO_HAVE_stack_pop
AO_API void AO_stack_init(AO_stack_t *);
AO_API int AO_stack_is_lock_free(void);
AO_API AO_uintptr_t *AO_stack_head_ptr(const AO_stack_t *);
AO_API AO_uintptr_t *AO_stack_next_ptr(AO_uintptr_t);
AO_API AO_uintptr_t *AO_stack_next_ptr_d(const AO_uintptr_t * );
#ifdef __cplusplus
}
#endif
#endif