https://git.reactos.org/?p=reactos.git;a=commitdiff;h=c4f736e8f4e05c214d74c…
commit c4f736e8f4e05c214d74c0751189f38305583be0
Author: Thomas Faber <thomas.faber(a)reactos.org>
AuthorDate: Sun Feb 2 12:53:57 2020 +0100
Commit: Thomas Faber <thomas.faber(a)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
{