[PATCH] CriticalSection SpinCount Implementation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The following patch implements all the goo related to SpinCount, by doing the 
following:
1) Implement RtlSetCriticalSectionSpinCount and make 
SetCriticalSectionSpinCount call down to it.
2) A bit more NtQuerySystemInformation implementation so we can determine if 
we're running as UP or SMP from within NTDLL. This is important, because 
SetCriticalSectionSpinCount and RtlInitializeCriticalSectionAndSpinCount have 
different semantics under the two environments.
3) Make RtlInitializeCriticalSection call 
RtlInitializeCriticalSectionAndSpinCount. This prevents the former call from 
creating a critical section with an uninitialized SpinCount value as it was 
before.
4) Make RtlpWaitForCriticalSection spin SpinCount times before calling 
WaitForSingleObject

-Ryan
? controls/edit.glue.c
? dlls/gdi/printdrv.glue.c
? dlls/gdi/win16drv/prtdrv.glue.c
? dlls/kernel/utthunk.glue.c
? dlls/msvideo/msvideo_main.glue.c
? dlls/setupapi/virtcopy.glue.c
? dlls/user/property.glue.c
? dlls/user/text.glue.c
? dlls/user/wnd16.glue.c
? dlls/user/dde/ddeml16.glue.c
? dlls/winaspi/winaspi16.glue.c
? dlls/winmm/lolvldrv.glue.c
? dlls/winmm/mmsystem.glue.c
? dlls/winmm/time.glue.c
? loader/task.glue.c
? loader/ne/module.glue.c
? loader/ne/segment.glue.c
? memory/local.glue.c
? objects/dc.glue.c
? objects/font.glue.c
? objects/gdiobj.glue.c
? objects/linedda.glue.c
? objects/metafile.glue.c
? windows/driver.glue.c
? windows/hook.glue.c
? windows/painting.glue.c
Index: dlls/ntdll/critsection.c
===================================================================
RCS file: /home/wine/wine/dlls/ntdll/critsection.c,v
retrieving revision 1.13
diff -u -r1.13 critsection.c
--- dlls/ntdll/critsection.c	12 Sep 2002 22:07:03 -0000	1.13
+++ dlls/ntdll/critsection.c	13 Sep 2002 16:25:38 -0000
@@ -42,6 +42,22 @@
     return interlocked_xchg_add( dest, -1 ) - 1;
 }
 
+static BOOL is_smp()
+{
+   static BOOL cached = FALSE;
+   static BOOL value;
+
+   if (!cached)
+   {
+      SYSTEM_BASIC_INFORMATION info;
+      NtQuerySystemInformation(0x0, &info, sizeof(info), 0);
+      value = (info.bKeNumberProcessors > 1);
+      cached = TRUE;
+   }
+
+   return value;
+}
+
 /***********************************************************************
  *           get_semaphore
  */
@@ -66,12 +82,7 @@
  */
 NTSTATUS WINAPI RtlInitializeCriticalSection( RTL_CRITICAL_SECTION *crit )
 {
-    crit->DebugInfo      = NULL;
-    crit->LockCount      = -1;
-    crit->RecursionCount = 0;
-    crit->OwningThread   = 0;
-    crit->LockSemaphore  = 0;
-    return STATUS_SUCCESS;
+    return RtlInitializeCriticalSectionAndSpinCount( crit, 0 );
 }
 
 /***********************************************************************
@@ -83,11 +94,38 @@
  */
 NTSTATUS WINAPI RtlInitializeCriticalSectionAndSpinCount( RTL_CRITICAL_SECTION *crit, DWORD spincount )
 {
-    if(spincount) TRACE("critsection=%p: spincount=%ld not supported\n", crit, spincount);
-    crit->SpinCount = spincount;
-    return RtlInitializeCriticalSection( crit );
+    crit->DebugInfo      = NULL;
+    crit->LockCount      = -1;
+    crit->RecursionCount = 0;
+    crit->OwningThread   = 0;
+    crit->LockSemaphore  = 0;
+
+    if (spincount && is_smp())
+        crit->SpinCount = spincount;
+    else
+        crit->SpinCount = 0;
+
+    return STATUS_SUCCESS;
 }
 
+/***********************************************************************
+ *           RtlSetCriticalSectionSpinCount   (NTDLL.@)
+ */
+DWORD WINAPI RtlSetCriticalSectionSpinCount( RTL_CRITICAL_SECTION *crit, DWORD dwSpinCount )
+{
+    DWORD ret = crit->SpinCount;
+
+    if (dwSpinCount && is_smp())
+    {
+        crit->SpinCount = dwSpinCount;
+    }
+    else
+    {
+        crit->SpinCount = 0;
+    }
+
+    return ret;
+}
 
 /***********************************************************************
  *           RtlDeleteCriticalSection   (NTDLL.@)
@@ -112,6 +150,16 @@
     {
         EXCEPTION_RECORD rec;
         HANDLE sem = get_semaphore( crit );
+        ULONG tries;  
+
+        /* Try spinning on the lock a bit before going to
+           WaitForSingleObject. This path should only be
+           followed on SMP systems. */
+        for(tries = crit->SpinCount;tries;tries--)
+        {
+            if (RtlTryEnterCriticalSection(crit))
+                return STATUS_SUCCESS;
+        }
 
         DWORD res = WaitForSingleObject( sem, 5000L );
         if ( res == WAIT_TIMEOUT )
Index: dlls/ntdll/nt.c
===================================================================
RCS file: /home/wine/wine/dlls/ntdll/nt.c,v
retrieving revision 1.44
diff -u -r1.44 nt.c
--- dlls/ntdll/nt.c	12 Sep 2002 22:07:03 -0000	1.44
+++ dlls/ntdll/nt.c	13 Sep 2002 16:25:38 -0000
@@ -24,6 +24,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 #include <time.h>
 #include "wine/debug.h"
 
@@ -31,6 +32,10 @@
 #include "ntdll_misc.h"
 #include "wine/server.h"
 
+#ifdef linux
+#include <sys/sysinfo.h>
+#endif
+
 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
 
 /*
@@ -650,8 +655,33 @@
 	IN ULONG Length,
 	OUT PULONG ResultLength)
 {
+    SYSTEM_BASIC_INFORMATION *basic_info = (SYSTEM_BASIC_INFORMATION*)SystemInformation;
+
     switch(SystemInformationClass)
     {
+    case 0x0:
+	ZeroMemory (SystemInformation, Length);
+
+        /* Fill out a few choice fields */
+
+        if (ResultLength)
+            *ResultLength = sizeof(SYSTEM_BASIC_INFORMATION);
+
+        basic_info->uPageSize = getpagesize();
+
+#ifdef linux
+        {
+            struct sysinfo info;
+            sysinfo(&info);
+            basic_info->bKeNumberProcessors = info.procs;
+        }
+#else
+        basic_info->bKeNumberProcessors = 1;
+#endif
+
+	FIXME("(0x%08x,%p,0x%08lx,%p) partial stub\n",
+	      SystemInformationClass,SystemInformation,Length,ResultLength);
+
     case 0x25:
 	/* Something to do with the size of the registry             *
 	 * Since we don't have a size limitation, fake it            *
Index: dlls/ntdll/ntdll.spec
===================================================================
RCS file: /home/wine/wine/dlls/ntdll/ntdll.spec,v
retrieving revision 1.76
diff -u -r1.76 ntdll.spec
--- dlls/ntdll/ntdll.spec	6 Sep 2002 18:51:32 -0000	1.76
+++ dlls/ntdll/ntdll.spec	13 Sep 2002 16:25:39 -0000
@@ -499,6 +499,7 @@
 @ stub RtlSelfRelativeToAbsoluteSD
 @ stdcall RtlSetAllBits(ptr) RtlSetAllBits
 @ stdcall RtlSetBits(ptr long long) RtlSetBits
+@ stdcall RtlSetCriticalSectionSpinCount(ptr long) RtlSetCriticalSectionSpinCount
 @ stub RtlSetCurrentDirectory_U
 @ stub RtlSetCurrentEnvironment
 @ stdcall RtlSetDaclSecurityDescriptor(ptr long ptr long) RtlSetDaclSecurityDescriptor
Index: include/winternl.h
===================================================================
RCS file: /home/wine/wine/include/winternl.h,v
retrieving revision 1.2
diff -u -r1.2 winternl.h
--- include/winternl.h	12 Sep 2002 22:07:05 -0000	1.2
+++ include/winternl.h	13 Sep 2002 16:25:39 -0000
@@ -950,6 +950,7 @@
 void      WINAPI RtlSecondsSince1980ToTime(DWORD,LARGE_INTEGER *);
 void      WINAPI RtlSetAllBits(PRTL_BITMAP);
 void      WINAPI RtlSetBits(PRTL_BITMAP,ULONG,ULONG);
+DWORD     WINAPI RtlSetCriticalSectionSpinCount(RTL_CRITICAL_SECTION *,DWORD);
 NTSTATUS  WINAPI RtlSetDaclSecurityDescriptor(PSECURITY_DESCRIPTOR,BOOLEAN,PACL,BOOLEAN);
 DWORD     WINAPI RtlSetEnvironmentVariable(DWORD,PUNICODE_STRING,PUNICODE_STRING);
 NTSTATUS  WINAPI RtlSetOwnerSecurityDescriptor(PSECURITY_DESCRIPTOR,PSID,BOOLEAN);
Index: scheduler/critsection.c
===================================================================
RCS file: /home/wine/wine/scheduler/critsection.c,v
retrieving revision 1.35
diff -u -r1.35 critsection.c
--- scheduler/critsection.c	12 Sep 2002 22:07:06 -0000	1.35
+++ scheduler/critsection.c	13 Sep 2002 16:25:44 -0000
@@ -61,10 +61,7 @@
  */
 DWORD WINAPI SetCriticalSectionSpinCount( CRITICAL_SECTION *crit, DWORD spincount )
 {
-    ULONG_PTR oldspincount = crit->SpinCount;
-    if(spincount) FIXME("critsection=%p: spincount=%ld not supported\n", crit, spincount);
-    crit->SpinCount = spincount;
-    return oldspincount;
+    return RtlSetCriticalSectionSpinCount( crit, spincount );
 }
 
 /***********************************************************************

[Index of Archives]     [Gimp for Windows]     [Red Hat]     [Samba]     [Yosemite Camping]     [Graphics Cards]     [Wine Home]

  Powered by Linux