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