… | |
… | |
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 */ |
… | |
… | |
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 | #elif _MSC_VER >= 1400 /* VC++ 2005 */ |
625 | #elif _MSC_VER >= 1400 /* VC++ 2005 */ |
627 | #pragma intrinsic(_ReadBarrier,_WriteBarrier,_ReadWriteBarrier) |
626 | #pragma intrinsic(_ReadBarrier,_WriteBarrier,_ReadWriteBarrier) |
… | |
… | |
644 | #ifndef ECB_MEMORY_FENCE |
643 | #ifndef ECB_MEMORY_FENCE |
645 | #if ECB_C11 && !defined __STDC_NO_ATOMICS__ |
644 | #if ECB_C11 && !defined __STDC_NO_ATOMICS__ |
646 | /* 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, */ |
647 | /* not just C11 atomics and atomic accesses */ |
646 | /* not just C11 atomics and atomic accesses */ |
648 | #include <stdatomic.h> |
647 | #include <stdatomic.h> |
649 | /* 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 */ |
650 | /* 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 */ |
651 | #define ECB_MEMORY_FENCE atomic_thread_fence (memory_order_seq_cst) |
654 | #define ECB_MEMORY_FENCE atomic_thread_fence (memory_order_seq_cst) |
652 | #endif |
655 | #endif |
653 | #endif |
656 | #endif |
654 | |
657 | |
655 | #ifndef ECB_MEMORY_FENCE |
658 | #ifndef ECB_MEMORY_FENCE |
… | |
… | |
2547 | EV_WIN32_CLOSE_FD (evpipe [1]); |
2550 | EV_WIN32_CLOSE_FD (evpipe [1]); |
2548 | } |
2551 | } |
2549 | |
2552 | |
2550 | #if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE |
2553 | #if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE |
2551 | evpipe_init (EV_A); |
2554 | evpipe_init (EV_A); |
2552 | /* now iterate over everything, in case we missed something */ |
2555 | /* iterate over everything, in case we missed something before */ |
2553 | pipecb (EV_A_ &pipe_w, EV_READ); |
2556 | ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM); |
2554 | #endif |
2557 | #endif |
2555 | } |
2558 | } |
2556 | |
2559 | |
2557 | postfork = 0; |
2560 | postfork = 0; |
2558 | } |
2561 | } |
… | |
… | |
2759 | } |
2762 | } |
2760 | |
2763 | |
2761 | void noinline |
2764 | void noinline |
2762 | ev_invoke_pending (EV_P) |
2765 | ev_invoke_pending (EV_P) |
2763 | { |
2766 | { |
2764 | for (pendingpri = NUMPRI; pendingpri--; ) /* pendingpri is modified during the loop */ |
2767 | pendingpri = NUMPRI; |
|
|
2768 | |
|
|
2769 | while (pendingpri) /* pendingpri possibly gets modified in the inner loop */ |
|
|
2770 | { |
|
|
2771 | --pendingpri; |
|
|
2772 | |
2765 | while (pendingcnt [pendingpri]) |
2773 | while (pendingcnt [pendingpri]) |
2766 | { |
2774 | { |
2767 | ANPENDING *p = pendings [pendingpri] + --pendingcnt [pendingpri]; |
2775 | ANPENDING *p = pendings [pendingpri] + --pendingcnt [pendingpri]; |
2768 | |
2776 | |
2769 | p->w->pending = 0; |
2777 | p->w->pending = 0; |
2770 | EV_CB_INVOKE (p->w, p->events); |
2778 | EV_CB_INVOKE (p->w, p->events); |
2771 | EV_FREQUENT_CHECK; |
2779 | EV_FREQUENT_CHECK; |
2772 | } |
2780 | } |
|
|
2781 | } |
2773 | } |
2782 | } |
2774 | |
2783 | |
2775 | #if EV_IDLE_ENABLE |
2784 | #if EV_IDLE_ENABLE |
2776 | /* make idle watchers pending. this handles the "call-idle */ |
2785 | /* make idle watchers pending. this handles the "call-idle */ |
2777 | /* only when higher priorities are idle" logic */ |
2786 | /* only when higher priorities are idle" logic */ |
… | |
… | |
3135 | backend_poll (EV_A_ waittime); |
3144 | backend_poll (EV_A_ waittime); |
3136 | assert ((loop_done = EVBREAK_CANCEL, 1)); /* assert for side effect */ |
3145 | assert ((loop_done = EVBREAK_CANCEL, 1)); /* assert for side effect */ |
3137 | |
3146 | |
3138 | pipe_write_wanted = 0; /* just an optimisation, no fence needed */ |
3147 | pipe_write_wanted = 0; /* just an optimisation, no fence needed */ |
3139 | |
3148 | |
|
|
3149 | ECB_MEMORY_FENCE_ACQUIRE; |
3140 | if (pipe_write_skipped) |
3150 | if (pipe_write_skipped) |
3141 | { |
3151 | { |
3142 | assert (("libev: pipe_w not active, but pipe not written", ev_is_active (&pipe_w))); |
3152 | assert (("libev: pipe_w not active, but pipe not written", ev_is_active (&pipe_w))); |
3143 | ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM); |
3153 | ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM); |
3144 | } |
3154 | } |