… | |
… | |
568 | |
568 | |
569 | /* ECB_NO_THREADS - ecb is not used by multiple threads, ever */ |
569 | /* ECB_NO_THREADS - ecb is not used by multiple threads, ever */ |
570 | /* ECB_NO_SMP - ecb might be used in multiple threads, but only on a single cpu */ |
570 | /* ECB_NO_SMP - ecb might be used in multiple threads, but only on a single cpu */ |
571 | |
571 | |
572 | #if ECB_NO_THREADS |
572 | #if ECB_NO_THREADS |
573 | # define ECB_NO_SMP 1 |
573 | #define ECB_NO_SMP 1 |
574 | #endif |
574 | #endif |
575 | |
575 | |
576 | #if ECB_NO_SMP |
576 | #if ECB_NO_SMP |
577 | #define ECB_MEMORY_FENCE do { } while (0) |
577 | #define ECB_MEMORY_FENCE do { } while (0) |
578 | #endif |
578 | #endif |
… | |
… | |
621 | #elif defined __clang && __has_feature (cxx_atomic) |
621 | #elif defined __clang && __has_feature (cxx_atomic) |
622 | /* see above */ |
622 | /* see above */ |
623 | #define ECB_MEMORY_FENCE __c11_atomic_thread_fence (__ATOMIC_SEQ_CST) |
623 | #define ECB_MEMORY_FENCE __c11_atomic_thread_fence (__ATOMIC_SEQ_CST) |
624 | #elif ECB_GCC_VERSION(4,4) || defined __INTEL_COMPILER || defined __clang__ |
624 | #elif ECB_GCC_VERSION(4,4) || defined __INTEL_COMPILER || defined __clang__ |
625 | #define ECB_MEMORY_FENCE __sync_synchronize () |
625 | #define ECB_MEMORY_FENCE __sync_synchronize () |
626 | /*#define ECB_MEMORY_FENCE_ACQUIRE ({ char dummy = 0; __sync_lock_test_and_set (&dummy, 1); }) */ |
|
|
627 | /*#define ECB_MEMORY_FENCE_RELEASE ({ char dummy = 1; __sync_lock_release (&dummy ); }) */ |
|
|
628 | #elif _MSC_VER >= 1400 /* VC++ 2005 */ |
626 | #elif _MSC_VER >= 1400 /* VC++ 2005 */ |
629 | #pragma intrinsic(_ReadBarrier,_WriteBarrier,_ReadWriteBarrier) |
627 | #pragma intrinsic(_ReadBarrier,_WriteBarrier,_ReadWriteBarrier) |
630 | #define ECB_MEMORY_FENCE _ReadWriteBarrier () |
628 | #define ECB_MEMORY_FENCE _ReadWriteBarrier () |
631 | #define ECB_MEMORY_FENCE_ACQUIRE _ReadWriteBarrier () /* according to msdn, _ReadBarrier is not a load fence */ |
629 | #define ECB_MEMORY_FENCE_ACQUIRE _ReadWriteBarrier () /* according to msdn, _ReadBarrier is not a load fence */ |
632 | #define ECB_MEMORY_FENCE_RELEASE _WriteBarrier () |
630 | #define ECB_MEMORY_FENCE_RELEASE _WriteBarrier () |
… | |
… | |
649 | /* not just C11 atomics and atomic accesses */ |
647 | /* not just C11 atomics and atomic accesses */ |
650 | #include <stdatomic.h> |
648 | #include <stdatomic.h> |
651 | /* unfortunately, the C11 memory model seems to be very limited, and unable to express */ |
649 | /* unfortunately, the C11 memory model seems to be very limited, and unable to express */ |
652 | /* simple barrier semantics. That means we need to take out thor's hammer. */ |
650 | /* simple barrier semantics. That means we need to take out thor's hammer. */ |
653 | #define ECB_MEMORY_FENCE atomic_thread_fence (memory_order_seq_cst) |
651 | #define ECB_MEMORY_FENCE atomic_thread_fence (memory_order_seq_cst) |
654 | #endif |
|
|
655 | #endif |
652 | #endif |
656 | #endif |
653 | #endif |
657 | |
654 | |
658 | #ifndef ECB_MEMORY_FENCE |
655 | #ifndef ECB_MEMORY_FENCE |
659 | #if !ECB_AVOID_PTHREADS |
656 | #if !ECB_AVOID_PTHREADS |
… | |
… | |
2736 | } |
2733 | } |
2737 | |
2734 | |
2738 | void |
2735 | void |
2739 | ev_loop_fork (EV_P) EV_THROW |
2736 | ev_loop_fork (EV_P) EV_THROW |
2740 | { |
2737 | { |
2741 | postfork = 1; /* must be in line with ev_default_fork */ |
2738 | postfork = 1; |
2742 | } |
2739 | } |
2743 | |
2740 | |
2744 | /*****************************************************************************/ |
2741 | /*****************************************************************************/ |
2745 | |
2742 | |
2746 | void |
2743 | void |
… | |
… | |
3138 | backend_poll (EV_A_ waittime); |
3135 | backend_poll (EV_A_ waittime); |
3139 | assert ((loop_done = EVBREAK_CANCEL, 1)); /* assert for side effect */ |
3136 | assert ((loop_done = EVBREAK_CANCEL, 1)); /* assert for side effect */ |
3140 | |
3137 | |
3141 | pipe_write_wanted = 0; /* just an optimisation, no fence needed */ |
3138 | pipe_write_wanted = 0; /* just an optimisation, no fence needed */ |
3142 | |
3139 | |
|
|
3140 | MEMORY_FENCE_ACQUIRE; |
3143 | if (pipe_write_skipped) |
3141 | if (pipe_write_skipped) |
3144 | { |
3142 | { |
3145 | assert (("libev: pipe_w not active, but pipe not written", ev_is_active (&pipe_w))); |
3143 | assert (("libev: pipe_w not active, but pipe not written", ev_is_active (&pipe_w))); |
3146 | ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM); |
3144 | ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM); |
3147 | } |
3145 | } |