/* Copyright 2005 Chris Thomasson */


#ifndef AC_I686_H
#define AC_I686_H


#ifdef __cplusplus
extern "C"
{
#endif




/*****  i686 Specific API  *****/
#define AC_I686_CACHE_LINE 128
#define AC_I686_WORD_SIZE 4
#define AC_DECLSPEC_ALIGN_CACHE_LINE AC_DECLSPEC_ALIGN( AC_I686_CACHE_LINE )


#ifdef _MSC_VER 
typedef signed __int32 ac_i686_intword_t;
typedef unsigned __int32 ac_i686_uintword_t;
typedef signed __int16 ac_i686_intword2_t;
typedef unsigned __int16 ac_i686_uintword2_t;
#define ac_i686_pause() _asm pause

#else
typedef signed int ac_i686_intword_t;
typedef unsigned int ac_i686_uintword_t;
typedef signed int short ac_i686_intword2_t;
typedef unsigned int short ac_i686_uintword2_t;
#define ac_i686_pause() __asm__ __volatile__ ( "pause" )
#endif


typedef ac_i686_uintword_t ac_i686_flags_t;


#define ac_i686_pause_yield() ac_i686_pause(); sched_yield()




#ifdef _MSC_VER 
/* 4324: structure was padded due to __declspec(align()) */
#pragma warning ( disable : 4324 )
#pragma pack(1) 
#endif

/* MUST be four adjacent words */
typedef struct 
AC_DECLSPEC_PACKED 
ac_i686_node_
{
  struct ac_i686_node_ *next;
  struct ac_i686_node_ *lfgc_next;
  ac_fp_dtor_t fp_dtor;
  const void *state;

} ac_i686_node_t;


/* MUST be two adjacent words. front must be at offset 0 */
typedef struct 
AC_DECLSPEC_PACKED
ac_i686_stack_mpmc_
{
  ac_i686_node_t *front;
  ac_i686_uintword_t aba;

} ac_i686_stack_mpmc_t;


/* MUST be two adjacent words. front must be at offset 0 */
typedef struct 
AC_DECLSPEC_PACKED
ac_i686_queue_spsc_
{
  ac_i686_node_t *front;
  ac_i686_node_t *back;

} ac_i686_queue_spsc_t;


/* MUST be two adjacent words */
typedef struct
AC_DECLSPEC_PACKED
ac_i686_tls_
{
  struct ac_i686_lfgc_smr_ *lfgc_smr;
  ac_thread_t *thread;

} ac_i686_tls_t;


#ifdef _MSC_VER 
#pragma pack() 
/* 4324: structure was padded due to __declspec(align()) */
#pragma warning ( default : 4324 )
#endif




/* critical i686 atomic api compile time assertion */
AC_BUILD_DBG_ASSERT
( i686,
  sizeof( void* ) == AC_I686_WORD_SIZE &&
  sizeof( ac_fp_dtor_t ) == AC_I686_WORD_SIZE &&
  sizeof( ac_i686_node_t* ) == AC_I686_WORD_SIZE &&
  sizeof( ac_i686_tls_t* ) == AC_I686_WORD_SIZE &&
  sizeof( ac_i686_queue_spsc_t* ) == AC_I686_WORD_SIZE &&
  sizeof( struct ac_i686_lfgc_smr_* ) == AC_I686_WORD_SIZE &&
  sizeof( ac_thread_t* ) == AC_I686_WORD_SIZE &&
  sizeof( ac_i686_intword_t ) == AC_I686_WORD_SIZE &&
  sizeof( ac_i686_uintword_t ) == AC_I686_WORD_SIZE &&
  sizeof( ac_i686_intword2_t ) == AC_I686_WORD_SIZE / 2 &&
  sizeof( ac_i686_uintword2_t ) == AC_I686_WORD_SIZE / 2 &&
  sizeof( ac_i686_node_t ) == AC_I686_WORD_SIZE * 4 &&
  sizeof( ac_i686_queue_spsc_t ) ==  AC_I686_WORD_SIZE * 2 &&
  sizeof( ac_i686_tls_t ) == AC_I686_WORD_SIZE * 2 &&
  sizeof( ptrdiff_t ) == AC_I686_WORD_SIZE &&
  sizeof( size_t ) == AC_I686_WORD_SIZE );




AC_SYS_APIEXPORT 
void AC_CDECL
ac_i686_mb_fence
( void );


AC_SYS_APIEXPORT 
ac_i686_intword_t AC_CDECL
ac_i686_mb_load_fence
( ac_i686_intword_t* );
      

AC_SYS_APIEXPORT 
ac_i686_intword_t AC_CDECL
ac_i686_mb_store_fence
( ac_i686_intword_t*,
  ac_i686_intword_t );
  

AC_SYS_APIEXPORT 
ac_i686_intword_t AC_CDECL
ac_i686_mb_load_naked
( ac_i686_intword_t* );


AC_SYS_APIEXPORT 
ac_i686_intword_t AC_CDECL
ac_i686_mb_store_naked
( ac_i686_intword_t*,
  ac_i686_intword_t );
  

AC_SYS_APIEXPORT 
int AC_CDECL
np_ac_i686_atomic_dwcas_fence
( void*,
  void*,
  const void* );


AC_SYS_APIEXPORT 
ac_i686_intword_t AC_CDECL
ac_i686_atomic_cas_fence
( ac_i686_intword_t*,
  ac_i686_intword_t,
  ac_i686_intword_t );
  
  
AC_SYS_APIEXPORT 
ac_i686_intword_t AC_CDECL
ac_i686_atomic_xchg_fence
( ac_i686_intword_t*,
  ac_i686_intword_t );


AC_SYS_APIEXPORT 
ac_i686_intword_t AC_CDECL
ac_i686_atomic_xadd_fence
( ac_i686_intword_t*,
  ac_i686_intword_t );


AC_SYS_APIEXPORT 
ac_i686_intword_t AC_CDECL
ac_i686_atomic_inc_fence
( ac_i686_intword_t* );


AC_SYS_APIEXPORT 
ac_i686_intword_t AC_CDECL
ac_i686_atomic_dec_fence
( ac_i686_intword_t* );


AC_SYS_APIEXPORT void AC_CDECL 
ac_i686_stack_mpmc_push_cas
( ac_i686_stack_mpmc_t*,
  ac_i686_node_t* );


AC_SYS_APIEXPORT ac_i686_node_t* AC_CDECL 
np_ac_i686_stack_mpmc_pop_dwcas
( ac_i686_stack_mpmc_t* );


AC_SYS_APIEXPORT void AC_CDECL 
ac_i686_queue_spsc_push
( ac_i686_queue_spsc_t*,
  ac_i686_node_t* );


AC_SYS_APIEXPORT ac_i686_node_t* AC_CDECL 
ac_i686_queue_spsc_pop
( ac_i686_queue_spsc_t* );


AC_APIEXPORT ac_i686_node_t* AC_APIDECL
ac_i686_node_cache_pop
( const void *state );


AC_APIEXPORT void AC_APIDECL
ac_i686_node_cache_push
( ac_i686_node_t* );


AC_APIEXPORT int AC_APIDECL
ac_i686_node_cache_push_no_free
( ac_i686_node_t* );




#define ac_i686_stack_mpmc_init( ac_macro_this ) \
  (ac_macro_this)->front = 0


#define ac_i686_queue_spsc_init( ac_macro_this, ac_macro_dummy ) \
  (ac_macro_this)->front = (ac_macro_dummy); \
  (ac_macro_this)->back = (ac_macro_dummy)


#define ac_i686_node_init( ac_macro_this, ac_macro_fp_dtor, ac_macro_state ) \
  (ac_macro_this)->next = 0; \
  (ac_macro_this)->lfgc_next = 0; \
  (ac_macro_this)->fp_dtor = (ac_macro_fp_dtor); \
  (ac_macro_this)->state = (ac_macro_state) 


#define ac_i686_node_get_next( ac_macro_this ) \
  ( (ac_macro_this)->next )


#define ac_i686_mb_node_get_next( ac_macro_this ) \
  ( (ac_i686_node_t*)ac_mb_loadptr_depends( &(ac_macro_this)->next ) )


#define ac_i686_node_get_state( ac_macro_this ) \
  ( (void*)(ac_macro_this)->state )


#define ac_i686_mb_node_get_state( ac_macro_this ) \
  ( ac_mb_loadptr_depends( &(ac_macro_this)->state ) )


#define ac_i686_mb_loadptr_fence( ac_macro_state ) \
  ( (void*)ac_i686_mb_load_fence \
      ( (ac_i686_intword_t*)(ac_macro_state) ) )


#define ac_i686_mb_loadptr_naked( ac_macro_state ) \
  ( (void*)ac_i686_mb_load_naked \
      ( (ac_i686_intword_t*)(ac_macro_state) ) )  
      
      
#define ac_i686_mb_storeptr_fence( ac_macro_dest, ac_macro_state ) \
  ( (void*)ac_i686_mb_store_fence \
      ( (ac_i686_intword_t*)(ac_macro_dest), \
        (ac_i686_intword_t)(ac_macro_state) ) )
        
        
#define ac_i686_mb_storeptr_naked( ac_macro_dest, ac_macro_state ) \
  ( (void*)ac_i686_mb_store_naked \
      ( (ac_i686_intword_t*)(ac_macro_dest), \
        (ac_i686_intword_t)(ac_macro_state) ) )
        
        
#define ac_i686_atomic_casptr_fence( ac_macro_dest, ac_macro_cmp, ac_macro_xchg ) \
  ( (void*)ac_i686_atomic_cas_fence \
      ( (ac_i686_intword_t*)(ac_macro_dest), \
        (ac_i686_intword_t)(ac_macro_cmp), \
        (ac_i686_intword_t)(ac_macro_xchg) ) )
        
        
#define ac_i686_atomic_xchgptr_fence( ac_macro_dest, ac_macro_xchg ) \
  ( (void*)ac_i686_atomic_xchg_fence \
      ( (ac_i686_intword_t*)(ac_macro_dest), \
        (ac_i686_intword_t)(ac_macro_xchg) ) )








/*****  Low-Level Atomic API Abstraction  *****/
#define AC_CPU_CACHE_LINE AC_I686_CACHE_LINE
#define AC_CPU_WORD_SIZE AC_I686_WORD_SIZE


#ifndef AC_CPU_HAS_DWCAS
#define AC_CPU_HAS_DWCAS
#endif




typedef ac_i686_intword_t ac_intword_t;
typedef ac_i686_uintword_t ac_uintword_t;
typedef ac_i686_intword2_t ac_intword2_t;
typedef ac_i686_uintword2_t ac_uintword2_t;
typedef ac_i686_flags_t ac_flags_t;


typedef ac_i686_node_t ac_cpu_node_t;
typedef ac_i686_stack_mpmc_t ac_cpu_stack_mpmc_t;
typedef ac_i686_queue_spsc_t ac_cpu_queue_spsc_t;
typedef ac_i686_tls_t ac_cpu_tls_t;




#define ac_cpu_pause ac_i686_pause
#define ac_cpu_pause_yield ac_i686_pause_yield


#define ac_mb_fence ac_i686_mb_fence


#define ac_mb_load_fence ac_i686_mb_load_fence
#define ac_mb_load_naked ac_i686_mb_load_naked
#define ac_mb_load_acquire ac_mb_load_naked
#define ac_mb_load_depends ac_mb_load_naked
#define ac_mb_loadptr_fence ac_i686_mb_loadptr_fence
#define ac_mb_loadptr_naked ac_i686_mb_loadptr_naked
#define ac_mb_loadptr_acquire ac_mb_loadptr_naked
#define ac_mb_loadptr_depends ac_mb_loadptr_naked


#define ac_mb_store_fence ac_i686_mb_store_fence
#define ac_mb_store_naked ac_i686_mb_store_naked
#define ac_mb_store_release ac_mb_store_naked
#define ac_mb_storeptr_fence ac_i686_mb_storeptr_fence
#define ac_mb_storeptr_naked ac_i686_mb_storeptr_naked
#define ac_mb_storeptr_release ac_mb_storeptr_naked


#define np_ac_atomic_dwcas_fence np_ac_i686_atomic_dwcas_fence
#define np_ac_atomic_dwcas_acquire np_ac_atomic_dwcas_fence
#define np_ac_atomic_dwcas_release np_ac_atomic_dwcas_fence
#define np_ac_atomic_dwcas_depends np_ac_atomic_dwcas_fence


#define ac_atomic_cas_fence ac_i686_atomic_cas_fence
#define ac_atomic_cas_acquire ac_atomic_cas_fence
#define ac_atomic_cas_release ac_atomic_cas_fence
#define ac_atomic_cas_depends ac_atomic_cas_fence
#define ac_atomic_casptr_fence ac_i686_atomic_casptr_fence
#define ac_atomic_casptr_acquire ac_atomic_casptr_fence
#define ac_atomic_casptr_release ac_atomic_casptr_fence
#define ac_atomic_casptr_depends ac_atomic_casptr_fence


#define ac_atomic_xadd_fence ac_i686_atomic_xadd_fence
#define ac_atomic_xadd_acquire ac_atomic_xadd_fence
#define ac_atomic_xadd_release ac_atomic_xadd_fence
#define ac_atomic_xadd_depends ac_atomic_xadd_fence


#define ac_atomic_xchg_fence ac_i686_atomic_xchg_fence
#define ac_atomic_xchg_acquire ac_atomic_xchg_fence
#define ac_atomic_xchg_release ac_atomic_xchg_fence
#define ac_atomic_xchg_depends ac_atomic_xchg_fence
#define ac_atomic_xchgptr_fence ac_i686_atomic_xchgptr_fence
#define ac_atomic_xchgptr_acquire ac_atomic_xchgptr_fence
#define ac_atomic_xchgptr_release ac_atomic_xchgptr_fence
#define ac_atomic_xchgptr_depends ac_atomic_xchgptr_fence


#define ac_atomic_inc_fence ac_i686_atomic_inc_fence
#define ac_atomic_inc_acquire ac_atomic_inc_fence
#define ac_atomic_inc_release ac_atomic_inc_fence
#define ac_atomic_inc_depends ac_atomic_inc_fence


#define ac_atomic_dec_fence ac_i686_atomic_dec_fence
#define ac_atomic_dec_acquire ac_atomic_dec_fence
#define ac_atomic_dec_release ac_atomic_dec_fence
#define ac_atomic_dec_depends ac_atomic_dec_fence


#define ac_cpu_queue_spsc_init ac_i686_queue_spsc_init
#define ac_cpu_queue_spsc_push ac_i686_queue_spsc_push
#define ac_cpu_queue_spsc_pop ac_i686_queue_spsc_pop


#define ac_cpu_stack_mpmc_init ac_i686_stack_mpmc_init
#define ac_cpu_stack_mpmc_push_cas ac_i686_stack_mpmc_push_cas
#define np_ac_cpu_stack_mpmc_pop_dwcas np_ac_i686_stack_mpmc_pop_dwcas


#define ac_cpu_node_init ac_i686_node_init
#define ac_cpu_node_get_next ac_i686_node_get_next
#define ac_cpu_mb_node_get_next ac_i686_mb_node_get_next
#define ac_cpu_node_get_state ac_i686_node_get_state
#define ac_cpu_mb_node_get_state ac_i686_mb_node_get_state
#define ac_cpu_node_cache_pop ac_i686_node_cache_pop
#define ac_cpu_node_cache_push ac_i686_node_cache_push
#define ac_cpu_node_cache_push_no_free ac_i686_node_cache_push_no_free





#ifdef __cplusplus
}
#endif


#endif




#include "ac_i686_lfgc_smr.h"
#include "ac_i686_lfgc_refcount.h"