From da7d355be23e019506a1413fb4ab2881bd1e6059 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 20 Jul 2011 00:40:14 +0000 Subject: temporary fence hack --- Changes | 1 + ev.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 71 insertions(+), 25 deletions(-) diff --git a/Changes b/Changes index cf4715a..d2f2d52 100644 --- a/Changes +++ b/Changes @@ -2,6 +2,7 @@ Revision history for libev, a high-performance and full-featured event loop. TODO: ev_loop_wakeup +TODO: EV_MF_ACQ / EV_MF_REL (e.g. __sync_synchronize) 4.10 - fix a race where the workaround against the epoll fork bugs caused signals to not be handled anymore. diff --git a/ev.c b/ev.c index 4be8d49..c514a77 100644 --- a/ev.c +++ b/ev.c @@ -494,6 +494,45 @@ struct signalfd_siginfo #define ecb_inline static #endif +#ifndef ECB_MEMORY_FENCE + #if ECB_GCC_VERSION(2,5) + #if __x86 + #define ECB_MEMORY_FENCE __asm__ __volatile__ ("lock; orb $0, -1(%%esp)" : : : "memory") + #define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE + #define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE /* better be safe than sorry */ + #elif __amd64 + #define ECB_MEMORY_FENCE __asm__ __volatile__ ("mfence" : : : "memory") + #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("lfence" : : : "memory") + #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("sfence") + #endif + #endif +#endif + +#ifndef ECB_MEMORY_FENCE + #if ECB_GCC_VERSION(4,4) + #define ECB_MEMORY_FENCE __sync_synchronize () + #define ECB_MEMORY_FENCE_ACQUIRE ({ char dummy = 0; __sync_lock_test_and_set (&dummy, 1); }) + #define ECB_MEMORY_FENCE_RELEASE ({ char dummy = 1; __sync_lock_release (&dummy ); }) + #elif _MSC_VER >= 1400 + #define ECB_MEMORY_FENCE do { } while (0) + #define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE + #define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE + #elif defined(_WIN32) && defined(MemoryBarrier) + #define ECB_MEMORY_FENCE MemoryBarrier () + #define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE + #define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE + #endif +#endif + +#ifndef ECB_MEMORY_FENCE + #include + + static pthread_mutex_t ecb_mf_lock = PTHREAD_MUTEX_INITIALIZER; + #define ECB_MEMORY_FENCE do { pthread_mutex_lock (&ecb_mf_lock); pthread_mutex_unlock (&ecb_mf_lock); } while (0) + #define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE + #define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE +#endif + #if ECB_GCC_VERSION(3,1) #define ecb_attribute(attrlist) __attribute__(attrlist) #define ecb_is_constant(expr) __builtin_constant_p (expr) @@ -1422,39 +1461,43 @@ evpipe_init (EV_P) inline_speed void evpipe_write (EV_P_ EV_ATOMIC_T *flag) { - if (!*flag) - { - *flag = 1; + if (expect_true (*flag)) + return; - pipe_write_skipped = 1; + *flag = 1; - if (pipe_write_wanted) - { - int old_errno; + ECB_MEMORY_FENCE_RELEASE; - pipe_write_skipped = 0; + pipe_write_skipped = 1; + + ECB_MEMORY_FENCE; + + if (pipe_write_wanted) + { + int old_errno; - old_errno = errno; /* save errno because write will clobber it */ + pipe_write_skipped = 0; /* optimisation only */ + + old_errno = errno; /* save errno because write will clobber it */ #if EV_USE_EVENTFD - if (evfd >= 0) - { - uint64_t counter = 1; - write (evfd, &counter, sizeof (uint64_t)); - } - else + if (evfd >= 0) + { + uint64_t counter = 1; + write (evfd, &counter, sizeof (uint64_t)); + } + else #endif - { - /* win32 people keep sending patches that change this write() to send() */ - /* and then run away. but send() is wrong, it wants a socket handle on win32 */ - /* so when you think this write should be a send instead, please find out */ - /* where your send() is from - it's definitely not the microsoft send, and */ - /* tell me. thank you. */ - write (evpipe [1], &(evpipe [1]), 1); - } - - errno = old_errno; + { + /* win32 people keep sending patches that change this write() to send() */ + /* and then run away. but send() is wrong, it wants a socket handle on win32 */ + /* so when you think this write should be a send instead, please find out */ + /* where your send() is from - it's definitely not the microsoft send, and */ + /* tell me. thank you. */ + write (evpipe [1], &(evpipe [1]), 1); } + + errno = old_errno; } } @@ -2575,6 +2618,8 @@ ev_run (EV_P_ int flags) /* from now on, we want a pipe-wake-up */ pipe_write_wanted = 1; + ECB_MEMORY_FENCE; + if (expect_true (!(flags & EVRUN_NOWAIT || idleall || !activecnt || pipe_write_skipped))) { waittime = MAX_BLOCKTIME; -- cgit v1.2.3