]> rtime.felk.cvut.cz Git - sojka/libev.git/commitdiff
temporary fence hack
authorMarc Alexander Lehmann <libev@schmorp.de>
Wed, 20 Jul 2011 00:40:14 +0000 (00:40 +0000)
committerMarc Alexander Lehmann <libev@schmorp.de>
Wed, 20 Jul 2011 00:40:14 +0000 (00:40 +0000)
Changes
ev.c

diff --git a/Changes b/Changes
index cf4715a0a3b39da9f4b84a9963c4efde7fb70df7..d2f2d52304c6dd918ffd2d5729d5acb92a485b8e 100644 (file)
--- 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 4be8d498d57e5f4cc199dd22689444b3d5be79e7..c514a77e270c50a664726bcdc98842ed47bad971 100644 (file)
--- 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;