Hi, Basically, I've discovered a problem in libev, when compiling it using Visual Studio. Long story short, the libecb's MEMORY_FENCE macros are incorrect for Visual Studio 2008 and up:
Here is the fix I have locally in order to address the problem I have been seeing: #elif _MSC_VER >= 1500 /* VC++ 2008 */ #pragma intrinsic(_ReadBarrier,_WriteBarrier,_ReadWriteBarrier) #define ECB_MEMORY_FENCE _ReadWriteBarrier (); MemoryBarrier() #define ECB_MEMORY_FENCE_ACQUIRE _ReadWriteBarrier (); MemoryBarrier() /* according to msdn, _ReadBarrier is not a load fence */ #define ECB_MEMORY_FENCE_RELEASE _WriteBarrier (); MemoryBarrier() #elif _MSC_VER >= 1400 /* VC++ 2005 */ #pragma intrinsic(_ReadBarrier,_WriteBarrier,_ReadWriteBarrier) #define ECB_MEMORY_FENCE _ReadWriteBarrier (); #define ECB_MEMORY_FENCE_ACQUIRE _ReadWriteBarrier (); /* according to msdn, _ReadBarrier is not a load fence */ #define ECB_MEMORY_FENCE_RELEASE _WriteBarrier (); Basically, if you refer to the MSDN, (from this article, more precisely: http://msdn.microsoft.com/en-us/library/f20w0x5e(v=vs.90).aspx ) the _ReadWriteBarrier() intrinsic is now only a compiler intrinsic that only prevents compiler reordering. It doesn't generate anymore the appropriate code to trigger a CPU-barrier. The MemoryBarrier() macro however is what should be used instead to generate the appropriate code for a CPU barrier. For more details, if needed, I can provide a fully-featured reproduction case tomorrow - it's 1:30am right now, and I'm only glad I finally found this one - but here is some pseudo-code that exacerbates and demonstrates the problem: main thread: setup async event setup threaded condition X start SomeThread while forever: signal threaded condition X run libev's ev_run once SomeThread: while forever: wait for threaded condition X signal async event What happens is while ev_run should returned almost immediately, since the other thread signals the async event once right when the main thread enters ev_run, it sometime just stays here for a very long time. Until MAX_BLOCKTIME that is. Another workaround I first found, that confirms the problem, is that I've changed pipe_write_wanted to always be 1. Same exact code using the old barrier code, just writing 1 in pipe_write_wanted instead of 0, in order to force writing into the pipe. That should demonstrate that pipe_write_wanted is getting desynchronised between the thread that runs evpipe_write and the main thread that runs ev_run. Let me know if you have further questions or concerns about this, or if you really want a short reproduction code to demonstrate this - right now my code is a full-blown application that wouldn't be very easy to use as a test case. Thanks, -- Nicolas Noble
_______________________________________________ libev mailing list libev@lists.schmorp.de http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev