summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorroot <root>2011-07-20 00:40:14 +0000
committerroot <root>2011-07-20 00:40:14 +0000
commitda7d355be23e019506a1413fb4ab2881bd1e6059 (patch)
tree134a68b28ae26f3cf5eccc61102f138a2f2b76f1
parent67acb181649e135df7c731f5d5280fa7a86b6fe2 (diff)
temporary fence hack
-rw-r--r--Changes1
-rw-r--r--ev.c95
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 <pthread.h>
+
+ 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;