https://git.reactos.org/?p=reactos.git;a=commitdiff;h=c4f736e8f4e05c214d74c0...
commit c4f736e8f4e05c214d74c0751189f38305583be0 Author: Thomas Faber thomas.faber@reactos.org AuthorDate: Sun Feb 2 12:53:57 2020 +0100 Commit: Thomas Faber thomas.faber@reactos.org CommitDate: Sun Jun 14 09:10:31 2020 +0200
[RTL] Add and populate LastEntryInSegment. CORE-14588 --- sdk/lib/rtl/heap.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++- sdk/lib/rtl/heap.h | 3 ++- 2 files changed, 69 insertions(+), 2 deletions(-)
diff --git a/sdk/lib/rtl/heap.c b/sdk/lib/rtl/heap.c index ad4f6a1513d..962d5b079b6 100644 --- a/sdk/lib/rtl/heap.c +++ b/sdk/lib/rtl/heap.c @@ -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); diff --git a/sdk/lib/rtl/heap.h b/sdk/lib/rtl/heap.h index 8fb9bc7ae0d..aef68e5edcd 100644 --- a/sdk/lib/rtl/heap.h +++ b/sdk/lib/rtl/heap.h @@ -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 {