CVS: winex/dlls/ntdll critsection.c,1.17,1.18

[email protected] 31 Jul 2007 18:00:48 -0000
Newsgroups gmane.comp.emulators.winex.cvs
Message-ID <[email protected]>
Subject: winex/dlls/ntdll critsection.c,1.17,1.18Update of /var/lib/cvsd/cvsroot/winex/dlls/ntdll
In directory agravaine:/tmp/cvs-serv24840/dlls/ntdll

Modified Files:
	critsection.c 
Log Message:

- add assembly versions of RtlEnterCriticalSection and RtlLeaveCriticalSection to optimize the fast path (ie, that the CS is available for us to take)



Index: critsection.c
===================================================================
RCS file: /var/lib/cvsd/cvsroot/winex/dlls/ntdll/critsection.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- critsection.c	30 Mar 2007 15:55:17 -0000	1.17
+++ critsection.c	31 Jul 2007 18:00:46 -0000	1.18
@@ -14,6 +14,7 @@
 #endif
 #include "winerror.h"
 #include "winternl.h"
+#include "wine/port.h"
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
@@ -523,37 +524,74 @@
 
 
 /***********************************************************************
+ * function called by EnterCriticalSection if the section is contested
+ * Note - must be WINAPI (and non-static?) to ensure stack alignment
+ * fixups are done on MacOS X, since we don't do them in the
+ * hand-coded EnterCriticalSection()
+*/
+NTSTATUS WINAPI EnterContestedCriticalSection (RTL_CRITICAL_SECTION *crit,
+                                               DWORD dwThreadId)
+{
+   DWORD dwCount;
+
+   if (crit->OwningThread == dwThreadId)
+   {
+      crit->RecursionCount++;
+      return STATUS_SUCCESS;
+   }
+
+   /* Spin if desired */
+   for (dwCount = crit->SpinCount; dwCount; dwCount--)
+   {
+      if (RtlTryEnterCriticalSection (crit))
+         return STATUS_SUCCESS;
+   }
+
+   /* Blocking wait for it */
+   RtlpWaitForCriticalSection (crit);
+    
+   crit->OwningThread   = dwThreadId;
+   crit->RecursionCount = 1;
+
+   return STATUS_SUCCESS;
+}
+
+
+/***********************************************************************
  *           RtlEnterCriticalSection   (NTDLL.@)
+ *
  */
+#ifdef __i386__
+__ASM_GLOBAL_FUNC(RtlEnterCriticalSection,
+                  "mov    %fs:0x24,%ecx\n\t"
+                  "mov    0x4(%esp),%edx\n\t"
+                  "lock; incl 0x4(%edx)\n\t"
+                  "jne    1f\n\t"
+                  "mov    %ecx,%eax\n\t"
+                  "movl   $0x1,0x8(%edx)\n\t"
+                  "mov    %eax,0xc(%edx)\n\t"
+                  "xor    %eax,%eax\n\t"
+                  "ret    $0x4\n\t"
+                  "1: push   %ecx\n\t"
+                  "push   %edx\n\t"
+                  "call   " __ASM_NAME("EnterContestedCriticalSection") "\n\t"
+                  "ret    $0x4");
+#else
 NTSTATUS WINAPI RtlEnterCriticalSection( RTL_CRITICAL_SECTION *crit )
 {
-    const DWORD dwThreadId = GetCurrentThreadId();
-
-    if (interlocked_inc( &crit->LockCount ))
-    {
-        DWORD dwCount;
+   const DWORD dwThreadId = GetCurrentThreadId ();
 
-        if (crit->OwningThread == dwThreadId)
-        {
-            crit->RecursionCount++;
-            return STATUS_SUCCESS;
-        }
-	
-        /* Spin if desired */
-        for( dwCount = crit->SpinCount; dwCount; dwCount-- )
-        {
-            if( RtlTryEnterCriticalSection( crit ) ) return STATUS_SUCCESS;
-        }
+   if (!interlocked_inc (&crit->LockCount))
+   {
+      crit->OwningThread   = dwThreadId;
+      crit->RecursionCount = 1;
 
-        /* Blocking wait for it */
-        RtlpWaitForCriticalSection( crit );
-    }
-    
-    crit->OwningThread   = dwThreadId;
-    crit->RecursionCount = 1;
+      return STATUS_SUCCESS;
+   }
 
-    return STATUS_SUCCESS;
+   return EnterContestedCriticalSection (crit, dwThreadId);
 }
+#endif
 
 
 /***********************************************************************
@@ -581,6 +619,23 @@
 /***********************************************************************
  *           RtlLeaveCriticalSection   (NTDLL.@)
  */
+#ifdef __i386__
+__ASM_GLOBAL_FUNC(RtlLeaveCriticalSection,
+                  "mov    0x4(%esp),%edx\n\t"
+                  "xor    %eax,%eax\n\t"
+                  "decl   0x8(%edx)\n\t"
+                  "jne    1f\n\t"
+                  "mov    %eax,0xc(%edx)\n\t"
+                  "lock; decl 0x4(%edx)\n\t"
+                  "jge    2f\n\t"
+                  "ret    $0x4\n\t"
+                  "1: lock; decl 0x4(%edx)\n\t"
+                  "ret    $0x4\n\t"
+                  "2: push %edx\n\t"
+                  "call " __ASM_NAME("RtlpUnWaitCriticalSection") "\n\t"
+                  "xor    %eax,%eax\n\t"
+                  "ret    $0x4");
+#else
 NTSTATUS WINAPI RtlLeaveCriticalSection( RTL_CRITICAL_SECTION *crit )
 {
     if (--crit->RecursionCount) interlocked_dec( &crit->LockCount );
@@ -595,3 +650,4 @@
     }
     return STATUS_SUCCESS;
 }
+#endif