http://bugs.winehq.org/show_bug.cgi?id=34865
--- Comment #2 from Anastasius Focht focht@gmx.net 2013-11-11 15:18:01 CST --- Hello again,
it seems the Cygwin dll distributed with R-studio is a custom build (snapshot) that has a very short-lived patch applied which introduces the use of APC to create the signal receiver thread.
Again: that patch never made it into official source tree!
After unsuccessfully digging the CVS history and I found a discussion related to user APC on the Cygwin mailing list:
http://marc.info/?t=131176630600003
Patch: http://www.mail-archive.com/cygwin-patches@cygwin.com/msg05242.html
--- quote --- As sigproc_init is called during dll initialization, wait_sig thread is not created as soon as possible.(this is known in msdn createthread reference. http://msdn.microsoft.com/en-us/library/ms682453(v=vs.85).aspx) And then wait_sig starts to wake up as sig_dispatch_pending enters waitforsingleobject. then main thread stops for few ms. and it shows poor performance.
as a workaround, issue user apc call, let the os decide when to call them. And the result was quite good. patch,changelog modified are attached. Please review it. --- quote ---
Corinna's answer:
--- quote --- The slowdown of the code was the result of a patch which was supposed to fix a potential race condition. Jojelino's patch looks nice, but it might reintroduce a new race. Handle with care. --- quote ---
Compare Cygwin1.dll disassembly (see patch source):
--- snip --- 610DA9E9 mov edx, 611EA590h ; "sync_proc_subproc" ... 610DAA04 mov dword ptr [eax+18h], 611EA5A2h ; "sig" ... 610DAA29 call GetCurrentThread 610DAA2E mov [esp+8], ebx 610DAA32 mov dword ptr [esp], 61003DB0h ; address of user APC 610DAA39 mov [esp+4], eax 610DAA3D call QueueUserAPC ... --- snip ---
Date/size of cygwin dll:
--- snip --- -rw-rw-r--. 1 focht focht 2288181 Jul 16 2012 cygwin1.dll --- snip ---
--- quote --- On Sat, Jul 30, 2011 at 05:09:08PM -0400, Christopher Faylor wrote:
Oops. Forgot to mention that these changes are available in the most recent snapshot at: http://cygwin.com/snapshots/ . --- quote ---
Unfortunately this snapshot is too far away and not available anymore.
The queued APC needs to be executed only once to create the real signal receiver thread which handles the other end of the pipe. My guess would be that this APC is implicitly triggered by some win API calls that have alertable wait under the hood.
I manually triggered the APC and it indeed created the signal thread.
The APC entry point address 0x61003db0. Direct win64 API calls from within the APC can be easily found at that range 0x61003xxx:
--- snip --- ... 002f:Call KERNEL32.QueueUserAPC(61003db0,fffffffe,61188380) ret=610daa42 002f:Ret KERNEL32.QueueUserAPC() retval=00000001 ret=610daa42 ... 002f:Call KERNEL32.CreateThread(6119a7ec,00000000,61003f30,61188380,00000000,61188384) ret=61003d33 ... 002f:Ret KERNEL32.CreateThread() retval=00000138 ret=61003d33 002f:Call KERNEL32.SetThreadPriority(00000138,00000002) ret=61003dd2 0030:Call PE DLL (proc=0x6107f390,module=0x61000000 L"cygwin1.dll",reason=THREAD_ATTACH,res=(nil)) 002f:Ret KERNEL32.SetThreadPriority() retval=00000001 ret=61003dd2 0030:Ret PE DLL (proc=0x6107f390,module=0x61000000 L"cygwin1.dll",reason=THREAD_ATTACH,res=(nil)) retval=1 002f:Call KERNEL32.CloseHandle(00000138) ret=61003de0 0030:Call PE DLL (proc=0x7ecf6e94,module=0x7ec40000 L"user32.dll",reason=THREAD_ATTACH,res=(nil)) 0030:Ret PE DLL (proc=0x7ecf6e94,module=0x7ec40000 L"user32.dll",reason=THREAD_ATTACH,res=(nil)) retval=1 ... 0030:Starting thread proc 0x6107f360 (arg=0x61188380) --- snip ---
I'm not sure why RStudio chose a Cygwin snapshot with custom patches applied for their official 3.0.2 release for Windows.
Regards