[RTL] Add and populate LastEntryInSegment. CORE-14588
authorThomas Faber <thomas.faber@reactos.org>
Sun, 2 Feb 2020 11:53:57 +0000 (12:53 +0100)
committerThomas Faber <thomas.faber@reactos.org>
Sun, 14 Jun 2020 07:10:31 +0000 (09:10 +0200)
sdk/lib/rtl/heap.c
sdk/lib/rtl/heap.h

index ad4f6a1..962d5b0 100644 (file)
@@ -702,10 +702,12 @@ RtlpFindAndCommitPages(PHEAP Heap,
                 if(UcrDescriptor->Address == Segment->LastValidEntry)
                 {
                     FirstEntry->Flags = HEAP_ENTRY_LAST_ENTRY;
+                    Segment->LastEntryInSegment = FirstEntry;
                 }
                 else
                 {
                     FirstEntry->Flags = 0;
+                    Segment->LastEntryInSegment = Segment->FirstEntry;
                     /* Update field of next entry */
                     ASSERT((FirstEntry + FirstEntry->Size)->PreviousSize == 0);
                     (FirstEntry + FirstEntry->Size)->PreviousSize = FirstEntry->Size;
@@ -720,6 +722,7 @@ RtlpFindAndCommitPages(PHEAP Heap,
             else
             {
                 FirstEntry->Flags = HEAP_ENTRY_LAST_ENTRY;
+                Segment->LastEntryInSegment = FirstEntry;
             }
 
             /* We're done */
@@ -841,6 +844,7 @@ RtlpDeCommitFreeBlock(PHEAP Heap,
         FreeEntry->Flags = HEAP_ENTRY_LAST_ENTRY;
         FreeEntry->Size = (USHORT)PrecedingSize;
         Heap->TotalFreeSize += PrecedingSize;
+        Segment->LastEntryInSegment = FreeEntry;
 
         /* Insert it into the free list */
         RtlpInsertFreeBlockHelper(Heap, FreeEntry, PrecedingSize, FALSE);
@@ -849,6 +853,13 @@ RtlpDeCommitFreeBlock(PHEAP Heap,
     {
         /* Adjust preceding in use entry */
         PrecedingInUseEntry->Flags |= HEAP_ENTRY_LAST_ENTRY;
+        Segment->LastEntryInSegment = PrecedingInUseEntry;
+    }
+    else if ((ULONG_PTR)Segment->LastEntryInSegment >= DecommitBase &&
+             (ULONG_PTR)Segment->LastEntryInSegment < DecommitBase + DecommitSize)
+    {
+        /* Invalidate last entry */
+        Segment->LastEntryInSegment = Segment->FirstEntry;
     }
 
     /* Now the next one */
@@ -933,6 +944,9 @@ RtlpInitializeHeapSegment(IN OUT PHEAP Heap,
         RtlpInsertFreeBlock(Heap, (PHEAP_FREE_ENTRY) HeapEntry, (SegmentCommit >> HEAP_ENTRY_SHIFT) - Segment->Entry.Size);
     }
 
+    /* Always point to a valid entry */
+    Segment->LastEntryInSegment = Segment->FirstEntry;
+
     /* Initialise the Heap Segment UnCommitted Range information */
     Segment->NumberOfUnCommittedPages = (ULONG)((SegmentReserve - SegmentCommit) >> PAGE_SHIFT);
     Segment->NumberOfUnCommittedRanges = 0;
@@ -984,6 +998,7 @@ RtlpCoalesceFreeBlocks (PHEAP Heap,
                         BOOLEAN Remove)
 {
     PHEAP_FREE_ENTRY CurrentEntry, NextEntry;
+    UCHAR SegmentOffset;
 
     /* Get the previous entry */
     CurrentEntry = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)FreeEntry - FreeEntry->PreviousSize);
@@ -1022,6 +1037,12 @@ RtlpCoalesceFreeBlocks (PHEAP Heap,
         {
             ((PHEAP_ENTRY)FreeEntry + *FreeSize)->PreviousSize = (USHORT)(*FreeSize);
         }
+        else
+        {
+            SegmentOffset = FreeEntry->SegmentOffset;
+            ASSERT(SegmentOffset < HEAP_SEGMENTS);
+            Heap->Segments[SegmentOffset]->LastEntryInSegment = FreeEntry;
+        }
     }
 
     /* Check the next block if it exists */
@@ -1057,6 +1078,12 @@ RtlpCoalesceFreeBlocks (PHEAP Heap,
             {
                 ((PHEAP_ENTRY)FreeEntry + *FreeSize)->PreviousSize = (USHORT)(*FreeSize);
             }
+            else
+            {
+                SegmentOffset = FreeEntry->SegmentOffset;
+                ASSERT(SegmentOffset < HEAP_SEGMENTS);
+                Heap->Segments[SegmentOffset]->LastEntryInSegment = FreeEntry;
+            }
         }
     }
     return FreeEntry;
@@ -1637,6 +1664,7 @@ RtlpSplitEntry(PHEAP Heap,
     UCHAR FreeFlags, EntryFlags = HEAP_ENTRY_BUSY;
     PHEAP_ENTRY InUseEntry;
     SIZE_T FreeSize;
+    UCHAR SegmentOffset;
 
     /* Add extra flags in case of settable user value feature is requested,
        or there is a tag (small or normal) or there is a request to
@@ -1748,6 +1776,12 @@ RtlpSplitEntry(PHEAP Heap,
 
             /* Reset flags of the free entry */
             FreeFlags = 0;
+            if (SplitBlock->Flags & HEAP_ENTRY_LAST_ENTRY)
+            {
+                SegmentOffset = SplitBlock->SegmentOffset;
+                ASSERT(SegmentOffset < HEAP_SEGMENTS);
+                Heap->Segments[SegmentOffset]->LastEntryInSegment = SplitBlock;
+            }
         }
     }
 
@@ -2311,6 +2345,7 @@ RtlpGrowBlockInPlace (IN PHEAP Heap,
     PHEAP_FREE_ENTRY FreeEntry, UnusedEntry, FollowingEntry;
     SIZE_T FreeSize, PrevSize, TailPart, AddedSize = 0;
     PHEAP_ENTRY_EXTRA OldExtra, NewExtra;
+    UCHAR SegmentOffset;
 
     /* We can't grow beyond specified threshold */
     if (Index > Heap->VirtualMemoryThreshold)
@@ -2407,9 +2442,17 @@ RtlpGrowBlockInPlace (IN PHEAP Heap,
         InUseEntry->Flags |= RememberFlags & HEAP_ENTRY_LAST_ENTRY;
 
         /* Either update previous size of the next entry or mark it as a last
-           entry in the segment*/
+           entry in the segment */
         if (!(RememberFlags & HEAP_ENTRY_LAST_ENTRY))
+        {
             (InUseEntry + InUseEntry->Size)->PreviousSize = InUseEntry->Size;
+        }
+        else
+        {
+            SegmentOffset = InUseEntry->SegmentOffset;
+            ASSERT(SegmentOffset < HEAP_SEGMENTS);
+            Heap->Segments[SegmentOffset]->LastEntryInSegment = InUseEntry;
+        }
     }
     else
     {
@@ -2422,6 +2465,10 @@ RtlpGrowBlockInPlace (IN PHEAP Heap,
         /* Update the following block or set the last entry in the segment */
         if (RememberFlags & HEAP_ENTRY_LAST_ENTRY)
         {
+            SegmentOffset = UnusedEntry->SegmentOffset;
+            ASSERT(SegmentOffset < HEAP_SEGMENTS);
+            Heap->Segments[SegmentOffset]->LastEntryInSegment = UnusedEntry;
+
             /* Set flags and size */
             UnusedEntry->Flags = RememberFlags;
             UnusedEntry->Size = (USHORT)FreeSize;
@@ -2468,7 +2515,15 @@ RtlpGrowBlockInPlace (IN PHEAP Heap,
                     UnusedEntry->Size = (USHORT)FreeSize;
 
                     if (!(RememberFlags & HEAP_ENTRY_LAST_ENTRY))
+                    {
                         ((PHEAP_ENTRY)UnusedEntry + FreeSize)->PreviousSize = (USHORT)FreeSize;
+                    }
+                    else
+                    {
+                        SegmentOffset = UnusedEntry->SegmentOffset;
+                        ASSERT(SegmentOffset < HEAP_SEGMENTS);
+                        Heap->Segments[SegmentOffset]->LastEntryInSegment = UnusedEntry;
+                    }
 
                     /* Insert it back and update total size */
                     RtlpInsertFreeBlockHelper(Heap, UnusedEntry, FreeSize, FALSE);
@@ -2578,6 +2633,7 @@ RtlReAllocateHeap(HANDLE HeapPtr,
     SIZE_T RemainderBytes, ExtraSize;
     PHEAP_VIRTUAL_ALLOC_ENTRY VirtualAllocBlock;
     EXCEPTION_RECORD ExceptionRecord;
+    UCHAR SegmentOffset;
 
     /* Return success in case of a null pointer */
     if (!Ptr)
@@ -2787,6 +2843,10 @@ RtlReAllocateHeap(HANDLE HeapPtr,
                 /* Is that the last entry */
                 if (FreeFlags & HEAP_ENTRY_LAST_ENTRY)
                 {
+                    SegmentOffset = SplitBlock->SegmentOffset;
+                    ASSERT(SegmentOffset < HEAP_SEGMENTS);
+                    Heap->Segments[SegmentOffset]->LastEntryInSegment = SplitBlock;
+
                     /* Set its size and insert it to the list */
                     SplitBlock->Size = (USHORT)FreeSize;
                     RtlpInsertFreeBlockHelper(Heap, SplitBlock, FreeSize, FALSE);
@@ -2834,6 +2894,12 @@ RtlReAllocateHeap(HANDLE HeapPtr,
                                 /* Update previous size of the next entry */
                                 ((PHEAP_FREE_ENTRY)((PHEAP_ENTRY)SplitBlock + FreeSize))->PreviousSize = (USHORT)FreeSize;
                             }
+                            else
+                            {
+                                SegmentOffset = SplitBlock->SegmentOffset;
+                                ASSERT(SegmentOffset < HEAP_SEGMENTS);
+                                Heap->Segments[SegmentOffset]->LastEntryInSegment = SplitBlock;
+                            }
 
                             /* Insert the new one back and update total size */
                             RtlpInsertFreeBlockHelper(Heap, SplitBlock, FreeSize, FALSE);
index 8fb9bc7..aef68e5 100644 (file)
@@ -217,7 +217,8 @@ typedef struct _HEAP_LIST_LOOKUP
     ULONG NumberOfUnCommittedRanges;        \
     USHORT SegmentAllocatorBackTraceIndex;  \
     USHORT Reserved;                        \
-    LIST_ENTRY UCRSegmentList
+    LIST_ENTRY UCRSegmentList;              \
+    PVOID LastEntryInSegment //FIXME: non-Vista
 
 typedef struct _HEAP
 {