mirror of
https://github.com/reactos/reactos
synced 2025-10-06 08:22:58 +02:00
Compare commits
6 Commits
hpoussin/m
...
heap-laste
Author | SHA1 | Date | |
---|---|---|---|
|
213cc2a917 | ||
|
4ab4f6a5fb | ||
|
10d23614d3 | ||
|
771f7d3f95 | ||
|
1b7a4b3ebf | ||
|
78dddd125c |
@@ -233,6 +233,7 @@ RtlpClearFreeListsBit(PHEAP Heap,
|
||||
{
|
||||
ULONG Index, Bit;
|
||||
|
||||
ASSERT(IsListEmpty(&Heap->FreeLists[FreeEntry->Size]));
|
||||
ASSERT(FreeEntry->Size < HEAP_FREELISTS);
|
||||
|
||||
/* Calculate offset in the free list bitmap */
|
||||
@@ -387,10 +388,18 @@ RtlpRemoveFreeBlock(PHEAP Heap,
|
||||
{
|
||||
SIZE_T Result, RealSize;
|
||||
|
||||
if (FreeEntry->Size < HEAP_FREELISTS)
|
||||
{
|
||||
ASSERT(Heap->FreeLists[FreeEntry->Size].Flink->Blink == &Heap->FreeLists[FreeEntry->Size]);
|
||||
ASSERT(Heap->FreeLists[FreeEntry->Size].Flink->Flink->Blink == Heap->FreeLists[FreeEntry->Size].Flink);
|
||||
ASSERT(Heap->FreeLists[FreeEntry->Size].Blink->Flink == &Heap->FreeLists[FreeEntry->Size]);
|
||||
ASSERT(Heap->FreeLists[FreeEntry->Size].Blink->Blink->Flink == Heap->FreeLists[FreeEntry->Size].Blink);
|
||||
}
|
||||
/* Remove the free block and update the freelists bitmap */
|
||||
if (RemoveEntryList(&FreeEntry->FreeList) &&
|
||||
(Dedicated || (!Dedicated && FreeEntry->Size < HEAP_FREELISTS)))
|
||||
{
|
||||
ASSERT(IsListEmpty(&Heap->FreeLists[FreeEntry->Size]));
|
||||
RtlpClearFreeListsBit(Heap, FreeEntry);
|
||||
}
|
||||
|
||||
@@ -665,18 +674,27 @@ RtlpFindAndCommitPages(PHEAP Heap,
|
||||
/* Calculate first and last entries */
|
||||
FirstEntry = (PHEAP_ENTRY)Address;
|
||||
|
||||
/* Go through the entries to find the last one */
|
||||
if (PreviousUcr)
|
||||
LastEntry = (PHEAP_ENTRY)((ULONG_PTR)PreviousUcr->Address + PreviousUcr->Size);
|
||||
else
|
||||
LastEntry = &Segment->Entry;
|
||||
//LastEntry = Segment->LastEntryInSegment;
|
||||
|
||||
while (!(LastEntry->Flags & HEAP_ENTRY_LAST_ENTRY))
|
||||
{
|
||||
ASSERT(LastEntry->Size != 0);
|
||||
LastEntry += LastEntry->Size;
|
||||
/* Go through the entries to find the last one */
|
||||
if (PreviousUcr)
|
||||
LastEntry = (PHEAP_ENTRY)((ULONG_PTR)PreviousUcr->Address + PreviousUcr->Size);
|
||||
else
|
||||
LastEntry = &Segment->Entry;
|
||||
|
||||
while (!(LastEntry->Flags & HEAP_ENTRY_LAST_ENTRY))
|
||||
{
|
||||
ASSERT(LastEntry->Size != 0);
|
||||
LastEntry += LastEntry->Size;
|
||||
}
|
||||
}
|
||||
ASSERT((LastEntry + LastEntry->Size) == FirstEntry);
|
||||
if ((((PHEAP_ENTRY)Segment->LastEntryInSegment)->Flags & HEAP_ENTRY_LAST_ENTRY) &&
|
||||
(PHEAP_ENTRY)Segment->LastEntryInSegment + ((PHEAP_ENTRY)Segment->LastEntryInSegment)->Size == FirstEntry)
|
||||
{
|
||||
ASSERT(LastEntry == Segment->LastEntryInSegment);
|
||||
}
|
||||
|
||||
/* Unmark it as a last entry */
|
||||
LastEntry->Flags &= ~HEAP_ENTRY_LAST_ENTRY;
|
||||
@@ -702,10 +720,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 +740,7 @@ RtlpFindAndCommitPages(PHEAP Heap,
|
||||
else
|
||||
{
|
||||
FirstEntry->Flags = HEAP_ENTRY_LAST_ENTRY;
|
||||
Segment->LastEntryInSegment = FirstEntry;
|
||||
}
|
||||
|
||||
/* We're done */
|
||||
@@ -841,6 +862,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 +871,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 +962,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;
|
||||
@@ -983,7 +1015,11 @@ RtlpCoalesceFreeBlocks (PHEAP Heap,
|
||||
PSIZE_T FreeSize,
|
||||
BOOLEAN Remove)
|
||||
{
|
||||
SIZE_T OrigFreeSize = *FreeSize;
|
||||
PHEAP_FREE_ENTRY CurrentEntry, NextEntry;
|
||||
UCHAR SegmentOffset;
|
||||
|
||||
ASSERT(*FreeSize == FreeEntry->Size);
|
||||
|
||||
/* Get the previous entry */
|
||||
CurrentEntry = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)FreeEntry - FreeEntry->PreviousSize);
|
||||
@@ -1020,20 +1056,26 @@ RtlpCoalesceFreeBlocks (PHEAP Heap,
|
||||
/* Also update previous size if needed */
|
||||
if (!(FreeEntry->Flags & HEAP_ENTRY_LAST_ENTRY))
|
||||
{
|
||||
ASSERT(((PHEAP_ENTRY)FreeEntry + *FreeSize)->PreviousSize == OrigFreeSize);
|
||||
((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 */
|
||||
if (!(FreeEntry->Flags & HEAP_ENTRY_LAST_ENTRY))
|
||||
{
|
||||
NextEntry = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)FreeEntry + *FreeSize);
|
||||
ASSERT(*FreeSize == NextEntry->PreviousSize);
|
||||
|
||||
if (!(NextEntry->Flags & HEAP_ENTRY_BUSY) &&
|
||||
NextEntry->Size + *FreeSize <= HEAP_MAX_BLOCK_SIZE)
|
||||
{
|
||||
ASSERT(*FreeSize == NextEntry->PreviousSize);
|
||||
|
||||
/* Remove it if asked for */
|
||||
if (Remove)
|
||||
{
|
||||
@@ -1057,6 +1099,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 +1685,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 +1797,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 +2366,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 +2463,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 +2486,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 +2536,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 +2654,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 +2864,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 +2915,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);
|
||||
|
@@ -203,22 +203,26 @@ typedef struct _HEAP_LIST_LOOKUP
|
||||
PLIST_ENTRY *ListHints;
|
||||
} HEAP_LIST_LOOKUP, *PHEAP_LIST_LOOKUP;
|
||||
|
||||
#define HEAP_SEGMENT_MEMBERS \
|
||||
HEAP_ENTRY Entry; \
|
||||
ULONG SegmentSignature; \
|
||||
ULONG SegmentFlags; \
|
||||
LIST_ENTRY SegmentListEntry; \
|
||||
struct _HEAP *Heap; \
|
||||
PVOID BaseAddress; \
|
||||
ULONG NumberOfPages; \
|
||||
PHEAP_ENTRY FirstEntry; \
|
||||
PHEAP_ENTRY LastValidEntry; \
|
||||
ULONG NumberOfUnCommittedPages; \
|
||||
ULONG NumberOfUnCommittedRanges; \
|
||||
USHORT SegmentAllocatorBackTraceIndex; \
|
||||
USHORT Reserved; \
|
||||
LIST_ENTRY UCRSegmentList; \
|
||||
PVOID LastEntryInSegment //FIXME: non-Vista
|
||||
|
||||
typedef struct _HEAP
|
||||
{
|
||||
HEAP_ENTRY Entry;
|
||||
ULONG SegmentSignature;
|
||||
ULONG SegmentFlags;
|
||||
LIST_ENTRY SegmentListEntry;
|
||||
struct _HEAP *Heap;
|
||||
PVOID BaseAddress;
|
||||
ULONG NumberOfPages;
|
||||
PHEAP_ENTRY FirstEntry;
|
||||
PHEAP_ENTRY LastValidEntry;
|
||||
ULONG NumberOfUnCommittedPages;
|
||||
ULONG NumberOfUnCommittedRanges;
|
||||
USHORT SegmentAllocatorBackTraceIndex;
|
||||
USHORT Reserved;
|
||||
LIST_ENTRY UCRSegmentList;
|
||||
HEAP_SEGMENT_MEMBERS;
|
||||
|
||||
ULONG Flags;
|
||||
ULONG ForceFlags;
|
||||
@@ -271,20 +275,7 @@ typedef struct _HEAP
|
||||
|
||||
typedef struct _HEAP_SEGMENT
|
||||
{
|
||||
HEAP_ENTRY Entry;
|
||||
ULONG SegmentSignature;
|
||||
ULONG SegmentFlags;
|
||||
LIST_ENTRY SegmentListEntry;
|
||||
PHEAP Heap;
|
||||
PVOID BaseAddress;
|
||||
ULONG NumberOfPages;
|
||||
PHEAP_ENTRY FirstEntry;
|
||||
PHEAP_ENTRY LastValidEntry;
|
||||
ULONG NumberOfUnCommittedPages;
|
||||
ULONG NumberOfUnCommittedRanges;
|
||||
USHORT SegmentAllocatorBackTraceIndex;
|
||||
USHORT Reserved;
|
||||
LIST_ENTRY UCRSegmentList;
|
||||
HEAP_SEGMENT_MEMBERS;
|
||||
} HEAP_SEGMENT, *PHEAP_SEGMENT;
|
||||
|
||||
typedef struct _HEAP_UCR_DESCRIPTOR
|
||||
|
Reference in New Issue
Block a user