doors IPC
Marcus Meissner
marcus at jet.franken.de
Tue May 8 09:05:04 CDT 2001
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;
}
More information about the wine-devel
mailing list