[PATCH] ntdll: Implement dynamic spinning

Jangwoong Kim 6812skiii at gmail.com
Fri Jan 1 07:41:08 CST 2021


Previously, InitialzeCriticalSectionEx with
RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN worked as semi-stub.

This patch implements dynamic spinning.
Specifically, 32th bit from the right (starting with zero index)
indicates whether it is dynamically spinning critical section.

Signed-off-by: Jangwoong Kim <6812skiii at gmail.com>
---
 dlls/ntdll/critsection.c | 45 +++++++++++++++++++++++++++++++++-------
 1 file changed, 38 insertions(+), 7 deletions(-)

diff --git a/dlls/ntdll/critsection.c b/dlls/ntdll/critsection.c
index fe7d933c0fa..8642015e05c 100644
--- a/dlls/ntdll/critsection.c
+++ b/dlls/ntdll/critsection.c
@@ -20,6 +20,7 @@
 
 #include <assert.h>
 #include <errno.h>
+#include <limits.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <sys/types.h>
@@ -34,6 +35,10 @@
 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
 WINE_DECLARE_DEBUG_CHANNEL(relay);
 
+#define IS_DYNAMIC_SPIN crit->SpinCount >> 31 == 1 ? TRUE : FALSE
+#define MAX_ADAPTIVE_SPIN_COUNT 100
+#define MIN(a,b) (((a)<(b))?(a):(b))
+
 static inline void small_pause(void)
 {
 #ifdef __i386__
@@ -159,7 +164,7 @@ NTSTATUS WINAPI RtlInitializeCriticalSectionAndSpinCount( RTL_CRITICAL_SECTION *
  */
 NTSTATUS WINAPI RtlInitializeCriticalSectionEx( RTL_CRITICAL_SECTION *crit, ULONG spincount, ULONG flags )
 {
-    if (flags & (RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN|RTL_CRITICAL_SECTION_FLAG_STATIC_INIT))
+    if (flags & RTL_CRITICAL_SECTION_FLAG_STATIC_INIT)
         FIXME("(%p,%u,0x%08x) semi-stub\n", crit, spincount, flags);
 
     /* FIXME: if RTL_CRITICAL_SECTION_FLAG_STATIC_INIT is given, we should use
@@ -189,8 +194,15 @@ NTSTATUS WINAPI RtlInitializeCriticalSectionEx( RTL_CRITICAL_SECTION *crit, ULON
     crit->RecursionCount = 0;
     crit->OwningThread   = 0;
     crit->LockSemaphore  = 0;
+    spincount = spincount & ~0x80000000;
+    if (flags & RTL_CRITICAL_SECTION_FLAG_DYNAMIC_SPIN)
+    {
+        spincount = MIN(spincount, MAX_ADAPTIVE_SPIN_COUNT);
+        /* 31th bit (from right starting with 0) indicates whether it is dynamically spinning CS */
+        spincount |= ((ULONG)1 << 31);
+    }
     if (NtCurrentTeb()->Peb->NumberOfProcessors <= 1) spincount = 0;
-    crit->SpinCount = spincount & ~0x80000000;
+    crit->SpinCount = spincount;
     return STATUS_SUCCESS;
 }
 
@@ -403,14 +415,33 @@ NTSTATUS WINAPI RtlEnterCriticalSection( RTL_CRITICAL_SECTION *crit )
         ULONG count;
 
         if (RtlTryEnterCriticalSection( crit )) return STATUS_SUCCESS;
-        for (count = crit->SpinCount; count > 0; count--)
+        if (IS_DYNAMIC_SPIN)
+        {
+            ULONG max_count = MIN(MAX_ADAPTIVE_SPIN_COUNT, crit->SpinCount & ~0x80000000 * 2);
+            for (count = 0 ; count < max_count ; count++) {
+                if (crit->LockCount == -1)
+                {
+                  if (InterlockedCompareExchange( &crit->LockCount, 0, -1 ) == -1)
+                      {
+                          crit->SpinCount += ((LONG)count - (LONG)(crit->SpinCount & ~0x80000000)) / 10;
+                          goto done;
+                      }
+                }
+                small_pause();
+            }
+            crit->SpinCount += ((LONG)count - (LONG)(crit->SpinCount & ~0x80000000)) / 10;
+        }
+        else
         {
-            if (crit->LockCount > 0) break;  /* more than one waiter, don't bother spinning */
-            if (crit->LockCount == -1)       /* try again */
+            for (count = crit->SpinCount; count > 0; count--)
             {
-                if (InterlockedCompareExchange( &crit->LockCount, 0, -1 ) == -1) goto done;
+                if (crit->LockCount > 0) break;  /* more than one waiter, don't bother spinning */
+                if (crit->LockCount == -1)       /* try again */
+                {
+                    if (InterlockedCompareExchange( &crit->LockCount, 0, -1 ) == -1) goto done;
+                }
+                small_pause();
             }
-            small_pause();
         }
     }
 
-- 
2.25.1




More information about the wine-devel mailing list