Optimize Critical Section Functions

Robert Shearman rob at codeweavers.com
Fri Aug 20 10:50:36 CDT 2004


Hi,

With this patch GCC generates better code for critical sections in the 
case of the fast paths with no contention.

Rob

Changelog:
Optimize critical section functions by telling GCC how likely certain 
branches are.

-------------- next part --------------
Index: wine/dlls/ntdll/critsection.c
===================================================================
RCS file: /home/wine/wine/dlls/ntdll/critsection.c,v
retrieving revision 1.26
diff -u -p -r1.26 critsection.c
--- wine/dlls/ntdll/critsection.c	17 Jun 2004 23:11:08 -0000	1.26
+++ wine/dlls/ntdll/critsection.c	20 Aug 2004 15:46:18 -0000
@@ -36,6 +36,14 @@
 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
 WINE_DECLARE_DEBUG_CHANNEL(relay);
 
+#ifdef __GNUC__
+# define likely(x)   __builtin_expect(!!(x), 1)
+# define unlikely(x) __builtin_expect(!!(x), 0)
+#else
+# define likely(x)   !!(x)
+# define unlikely(x) !!(x)
+#endif
+
 inline static LONG interlocked_inc( PLONG dest )
 {
     return interlocked_xchg_add( dest, 1 ) + 1;
@@ -61,7 +69,7 @@ inline static void small_pause(void)
 static inline HANDLE get_semaphore( RTL_CRITICAL_SECTION *crit )
 {
     HANDLE ret = crit->LockSemaphore;
-    if (!ret)
+    if (unlikely( !ret ))
     {
         HANDLE sem;
         if (NtCreateSemaphore( &sem, SEMAPHORE_ALL_ACCESS, NULL, 0, 1 )) return 0;
@@ -209,7 +217,7 @@ NTSTATUS WINAPI RtlpWaitForCriticalSecti
 
         time.QuadPart = -5000 * 10000;  /* 5 seconds */
         status = NtWaitForSingleObject( sem, FALSE, &time );
-        if ( status == WAIT_TIMEOUT )
+        if (unlikely( status == WAIT_TIMEOUT ))
         {
             const char *name = NULL;
             if (crit->DebugInfo) name = (char *)crit->DebugInfo->Spare[1];
@@ -226,7 +234,7 @@ NTSTATUS WINAPI RtlpWaitForCriticalSecti
                 status = NtWaitForSingleObject( sem, FALSE, &time );
             }
         }
-        if (status == STATUS_WAIT_0) return STATUS_SUCCESS;
+        if (likely( status == STATUS_WAIT_0 )) return STATUS_SUCCESS;
 
         /* Throw exception only for Wine internal locks */
         if ((!crit->DebugInfo) || (!crit->DebugInfo->Spare[1])) continue;
@@ -270,7 +278,7 @@ NTSTATUS WINAPI RtlpUnWaitCriticalSectio
  */
 NTSTATUS WINAPI RtlEnterCriticalSection( RTL_CRITICAL_SECTION *crit )
 {
-    if (crit->SpinCount)
+    if (unlikely( crit->SpinCount ))
     {
         ULONG count;
 
@@ -286,7 +294,7 @@ NTSTATUS WINAPI RtlEnterCriticalSection(
         }
     }
 
-    if (interlocked_inc( &crit->LockCount ))
+    if (unlikely( interlocked_inc( &crit->LockCount ) ))
     {
         if (crit->OwningThread == (HANDLE)GetCurrentThreadId())
         {
@@ -348,11 +356,11 @@ BOOL WINAPI RtlTryEnterCriticalSection( 
  */
 NTSTATUS WINAPI RtlLeaveCriticalSection( RTL_CRITICAL_SECTION *crit )
 {
-    if (--crit->RecursionCount) interlocked_dec( &crit->LockCount );
+    if (likely( --crit->RecursionCount )) interlocked_dec( &crit->LockCount );
     else
     {
         crit->OwningThread = 0;
-        if (interlocked_dec( &crit->LockCount ) >= 0)
+        if (unlikely( interlocked_dec( &crit->LockCount ) >= 0 ))
         {
             /* someone is waiting */
             RtlpUnWaitCriticalSection( crit );


More information about the wine-patches mailing list