… | |
… | |
559 | |
559 | |
560 | #ifndef ECB_H |
560 | #ifndef ECB_H |
561 | #define ECB_H |
561 | #define ECB_H |
562 | |
562 | |
563 | /* 16 bits major, 16 bits minor */ |
563 | /* 16 bits major, 16 bits minor */ |
564 | #define ECB_VERSION 0x00010005 |
564 | #define ECB_VERSION 0x00010006 |
565 | |
565 | |
566 | #ifdef _WIN32 |
566 | #ifdef _WIN32 |
567 | typedef signed char int8_t; |
567 | typedef signed char int8_t; |
568 | typedef unsigned char uint8_t; |
568 | typedef unsigned char uint8_t; |
569 | typedef signed short int16_t; |
569 | typedef signed short int16_t; |
… | |
… | |
683 | #include <intrin.h> /* fence functions _ReadBarrier, also bit search functions _BitScanReverse */ |
683 | #include <intrin.h> /* fence functions _ReadBarrier, also bit search functions _BitScanReverse */ |
684 | #endif |
684 | #endif |
685 | |
685 | |
686 | #ifndef ECB_MEMORY_FENCE |
686 | #ifndef ECB_MEMORY_FENCE |
687 | #if ECB_GCC_VERSION(2,5) || defined __INTEL_COMPILER || (__llvm__ && __GNUC__) || __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110 |
687 | #if ECB_GCC_VERSION(2,5) || defined __INTEL_COMPILER || (__llvm__ && __GNUC__) || __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110 |
|
|
688 | #define ECB_MEMORY_FENCE_RELAXED __asm__ __volatile__ ("" : : : "memory") |
688 | #if __i386 || __i386__ |
689 | #if __i386 || __i386__ |
689 | #define ECB_MEMORY_FENCE __asm__ __volatile__ ("lock; orb $0, -1(%%esp)" : : : "memory") |
690 | #define ECB_MEMORY_FENCE __asm__ __volatile__ ("lock; orb $0, -1(%%esp)" : : : "memory") |
690 | #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("" : : : "memory") |
691 | #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("" : : : "memory") |
691 | #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("" : : : "memory") |
692 | #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("" : : : "memory") |
692 | #elif ECB_GCC_AMD64 |
693 | #elif ECB_GCC_AMD64 |
… | |
… | |
742 | #if ECB_GCC_VERSION(4,7) |
743 | #if ECB_GCC_VERSION(4,7) |
743 | /* see comment below (stdatomic.h) about the C11 memory model. */ |
744 | /* see comment below (stdatomic.h) about the C11 memory model. */ |
744 | #define ECB_MEMORY_FENCE __atomic_thread_fence (__ATOMIC_SEQ_CST) |
745 | #define ECB_MEMORY_FENCE __atomic_thread_fence (__ATOMIC_SEQ_CST) |
745 | #define ECB_MEMORY_FENCE_ACQUIRE __atomic_thread_fence (__ATOMIC_ACQUIRE) |
746 | #define ECB_MEMORY_FENCE_ACQUIRE __atomic_thread_fence (__ATOMIC_ACQUIRE) |
746 | #define ECB_MEMORY_FENCE_RELEASE __atomic_thread_fence (__ATOMIC_RELEASE) |
747 | #define ECB_MEMORY_FENCE_RELEASE __atomic_thread_fence (__ATOMIC_RELEASE) |
|
|
748 | #define ECB_MEMORY_FENCE_RELAXED __atomic_thread_fence (__ATOMIC_RELAXED) |
747 | |
749 | |
748 | #elif ECB_CLANG_EXTENSION(c_atomic) |
750 | #elif ECB_CLANG_EXTENSION(c_atomic) |
749 | /* see comment below (stdatomic.h) about the C11 memory model. */ |
751 | /* see comment below (stdatomic.h) about the C11 memory model. */ |
750 | #define ECB_MEMORY_FENCE __c11_atomic_thread_fence (__ATOMIC_SEQ_CST) |
752 | #define ECB_MEMORY_FENCE __c11_atomic_thread_fence (__ATOMIC_SEQ_CST) |
751 | #define ECB_MEMORY_FENCE_ACQUIRE __c11_atomic_thread_fence (__ATOMIC_ACQUIRE) |
753 | #define ECB_MEMORY_FENCE_ACQUIRE __c11_atomic_thread_fence (__ATOMIC_ACQUIRE) |
752 | #define ECB_MEMORY_FENCE_RELEASE __c11_atomic_thread_fence (__ATOMIC_RELEASE) |
754 | #define ECB_MEMORY_FENCE_RELEASE __c11_atomic_thread_fence (__ATOMIC_RELEASE) |
|
|
755 | #define ECB_MEMORY_FENCE_RELAXED __c11_atomic_thread_fence (__ATOMIC_RELAXED) |
753 | |
756 | |
754 | #elif ECB_GCC_VERSION(4,4) || defined __INTEL_COMPILER || defined __clang__ |
757 | #elif ECB_GCC_VERSION(4,4) || defined __INTEL_COMPILER || defined __clang__ |
755 | #define ECB_MEMORY_FENCE __sync_synchronize () |
758 | #define ECB_MEMORY_FENCE __sync_synchronize () |
756 | #elif _MSC_VER >= 1500 /* VC++ 2008 */ |
759 | #elif _MSC_VER >= 1500 /* VC++ 2008 */ |
757 | /* apparently, microsoft broke all the memory barrier stuff in Visual Studio 2008... */ |
760 | /* apparently, microsoft broke all the memory barrier stuff in Visual Studio 2008... */ |
… | |
… | |
767 | #elif defined _WIN32 |
770 | #elif defined _WIN32 |
768 | #include <WinNT.h> |
771 | #include <WinNT.h> |
769 | #define ECB_MEMORY_FENCE MemoryBarrier () /* actually just xchg on x86... scary */ |
772 | #define ECB_MEMORY_FENCE MemoryBarrier () /* actually just xchg on x86... scary */ |
770 | #elif __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110 |
773 | #elif __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110 |
771 | #include <mbarrier.h> |
774 | #include <mbarrier.h> |
772 | #define ECB_MEMORY_FENCE __machine_rw_barrier () |
775 | #define ECB_MEMORY_FENCE __machine_rw_barrier () |
773 | #define ECB_MEMORY_FENCE_ACQUIRE __machine_r_barrier () |
776 | #define ECB_MEMORY_FENCE_ACQUIRE __machine_acq_barrier () |
774 | #define ECB_MEMORY_FENCE_RELEASE __machine_w_barrier () |
777 | #define ECB_MEMORY_FENCE_RELEASE __machine_rel_barrier () |
|
|
778 | #define ECB_MEMORY_FENCE_RELAXED __compiler_barrier () |
775 | #elif __xlC__ |
779 | #elif __xlC__ |
776 | #define ECB_MEMORY_FENCE __sync () |
780 | #define ECB_MEMORY_FENCE __sync () |
777 | #endif |
781 | #endif |
778 | #endif |
782 | #endif |
779 | |
783 | |
780 | #ifndef ECB_MEMORY_FENCE |
784 | #ifndef ECB_MEMORY_FENCE |
781 | #if ECB_C11 && !defined __STDC_NO_ATOMICS__ |
785 | #if ECB_C11 && !defined __STDC_NO_ATOMICS__ |
782 | /* we assume that these memory fences work on all variables/all memory accesses, */ |
786 | /* we assume that these memory fences work on all variables/all memory accesses, */ |
783 | /* not just C11 atomics and atomic accesses */ |
787 | /* not just C11 atomics and atomic accesses */ |
784 | #include <stdatomic.h> |
788 | #include <stdatomic.h> |
785 | /* Unfortunately, neither gcc 4.7 nor clang 3.1 generate any instructions for */ |
|
|
786 | /* any fence other than seq_cst, which isn't very efficient for us. */ |
|
|
787 | /* Why that is, we don't know - either the C11 memory model is quite useless */ |
|
|
788 | /* for most usages, or gcc and clang have a bug */ |
|
|
789 | /* I *currently* lean towards the latter, and inefficiently implement */ |
|
|
790 | /* all three of ecb's fences as a seq_cst fence */ |
|
|
791 | /* Update, gcc-4.8 generates mfence for all c++ fences, but nothing */ |
|
|
792 | /* for all __atomic_thread_fence's except seq_cst */ |
|
|
793 | #define ECB_MEMORY_FENCE atomic_thread_fence (memory_order_seq_cst) |
789 | #define ECB_MEMORY_FENCE atomic_thread_fence (memory_order_seq_cst) |
|
|
790 | #define ECB_MEMORY_FENCE_ACQUIRE atomic_thread_fence (memory_order_acquire) |
|
|
791 | #define ECB_MEMORY_FENCE_RELEASE atomic_thread_fence (memory_order_release) |
794 | #endif |
792 | #endif |
795 | #endif |
793 | #endif |
796 | |
794 | |
797 | #ifndef ECB_MEMORY_FENCE |
795 | #ifndef ECB_MEMORY_FENCE |
798 | #if !ECB_AVOID_PTHREADS |
796 | #if !ECB_AVOID_PTHREADS |
… | |
… | |
816 | #define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE |
814 | #define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE |
817 | #endif |
815 | #endif |
818 | |
816 | |
819 | #if !defined ECB_MEMORY_FENCE_RELEASE && defined ECB_MEMORY_FENCE |
817 | #if !defined ECB_MEMORY_FENCE_RELEASE && defined ECB_MEMORY_FENCE |
820 | #define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE |
818 | #define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE |
|
|
819 | #endif |
|
|
820 | |
|
|
821 | #if !defined ECB_MEMORY_FENCE_RELAXED && defined ECB_MEMORY_FENCE |
|
|
822 | #define ECB_MEMORY_FENCE_RELAXED ECB_MEMORY_FENCE /* very heavy-handed */ |
821 | #endif |
823 | #endif |
822 | |
824 | |
823 | /*****************************************************************************/ |
825 | /*****************************************************************************/ |
824 | |
826 | |
825 | #if ECB_CPP |
827 | #if ECB_CPP |