… | |
… | |
559 | |
559 | |
560 | #define ECB_C (__STDC__+0) /* this assumes that __STDC__ is either empty or a number */ |
560 | #define ECB_C (__STDC__+0) /* this assumes that __STDC__ is either empty or a number */ |
561 | #define ECB_C99 (__STDC_VERSION__ >= 199901L) |
561 | #define ECB_C99 (__STDC_VERSION__ >= 199901L) |
562 | #define ECB_C11 (__STDC_VERSION__ >= 201112L) |
562 | #define ECB_C11 (__STDC_VERSION__ >= 201112L) |
563 | #define ECB_CPP (__cplusplus+0) |
563 | #define ECB_CPP (__cplusplus+0) |
564 | #define ECB_CPP98 (__cplusplus >= 199711L) |
|
|
565 | #define ECB_CPP11 (__cplusplus >= 201103L) |
564 | #define ECB_CPP11 (__cplusplus >= 201103L) |
566 | |
565 | |
567 | /*****************************************************************************/ |
566 | /*****************************************************************************/ |
568 | |
567 | |
569 | /* ECB_NO_THREADS - ecb is not used by multiple threads, ever */ |
568 | /* 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 */ |
569 | /* ECB_NO_SMP - ecb might be used in multiple threads, but only on a single cpu */ |
571 | |
570 | |
572 | #if ECB_NO_THREADS |
571 | #if ECB_NO_THREADS |
573 | # define ECB_NO_SMP 1 |
572 | #define ECB_NO_SMP 1 |
574 | #endif |
573 | #endif |
575 | |
574 | |
576 | #if ECB_NO_SMP |
575 | #if ECB_NO_SMP |
577 | #define ECB_MEMORY_FENCE do { } while (0) |
576 | #define ECB_MEMORY_FENCE do { } while (0) |
578 | #endif |
577 | #endif |
… | |
… | |
614 | #endif |
613 | #endif |
615 | #endif |
614 | #endif |
616 | |
615 | |
617 | #ifndef ECB_MEMORY_FENCE |
616 | #ifndef ECB_MEMORY_FENCE |
618 | #if ECB_GCC_VERSION(4,7) |
617 | #if ECB_GCC_VERSION(4,7) |
619 | /* see comment below about the C11 memory model. in short - avoid */ |
618 | /* see comment below (stdatomic.h) about the C11 memory model. */ |
620 | #define ECB_MEMORY_FENCE __atomic_thread_fence (__ATOMIC_SEQ_CST) |
619 | #define ECB_MEMORY_FENCE __atomic_thread_fence (__ATOMIC_SEQ_CST) |
621 | #elif defined __clang && __has_feature (cxx_atomic) |
620 | #elif defined __clang && __has_feature (cxx_atomic) |
622 | /* see above */ |
621 | /* see comment below (stdatomic.h) about the C11 memory model. */ |
623 | #define ECB_MEMORY_FENCE __c11_atomic_thread_fence (__ATOMIC_SEQ_CST) |
622 | #define ECB_MEMORY_FENCE __c11_atomic_thread_fence (__ATOMIC_SEQ_CST) |
624 | #elif ECB_GCC_VERSION(4,4) || defined __INTEL_COMPILER || defined __clang__ |
623 | #elif ECB_GCC_VERSION(4,4) || defined __INTEL_COMPILER || defined __clang__ |
625 | #define ECB_MEMORY_FENCE __sync_synchronize () |
624 | #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 */ |
625 | #elif _MSC_VER >= 1400 /* VC++ 2005 */ |
629 | #pragma intrinsic(_ReadBarrier,_WriteBarrier,_ReadWriteBarrier) |
626 | #pragma intrinsic(_ReadBarrier,_WriteBarrier,_ReadWriteBarrier) |
630 | #define ECB_MEMORY_FENCE _ReadWriteBarrier () |
627 | #define ECB_MEMORY_FENCE _ReadWriteBarrier () |
631 | #define ECB_MEMORY_FENCE_ACQUIRE _ReadWriteBarrier () /* according to msdn, _ReadBarrier is not a load fence */ |
628 | #define ECB_MEMORY_FENCE_ACQUIRE _ReadWriteBarrier () /* according to msdn, _ReadBarrier is not a load fence */ |
632 | #define ECB_MEMORY_FENCE_RELEASE _WriteBarrier () |
629 | #define ECB_MEMORY_FENCE_RELEASE _WriteBarrier () |
… | |
… | |
646 | #ifndef ECB_MEMORY_FENCE |
643 | #ifndef ECB_MEMORY_FENCE |
647 | #if ECB_C11 && !defined __STDC_NO_ATOMICS__ |
644 | #if ECB_C11 && !defined __STDC_NO_ATOMICS__ |
648 | /* we assume that these memory fences work on all variables/all memory accesses, */ |
645 | /* we assume that these memory fences work on all variables/all memory accesses, */ |
649 | /* not just C11 atomics and atomic accesses */ |
646 | /* not just C11 atomics and atomic accesses */ |
650 | #include <stdatomic.h> |
647 | #include <stdatomic.h> |
651 | /* unfortunately, the C11 memory model seems to be very limited, and unable to express */ |
648 | /* Unfortunately, neither gcc 4.7 nor clang 3.1 generate any instructions for */ |
652 | /* simple barrier semantics. That means we need to take out thor's hammer. */ |
649 | /* any fence other than seq_cst, which isn't very efficient for us. */ |
|
|
650 | /* Why that is, we don't know - either the C11 memory model is quite useless */ |
|
|
651 | /* for most usages, or gcc and clang have a bug */ |
|
|
652 | /* I *currently* lean towards the latter, and inefficiently implement */ |
|
|
653 | /* all three of ecb's fences as a seq_cst fence */ |
653 | #define ECB_MEMORY_FENCE atomic_thread_fence (memory_order_seq_cst) |
654 | #define ECB_MEMORY_FENCE atomic_thread_fence (memory_order_seq_cst) |
654 | #endif |
|
|
655 | #endif |
655 | #endif |
656 | #endif |
656 | #endif |
657 | |
657 | |
658 | #ifndef ECB_MEMORY_FENCE |
658 | #ifndef ECB_MEMORY_FENCE |
659 | #if !ECB_AVOID_PTHREADS |
659 | #if !ECB_AVOID_PTHREADS |
… | |
… | |
2550 | EV_WIN32_CLOSE_FD (evpipe [1]); |
2550 | EV_WIN32_CLOSE_FD (evpipe [1]); |
2551 | } |
2551 | } |
2552 | |
2552 | |
2553 | #if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE |
2553 | #if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE |
2554 | evpipe_init (EV_A); |
2554 | evpipe_init (EV_A); |
2555 | /* now iterate over everything, in case we missed something */ |
2555 | /* iterate over everything, in case we missed something before */ |
2556 | pipecb (EV_A_ &pipe_w, EV_READ); |
2556 | ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM); |
2557 | #endif |
2557 | #endif |
2558 | } |
2558 | } |
2559 | |
2559 | |
2560 | postfork = 0; |
2560 | postfork = 0; |
2561 | } |
2561 | } |
… | |
… | |
2736 | } |
2736 | } |
2737 | |
2737 | |
2738 | void |
2738 | void |
2739 | ev_loop_fork (EV_P) EV_THROW |
2739 | ev_loop_fork (EV_P) EV_THROW |
2740 | { |
2740 | { |
2741 | postfork = 1; /* must be in line with ev_default_fork */ |
2741 | postfork = 1; |
2742 | } |
2742 | } |
2743 | |
2743 | |
2744 | /*****************************************************************************/ |
2744 | /*****************************************************************************/ |
2745 | |
2745 | |
2746 | void |
2746 | void |
… | |
… | |
3138 | backend_poll (EV_A_ waittime); |
3138 | backend_poll (EV_A_ waittime); |
3139 | assert ((loop_done = EVBREAK_CANCEL, 1)); /* assert for side effect */ |
3139 | assert ((loop_done = EVBREAK_CANCEL, 1)); /* assert for side effect */ |
3140 | |
3140 | |
3141 | pipe_write_wanted = 0; /* just an optimisation, no fence needed */ |
3141 | pipe_write_wanted = 0; /* just an optimisation, no fence needed */ |
3142 | |
3142 | |
|
|
3143 | ECB_MEMORY_FENCE_ACQUIRE; |
3143 | if (pipe_write_skipped) |
3144 | if (pipe_write_skipped) |
3144 | { |
3145 | { |
3145 | assert (("libev: pipe_w not active, but pipe not written", ev_is_active (&pipe_w))); |
3146 | 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); |
3147 | ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM); |
3147 | } |
3148 | } |
… | |
… | |
3176 | && !(flags & (EVRUN_ONCE | EVRUN_NOWAIT)) |
3177 | && !(flags & (EVRUN_ONCE | EVRUN_NOWAIT)) |
3177 | )); |
3178 | )); |
3178 | |
3179 | |
3179 | if (loop_done == EVBREAK_ONE) |
3180 | if (loop_done == EVBREAK_ONE) |
3180 | loop_done = EVBREAK_CANCEL; |
3181 | loop_done = EVBREAK_CANCEL; |
|
|
3182 | |
|
|
3183 | /* pendingpri is normally -1 here, which is not a good */ |
|
|
3184 | /* value when returning to an ev_invoke_pending */ |
|
|
3185 | pendingpri = NUMPRI - 1; |
3181 | |
3186 | |
3182 | #if EV_FEATURE_API |
3187 | #if EV_FEATURE_API |
3183 | --loop_depth; |
3188 | --loop_depth; |
3184 | #endif |
3189 | #endif |
3185 | |
3190 | |