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; }