[PATCH 2/5] ntdll: Factor out heap serialization to heap_(lock|unlock) helpers.

Rémi Bernon rbernon at codeweavers.com
Thu Apr 28 05:31:46 CDT 2022


Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/ntdll/heap.c | 107 ++++++++++++++++++++++++----------------------
 1 file changed, 56 insertions(+), 51 deletions(-)

diff --git a/dlls/ntdll/heap.c b/dlls/ntdll/heap.c
index 7f41088347d..c3689ecca9e 100644
--- a/dlls/ntdll/heap.c
+++ b/dlls/ntdll/heap.c
@@ -162,7 +162,7 @@ typedef struct tagHEAP
     DWORD            magic;         /* Magic number */
     DWORD            pending_pos;   /* Position in pending free requests ring */
     ARENA_INUSE    **pending_free;  /* Ring buffer for pending free requests */
-    RTL_CRITICAL_SECTION critSection; /* Critical section for serialization */
+    RTL_CRITICAL_SECTION cs;
     FREE_LIST_ENTRY *freeList;      /* Free lists */
 } HEAP;
 
@@ -324,13 +324,24 @@ static inline ULONG get_protection_type( DWORD flags )
     return (flags & HEAP_CREATE_ENABLE_EXECUTE) ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
 }
 
-static RTL_CRITICAL_SECTION_DEBUG process_heap_critsect_debug =
+static RTL_CRITICAL_SECTION_DEBUG process_heap_cs_debug =
 {
     0, 0, NULL,  /* will be set later */
-    { &process_heap_critsect_debug.ProcessLocksList, &process_heap_critsect_debug.ProcessLocksList },
+    { &process_heap_cs_debug.ProcessLocksList, &process_heap_cs_debug.ProcessLocksList },
       0, 0, { (DWORD_PTR)(__FILE__ ": main process heap section") }
 };
 
+static void heap_lock( HEAP *heap, DWORD flags )
+{
+    if ((flags | heap->flags) & HEAP_NO_SERIALIZE) return;
+    RtlEnterCriticalSection( &heap->cs );
+}
+
+static void heap_unlock( HEAP *heap, DWORD flags )
+{
+    if ((flags | heap->flags) & HEAP_NO_SERIALIZE) return;
+    RtlLeaveCriticalSection( &heap->cs );
+}
 
 /***********************************************************************
  *           HEAP_Dump
@@ -958,31 +969,31 @@ static SUBHEAP *HEAP_CreateSubHeap( HEAP *heap, LPVOID address, DWORD flags,
 
         if (!processHeap)  /* do it by hand to avoid memory allocations */
         {
-            heap->critSection.DebugInfo      = &process_heap_critsect_debug;
-            heap->critSection.LockCount      = -1;
-            heap->critSection.RecursionCount = 0;
-            heap->critSection.OwningThread   = 0;
-            heap->critSection.LockSemaphore  = 0;
-            heap->critSection.SpinCount      = 0;
-            process_heap_critsect_debug.CriticalSection = &heap->critSection;
+            heap->cs.DebugInfo      = &process_heap_cs_debug;
+            heap->cs.LockCount      = -1;
+            heap->cs.RecursionCount = 0;
+            heap->cs.OwningThread   = 0;
+            heap->cs.LockSemaphore  = 0;
+            heap->cs.SpinCount      = 0;
+            process_heap_cs_debug.CriticalSection = &heap->cs;
         }
         else
         {
-            RtlInitializeCriticalSection( &heap->critSection );
-            heap->critSection.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": HEAP.critSection");
+            RtlInitializeCriticalSection( &heap->cs );
+            heap->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": heap.cs");
         }
 
         if (heap->shared)
         {
             /* let's assume that only one thread at a time will try to do this */
-            HANDLE sem = heap->critSection.LockSemaphore;
+            HANDLE sem = heap->cs.LockSemaphore;
             if (!sem) NtCreateSemaphore( &sem, SEMAPHORE_ALL_ACCESS, NULL, 0, 1 );
 
             NtDuplicateObject( NtCurrentProcess(), sem, NtCurrentProcess(), &sem, 0, 0,
                                DUPLICATE_MAKE_GLOBAL | DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE );
-            heap->critSection.LockSemaphore = sem;
-            RtlFreeHeap( processHeap, 0, heap->critSection.DebugInfo );
-            heap->critSection.DebugInfo = NULL;
+            heap->cs.LockSemaphore = sem;
+            RtlFreeHeap( processHeap, 0, heap->cs.DebugInfo );
+            heap->cs.DebugInfo = NULL;
         }
     }
 
@@ -1339,11 +1350,7 @@ static BOOL HEAP_IsRealArena( HEAP *heapPtr,   /* [in] ptr to the heap */
     BOOL ret = FALSE;
     const ARENA_LARGE *large_arena;
 
-    flags &= HEAP_NO_SERIALIZE;
-    flags |= heapPtr->flags;
-    /* calling HeapLock may result in infinite recursion, so do the critsect directly */
-    if (!(flags & HEAP_NO_SERIALIZE))
-        RtlEnterCriticalSection( &heapPtr->critSection );
+    heap_lock( heapPtr, flags );
 
     if (block)  /* only check this single memory block */
     {
@@ -1389,7 +1396,7 @@ static BOOL HEAP_IsRealArena( HEAP *heapPtr,   /* [in] ptr to the heap */
     ret = TRUE;
 
 done:
-    if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection );
+    heap_unlock( heapPtr, flags );
     return ret;
 }
 
@@ -1569,9 +1576,9 @@ HANDLE WINAPI RtlCreateHeap( ULONG flags, PVOID addr, SIZE_T totalSize, SIZE_T c
     if (processHeap)
     {
         HEAP *heapPtr = subheap->heap;
-        RtlEnterCriticalSection( &processHeap->critSection );
+        RtlEnterCriticalSection( &processHeap->cs );
         list_add_head( &processHeap->entry, &heapPtr->entry );
-        RtlLeaveCriticalSection( &processHeap->critSection );
+        RtlLeaveCriticalSection( &processHeap->cs );
     }
     else if (!addr)
     {
@@ -1615,12 +1622,12 @@ HANDLE WINAPI RtlDestroyHeap( HANDLE heap )
     if (heap == processHeap) return heap; /* cannot delete the main process heap */
 
     /* remove it from the per-process list */
-    RtlEnterCriticalSection( &processHeap->critSection );
+    RtlEnterCriticalSection( &processHeap->cs );
     list_remove( &heapPtr->entry );
-    RtlLeaveCriticalSection( &processHeap->critSection );
+    RtlLeaveCriticalSection( &processHeap->cs );
 
-    heapPtr->critSection.DebugInfo->Spare[0] = 0;
-    RtlDeleteCriticalSection( &heapPtr->critSection );
+    heapPtr->cs.DebugInfo->Spare[0] = 0;
+    RtlDeleteCriticalSection( &heapPtr->cs );
 
     LIST_FOR_EACH_ENTRY_SAFE( arena, arena_next, &heapPtr->large_list, ARENA_LARGE, entry )
     {
@@ -1685,12 +1692,12 @@ void * WINAPI DECLSPEC_HOTPATCH RtlAllocateHeap( HANDLE heap, ULONG flags, SIZE_
     }
     if (rounded_size < HEAP_MIN_DATA_SIZE) rounded_size = HEAP_MIN_DATA_SIZE;
 
-    if (!(flags & HEAP_NO_SERIALIZE)) RtlEnterCriticalSection( &heapPtr->critSection );
+    heap_lock( heapPtr, flags );
 
     if (rounded_size >= HEAP_MIN_LARGE_BLOCK_SIZE && (flags & HEAP_GROWABLE))
     {
         void *ret = allocate_large_block( heap, flags, size );
-        if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection );
+        heap_unlock( heapPtr, flags );
         if (!ret && (flags & HEAP_GENERATE_EXCEPTIONS)) RtlRaiseStatus( STATUS_NO_MEMORY );
         TRACE("(%p,%08x,%08lx): returning %p\n", heap, flags, size, ret );
         return ret;
@@ -1702,7 +1709,7 @@ void * WINAPI DECLSPEC_HOTPATCH RtlAllocateHeap( HANDLE heap, ULONG flags, SIZE_
     {
         TRACE("(%p,%08x,%08lx): returning NULL\n",
                   heap, flags, size  );
-        if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection );
+        heap_unlock( heapPtr, flags );
         if (flags & HEAP_GENERATE_EXCEPTIONS) RtlRaiseStatus( STATUS_NO_MEMORY );
         return NULL;
     }
@@ -1728,7 +1735,7 @@ void * WINAPI DECLSPEC_HOTPATCH RtlAllocateHeap( HANDLE heap, ULONG flags, SIZE_
     notify_alloc( pInUse + 1, size, flags & HEAP_ZERO_MEMORY );
     initialize_block( pInUse + 1, size, pInUse->unused_bytes, flags );
 
-    if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection );
+    heap_unlock( heapPtr, flags );
 
     TRACE("(%p,%08x,%08lx): returning %p\n", heap, flags, size, pInUse + 1 );
     return pInUse + 1;
@@ -1766,9 +1773,7 @@ BOOLEAN WINAPI DECLSPEC_HOTPATCH RtlFreeHeap( HANDLE heap, ULONG flags, void *pt
         return FALSE;
     }
 
-    flags &= HEAP_NO_SERIALIZE;
-    flags |= heapPtr->flags;
-    if (!(flags & HEAP_NO_SERIALIZE)) RtlEnterCriticalSection( &heapPtr->critSection );
+    heap_lock( heapPtr, flags );
 
     /* Inform valgrind we are trying to free memory, so it can throw up an error message */
     notify_free( ptr );
@@ -1782,12 +1787,12 @@ BOOLEAN WINAPI DECLSPEC_HOTPATCH RtlFreeHeap( HANDLE heap, ULONG flags, void *pt
     else
         HEAP_MakeInUseBlockFree( subheap, pInUse );
 
-    if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection );
+    heap_unlock( heapPtr, flags );
     TRACE("(%p,%08x,%p): returning TRUE\n", heap, flags, ptr );
     return TRUE;
 
 error:
-    if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection );
+    heap_unlock( heapPtr, flags );
     RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_INVALID_PARAMETER );
     TRACE("(%p,%08x,%p): returning FALSE\n", heap, flags, ptr );
     return FALSE;
@@ -1829,7 +1834,7 @@ PVOID WINAPI RtlReAllocateHeap( HANDLE heap, ULONG flags, PVOID ptr, SIZE_T size
     flags &= HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY |
              HEAP_REALLOC_IN_PLACE_ONLY;
     flags |= heapPtr->flags;
-    if (!(flags & HEAP_NO_SERIALIZE)) RtlEnterCriticalSection( &heapPtr->critSection );
+    heap_lock( heapPtr, flags );
 
     rounded_size = ROUND_SIZE(size) + HEAP_TAIL_EXTRA_SIZE(flags);
     if (rounded_size < size) goto oom;  /* overflow */
@@ -1923,19 +1928,19 @@ PVOID WINAPI RtlReAllocateHeap( HANDLE heap, ULONG flags, PVOID ptr, SIZE_T size
 
     ret = pArena + 1;
 done:
-    if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection );
+    heap_unlock( heapPtr, flags );
     TRACE("(%p,%08x,%p,%08lx): returning %p\n", heap, flags, ptr, size, ret );
     return ret;
 
 oom:
-    if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection );
+    heap_unlock( heapPtr, flags );
     if (flags & HEAP_GENERATE_EXCEPTIONS) RtlRaiseStatus( STATUS_NO_MEMORY );
     RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_NO_MEMORY );
     TRACE("(%p,%08x,%p,%08lx): returning NULL\n", heap, flags, ptr, size );
     return NULL;
 
 error:
-    if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection );
+    heap_unlock( heapPtr, flags );
     RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_INVALID_PARAMETER );
     TRACE("(%p,%08x,%p,%08lx): returning NULL\n", heap, flags, ptr, size );
     return NULL;
@@ -1981,7 +1986,7 @@ BOOLEAN WINAPI RtlLockHeap( HANDLE heap )
 {
     HEAP *heapPtr = HEAP_GetPtr( heap );
     if (!heapPtr) return FALSE;
-    RtlEnterCriticalSection( &heapPtr->critSection );
+    RtlEnterCriticalSection( &heapPtr->cs );
     return TRUE;
 }
 
@@ -2002,7 +2007,7 @@ BOOLEAN WINAPI RtlUnlockHeap( HANDLE heap )
 {
     HEAP *heapPtr = HEAP_GetPtr( heap );
     if (!heapPtr) return FALSE;
-    RtlLeaveCriticalSection( &heapPtr->critSection );
+    RtlLeaveCriticalSection( &heapPtr->cs );
     return TRUE;
 }
 
@@ -2036,9 +2041,8 @@ SIZE_T WINAPI RtlSizeHeap( HANDLE heap, ULONG flags, const void *ptr )
         RtlSetLastWin32ErrorAndNtStatusFromNtStatus( STATUS_INVALID_HANDLE );
         return ~(SIZE_T)0;
     }
-    flags &= HEAP_NO_SERIALIZE;
-    flags |= heapPtr->flags;
-    if (!(flags & HEAP_NO_SERIALIZE)) RtlEnterCriticalSection( &heapPtr->critSection );
+
+    heap_lock( heapPtr, flags );
 
     pArena = (const ARENA_INUSE *)ptr - 1;
     if (!validate_block_pointer( heapPtr, &subheap, pArena ))
@@ -2055,7 +2059,8 @@ SIZE_T WINAPI RtlSizeHeap( HANDLE heap, ULONG flags, const void *ptr )
     {
         ret = (pArena->size & ARENA_SIZE_MASK) - pArena->unused_bytes;
     }
-    if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection );
+
+    heap_unlock( heapPtr, flags );
 
     TRACE("(%p,%08x,%p): returning %08lx\n", heap, flags, ptr, ret );
     return ret;
@@ -2102,7 +2107,7 @@ NTSTATUS WINAPI RtlWalkHeap( HANDLE heap, PVOID entry_ptr )
 
     if (!heapPtr || !entry) return STATUS_INVALID_PARAMETER;
 
-    if (!(heapPtr->flags & HEAP_NO_SERIALIZE)) RtlEnterCriticalSection( &heapPtr->critSection );
+    heap_lock( heapPtr, 0 );
 
     /* FIXME: enumerate large blocks too */
 
@@ -2207,7 +2212,7 @@ NTSTATUS WINAPI RtlWalkHeap( HANDLE heap, PVOID entry_ptr )
     if (TRACE_ON(heap)) HEAP_DumpEntry(entry);
 
 HW_end:
-    if (!(heapPtr->flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection );
+    heap_unlock( heapPtr, 0 );
     return ret;
 }
 
@@ -2230,7 +2235,7 @@ ULONG WINAPI RtlGetProcessHeaps( ULONG count, HANDLE *heaps )
     ULONG total = 1;  /* main heap */
     struct list *ptr;
 
-    RtlEnterCriticalSection( &processHeap->critSection );
+    RtlEnterCriticalSection( &processHeap->cs );
     LIST_FOR_EACH( ptr, &processHeap->entry ) total++;
     if (total <= count)
     {
@@ -2238,7 +2243,7 @@ ULONG WINAPI RtlGetProcessHeaps( ULONG count, HANDLE *heaps )
         LIST_FOR_EACH( ptr, &processHeap->entry )
             *heaps++ = LIST_ENTRY( ptr, HEAP, entry );
     }
-    RtlLeaveCriticalSection( &processHeap->critSection );
+    RtlLeaveCriticalSection( &processHeap->cs );
     return total;
 }
 
-- 
2.35.1




More information about the wine-devel mailing list