Hi,
Some time ago here was a discussion about speeding up the communication between the wineserver and the application with various kernel patches. I was reading "Unix Network Programming, volume 2 - IPC" and ran over a "doors" IPC api that is implemented on Solaris and has the lowest latency. According to the book it is ~3 times faster than pipe. Actual values for Solaris 2.6 in the book are: (in miliseconds) doors: 121 sysv msgq: 260 pipe: 324 unix dom. socket: 465 posix msgq: 584 ...
There is also a link to a Linux implementation of doors on: http://www.rampant.org/doors/
On this link you will find also more info on doors.
But according to the performance tests that the author made, the linux pipe is somewhat the same speed as doors so maybe it could be optimized more or maybe is Linux's pipe already so optimized that doors are unnecesary.
So what do you think, would this be useful for speeding up wine? I apologoize if you already know about this...
ciao Damjan
On Tue, May 08, 2001 at 03:57:10PM +0000, Damjan Lango wrote:
Hi,
Some time ago here was a discussion about speeding up the communication ...
What a coincidence ;)
I just did a patch changing the critical section handling to become more of a spinlock.
I have attached it. This should reduce the critical section based reschedules between: wine <-> wineserver <-> wine to: wine <-> wine
Since critical sections are thought to be 'fast' and 'short time' locking primitives, and Win32 threads should not sleep in a critical section, we can just give up our timeslice and wait for the other thread that has the lock to continue.
This is a preliminary version, but it works. It uses 'LockSemaphore' as differentation between process-local and global critical sections.
It uses 'sched_yield', which is a POSIX feature, to give up the timeslice. How does one force a reschedule on another UNIX? Is select(0,NULL,NULL,NULL,shorttimeout); reliable?
This patch can give spinning processes on SMP systems, but I do not consider this a real problem at this time.
I would like to know if there is something wrong with the concept ;)
At least winword feels a bit snappier now.
Ciao, Marcus
Index: critsection.c =================================================================== RCS file: /home/wine/wine/dlls/ntdll/critsection.c,v retrieving revision 1.4 diff -u -r1.4 critsection.c --- critsection.c 2001/01/22 02:18:13 1.4 +++ critsection.c 2001/05/08 14:42:54 @@ -122,6 +122,8 @@ */ static inline HANDLE get_semaphore( RTL_CRITICAL_SECTION *crit ) { + return crit->LockSemaphore; +#if 0 HANDLE ret = crit->LockSemaphore; if (!ret) { @@ -134,6 +136,7 @@ NtClose(sem); /* somebody beat us to it */ } return ret; +#endif }
/*********************************************************************** @@ -187,18 +190,48 @@ EXCEPTION_RECORD rec; HANDLE sem = get_semaphore( crit );
- DWORD res = WaitForSingleObject( sem, 5000L ); - if ( res == WAIT_TIMEOUT ) - { - ERR("Critical section %p wait timed out, retrying (60 sec) fs=%04x\n", crit, __get_fs() ); - res = WaitForSingleObject( sem, 60000L ); - if ( res == WAIT_TIMEOUT && TRACE_ON(relay) ) - { - ERR("Critical section %p wait timed out, retrying (5 min) fs=%04x\n", crit, __get_fs() ); - res = WaitForSingleObject( sem, 300000L ); - } - } - if (res == STATUS_WAIT_0) return STATUS_SUCCESS; + if (sem) { + DWORD res = WaitForSingleObject( sem, 5000L ); + if ( res == WAIT_TIMEOUT ) + { + ERR("Critical section %p wait timed out, retrying (60 sec) fs=%04x\n", crit, __get_fs() ); + res = WaitForSingleObject( sem, 60000L ); + if ( res == WAIT_TIMEOUT && TRACE_ON(relay) ) + { + ERR("Critical section %p wait timed out, retrying (5 min) fs=%04x\n", crit, __get_fs() ); + res = WaitForSingleObject( sem, 300000L ); + } + } + if (res == STATUS_WAIT_0) return STATUS_SUCCESS; + } else { + time_t starttm; + int warnlev = 0; + + /* Fast in process path */ + starttm = time(NULL); + interlocked_dec(&crit->LockCount); + while ( !RtlTryEnterCriticalSection(crit) && (warnlev<2) ) { + time_t thistm; + + sched_yield(); + + thistm = time(NULL); + switch (warnlev) { + case 0: if ((thistm - starttm)==5) { + ERR("Critical section %p wait timed out, retrying (60 sec) fs=%04x\n", crit, __get_fs() ); + warnlev++; + } + break; + case 1: if ((thistm - starttm)==60) { + ERR("Critical section %p wait timed out, retrying (60 sec) fs=%04x\n", crit, __get_fs() ); + warnlev++; + } + break; + default:break; + } + } + if (warnlev < 2) return STATUS_SUCCESS; + }
rec.ExceptionCode = EXCEPTION_CRITICAL_SECTION_WAIT; rec.ExceptionFlags = 0; @@ -217,7 +250,8 @@ NTSTATUS WINAPI RtlpUnWaitCriticalSection( RTL_CRITICAL_SECTION *crit ) { HANDLE sem = get_semaphore( crit ); - NTSTATUS res = NtReleaseSemaphore( sem, 1, NULL ); + NTSTATUS res = 0; + if (sem) res = NtReleaseSemaphore( sem, 1, NULL ); if (res) RtlRaiseStatus( res ); return res; }