// -*- C++ -*- (c) 2015 Vladimír Štill #include #include #ifndef __LART_WEAKMEM_H_ #define __LART_WEAKMEM_H_ #define _lart_weakmem_bypass_ __attribute__((annotate("lart.weakmem.bypass"))) #define _lart_weakmem_sc_ __attribute__((annotate("lart.weakmem.sc"))) #define _lart_weakmem_tso_ __attribute__((annotate("lart.weakmem.tso"))) #define _lart_weakmem_pso_ __attribute__((annotate("lart.weakmem.pso"))) #define _lart_weakmem_propagate_ __attribute__((annotate("lart.weakmem.propagate"))) #define __NOINLINE __attribute__((noinline)) #ifdef __cplusplus extern "C" { #endif volatile extern int __lart_weakmem_buffer_size; void __lart_weakmem_store_tso( void *addr, uint64_t value, int bitwidth ) _lart_weakmem_bypass_ _lart_weakmem_propagate_ __NOINLINE; uint64_t __lart_weakmem_load_tso( void *addr, int bitwidth ) _lart_weakmem_bypass_ _lart_weakmem_propagate_ __NOINLINE; void __lart_weakmem_store_pso( void *addr, uint64_t value, int bitwidth ) _lart_weakmem_bypass_ _lart_weakmem_propagate_ __NOINLINE; uint64_t __lart_weakmem_load_pso( void *addr, int bitwidth ) _lart_weakmem_bypass_ _lart_weakmem_propagate_ __NOINLINE; void __lart_weakmem_flush() _lart_weakmem_bypass_ _lart_weakmem_propagate_ __NOINLINE; void __lart_weakmem_cleanup( int cnt, ... ) _lart_weakmem_bypass_ _lart_weakmem_propagate_ __NOINLINE; /* memory manipulation "template" functions */ void __lart_weakmem_memmove( void *dest, const void *src, size_t n ) _lart_weakmem_bypass_ _lart_weakmem_propagate_ __NOINLINE; void __lart_weakmem_memcpy( void *dest, const void *src, size_t n ) _lart_weakmem_bypass_ _lart_weakmem_propagate_ __NOINLINE; void __lart_weakmem_memset( void *dest, int c, size_t n ) _lart_weakmem_bypass_ _lart_weakmem_propagate_ __NOINLINE; /* following functions will be generated by LART */ void __lart_weakmem_memmove_bypass( void *dest, const void *src, size_t n ) _lart_weakmem_bypass_ _lart_weakmem_propagate_ __NOINLINE; void __lart_weakmem_memcpy_bypass( void *dest, const void *src, size_t n ) _lart_weakmem_bypass_ _lart_weakmem_propagate_ __NOINLINE; void __lart_weakmem_memset_bypass( void *dest, int c, size_t n ) _lart_weakmem_bypass_ _lart_weakmem_propagate_ __NOINLINE; void __lart_weakmem_memmove_sc( void *dest, const void *src, size_t n ) _lart_weakmem_bypass_ _lart_weakmem_propagate_ __NOINLINE; void __lart_weakmem_memcpy_sc( void *dest, const void *src, size_t n ) _lart_weakmem_bypass_ _lart_weakmem_propagate_ __NOINLINE; void __lart_weakmem_memset_sc( void *dest, int c, size_t n ) _lart_weakmem_bypass_ _lart_weakmem_propagate_ __NOINLINE; void __lart_weakmem_memmove_tso( void *dest, const void *src, size_t n ) _lart_weakmem_bypass_ _lart_weakmem_propagate_ __NOINLINE; void __lart_weakmem_memcpy_tso( void *dest, const void *src, size_t n ) _lart_weakmem_bypass_ _lart_weakmem_propagate_ __NOINLINE; void __lart_weakmem_memset_tso( void *dest, int c, size_t n ) _lart_weakmem_bypass_ _lart_weakmem_propagate_ __NOINLINE; void __lart_weakmem_memmove_pso( void *dest, const void *src, size_t n ) _lart_weakmem_bypass_ _lart_weakmem_propagate_ __NOINLINE; void __lart_weakmem_memcpy_pso( void *dest, const void *src, size_t n ) _lart_weakmem_bypass_ _lart_weakmem_propagate_ __NOINLINE; void __lart_weakmem_memset_pso( void *dest, int c, size_t n ) _lart_weakmem_bypass_ _lart_weakmem_propagate_ __NOINLINE; /* end of generated functions */ #ifdef __cplusplus } // extern "C" #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wgcc-compat" namespace lart { namespace weakmem { enum Order { TSO, PSO }; template< Order o = TSO, typename T > void store( T *var, T val ) _lart_weakmem_bypass_ { (*(o == TSO ? &__lart_weakmem_store_tso : &__lart_weakmem_store_pso))( var, uint64_t( val ), sizeof( T ) * 8 ); } template< Order o = TSO, typename T > T load( T *var ) _lart_weakmem_bypass_ { return T( (*(o == TSO ? &__lart_weakmem_load_tso : &__lart_weakmem_load_pso))( var, sizeof( T ) * 8 ) ); } template< typename T, Order o = TSO > struct Slot { Slot() _lart_weakmem_bypass_ { } explicit Slot( T val ) _lart_weakmem_bypass_ : val( val ) { } T load() _lart_weakmem_bypass_ { return weakmem::load< o >( &val ); } void store( T x ) _lart_weakmem_bypass_ { weakmem::store< o >( &val, x ); } operator T() _lart_weakmem_bypass_ { return load(); } Slot &operator=( T x ) _lart_weakmem_bypass_ { store( x ); return *this; } private: T val; }; #pragma GCC diagnostic pop } } #endif // __cplusplus #endif // __LART_WEAKMEM_H_