mirror of
https://github.com/reactos/reactos.git
synced 2025-07-23 11:33:43 +00:00
[HEAP]
- Add ability to dynamically allocate UCR descriptors when preallocated amount is exhausted. - Fix a few bugs in RtlpFindAndCommitPages and in deactivated RtlpDecommitFreeBlock. - Enable free blocks decommitting. - New heap manager would now be ready to replace the old one. svn path=/trunk/; revision=49147
This commit is contained in:
parent
6e2cb102ff
commit
57f4a96cc1
2 changed files with 131 additions and 47 deletions
|
@ -178,6 +178,7 @@ typedef struct _HEAP
|
|||
USHORT SegmentAllocatorBackTraceIndex;
|
||||
USHORT Reserved;
|
||||
LIST_ENTRY UCRSegmentList;
|
||||
|
||||
ULONG Flags;
|
||||
ULONG ForceFlags;
|
||||
ULONG CompatibilityFlags;
|
||||
|
@ -200,6 +201,7 @@ typedef struct _HEAP
|
|||
USHORT MaximumTagIndex;
|
||||
PHEAP_TAG_ENTRY TagEntries;
|
||||
LIST_ENTRY UCRList;
|
||||
LIST_ENTRY UCRSegments; // FIXME: non-Vista
|
||||
ULONG AlignRound;
|
||||
ULONG AlignMask;
|
||||
LIST_ENTRY VirtualAllocdBlocks;
|
||||
|
@ -252,6 +254,13 @@ typedef struct _HEAP_UCR_DESCRIPTOR
|
|||
ULONG Size;
|
||||
} HEAP_UCR_DESCRIPTOR, *PHEAP_UCR_DESCRIPTOR;
|
||||
|
||||
typedef struct _HEAP_UCR_SEGMENT
|
||||
{
|
||||
LIST_ENTRY ListEntry;
|
||||
SIZE_T ReservedSize;
|
||||
SIZE_T CommittedSize;
|
||||
} HEAP_UCR_SEGMENT, *PHEAP_UCR_SEGMENT;
|
||||
|
||||
typedef struct _HEAP_ENTRY_EXTRA
|
||||
{
|
||||
union
|
||||
|
|
|
@ -104,7 +104,7 @@ RtlpInitializeHeap(PHEAP Heap,
|
|||
|
||||
/* Prepare a list of UCRs */
|
||||
InitializeListHead(&Heap->UCRList);
|
||||
InitializeListHead(&Heap->UCRSegmentList);
|
||||
InitializeListHead(&Heap->UCRSegments);
|
||||
UcrDescriptor = NextHeapBase;
|
||||
|
||||
for (i=0; i<NumUCRs; i++, UcrDescriptor++)
|
||||
|
@ -408,14 +408,86 @@ RtlpCreateUnCommittedRange(PHEAP_SEGMENT Segment)
|
|||
{
|
||||
PLIST_ENTRY Entry;
|
||||
PHEAP_UCR_DESCRIPTOR UcrDescriptor;
|
||||
PHEAP_UCR_SEGMENT UcrSegment;
|
||||
PHEAP Heap = Segment->Heap;
|
||||
SIZE_T ReserveSize = 16 * PAGE_SIZE;
|
||||
SIZE_T CommitSize = 1 * PAGE_SIZE;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("RtlpCreateUnCommittedRange(%p)\n", Segment);
|
||||
|
||||
/* Check if we have unused UCRs */
|
||||
if (IsListEmpty(&Heap->UCRList))
|
||||
{
|
||||
ASSERT(FALSE);
|
||||
/* Get a pointer to the first UCR segment */
|
||||
UcrSegment = CONTAINING_RECORD(&Heap->UCRSegments.Flink, HEAP_UCR_SEGMENT, ListEntry);
|
||||
|
||||
/* Check the list of UCR segments */
|
||||
if (IsListEmpty(&Heap->UCRSegments) ||
|
||||
UcrSegment->ReservedSize == UcrSegment->CommittedSize)
|
||||
{
|
||||
/* We need to create a new one. Reserve 16 pages for it */
|
||||
UcrSegment = NULL;
|
||||
Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
|
||||
(PVOID *)&UcrSegment,
|
||||
0,
|
||||
&ReserveSize,
|
||||
MEM_RESERVE,
|
||||
PAGE_READWRITE);
|
||||
|
||||
if (!NT_SUCCESS(Status)) return NULL;
|
||||
|
||||
/* Commit one page */
|
||||
Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
|
||||
(PVOID *)&UcrSegment,
|
||||
0,
|
||||
&CommitSize,
|
||||
MEM_COMMIT,
|
||||
PAGE_READWRITE);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Release reserved memory */
|
||||
ZwFreeVirtualMemory(NtCurrentProcess(),
|
||||
(PVOID *)&UcrDescriptor,
|
||||
&ReserveSize,
|
||||
MEM_RELEASE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Set it's data */
|
||||
UcrSegment->ReservedSize = ReserveSize;
|
||||
UcrSegment->CommittedSize = CommitSize;
|
||||
|
||||
/* Add it to the head of the list */
|
||||
InsertHeadList(&Heap->UCRSegments, &UcrSegment->ListEntry);
|
||||
|
||||
/* Get a pointer to the first available UCR descriptor */
|
||||
UcrDescriptor = (PHEAP_UCR_DESCRIPTOR)(UcrSegment + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It's possible to use existing UCR segment. Commit one more page */
|
||||
UcrDescriptor = (PHEAP_UCR_DESCRIPTOR)((PCHAR)UcrSegment + UcrSegment->CommittedSize);
|
||||
Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
|
||||
(PVOID *)&UcrDescriptor,
|
||||
0,
|
||||
&CommitSize,
|
||||
MEM_COMMIT,
|
||||
PAGE_READWRITE);
|
||||
|
||||
if (!NT_SUCCESS(Status)) return NULL;
|
||||
|
||||
/* Update sizes */
|
||||
UcrSegment->CommittedSize += CommitSize;
|
||||
}
|
||||
|
||||
/* There is a whole bunch of new UCR descriptors. Put them into the unused list */
|
||||
while ((PCHAR)UcrDescriptor < ((PCHAR)UcrSegment + UcrSegment->CommittedSize))
|
||||
{
|
||||
InsertTailList(&Heap->UCRList, &UcrDescriptor->ListEntry);
|
||||
UcrDescriptor++;
|
||||
}
|
||||
}
|
||||
|
||||
/* There are unused UCRs, just get the first one */
|
||||
|
@ -506,9 +578,10 @@ PHEAP_FREE_ENTRY NTAPI
|
|||
RtlpFindAndCommitPages(PHEAP Heap,
|
||||
PHEAP_SEGMENT Segment,
|
||||
PSIZE_T Size,
|
||||
PVOID Address)
|
||||
PVOID AddressRequested)
|
||||
{
|
||||
PLIST_ENTRY Current;
|
||||
ULONG_PTR Address = 0;
|
||||
PHEAP_UCR_DESCRIPTOR UcrDescriptor, PreviousUcr = NULL;
|
||||
PHEAP_ENTRY FirstEntry, LastEntry, PreviousLastEntry;
|
||||
NTSTATUS Status;
|
||||
|
@ -523,20 +596,20 @@ RtlpFindAndCommitPages(PHEAP Heap,
|
|||
|
||||
/* Check if we can use that one right away */
|
||||
if (UcrDescriptor->Size >= *Size &&
|
||||
(UcrDescriptor->Address == Address || !Address))
|
||||
(UcrDescriptor->Address == AddressRequested || !AddressRequested))
|
||||
{
|
||||
/* Get the address */
|
||||
Address = UcrDescriptor->Address;
|
||||
Address = (ULONG_PTR)UcrDescriptor->Address;
|
||||
|
||||
/* Commit it */
|
||||
if (Heap->CommitRoutine)
|
||||
{
|
||||
Status = Heap->CommitRoutine(Heap, &Address, Size);
|
||||
Status = Heap->CommitRoutine(Heap, (PVOID *)&Address, Size);
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
|
||||
&Address,
|
||||
(PVOID *)&Address,
|
||||
0,
|
||||
Size,
|
||||
MEM_COMMIT,
|
||||
|
@ -597,7 +670,7 @@ RtlpFindAndCommitPages(PHEAP Heap,
|
|||
LastEntry->Flags &= ~HEAP_ENTRY_LAST_ENTRY;
|
||||
|
||||
/* Update UCR descriptor */
|
||||
UcrDescriptor->Address = (PUCHAR)UcrDescriptor->Address + *Size;
|
||||
UcrDescriptor->Address = (PVOID)((ULONG_PTR)UcrDescriptor->Address + *Size);
|
||||
UcrDescriptor->Size -= *Size;
|
||||
|
||||
DPRINT("Updating UcrDescriptor %p, new Address %p, size %d\n",
|
||||
|
@ -644,6 +717,7 @@ RtlpFindAndCommitPages(PHEAP Heap,
|
|||
}
|
||||
|
||||
/* Advance to the next descriptor */
|
||||
PreviousUcr = UcrDescriptor;
|
||||
Current = Current->Flink;
|
||||
}
|
||||
|
||||
|
@ -655,15 +729,16 @@ RtlpDeCommitFreeBlock(PHEAP Heap,
|
|||
PHEAP_FREE_ENTRY FreeEntry,
|
||||
SIZE_T Size)
|
||||
{
|
||||
#if 0
|
||||
PHEAP_SEGMENT Segment;
|
||||
PHEAP_ENTRY PrecedingInUseEntry = NULL, NextInUseEntry = NULL;
|
||||
PHEAP_FREE_ENTRY NextFreeEntry;
|
||||
PHEAP_UCR_DESCRIPTOR UcrDescriptor;
|
||||
ULONG PrecedingSize, NextSize, DecommitSize;
|
||||
ULONG DecommitBase;
|
||||
ULONG_PTR DecommitBase;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("Decommitting %p %p %x\n", Heap, FreeEntry, Size);
|
||||
|
||||
/* We can't decommit if there is a commit routine! */
|
||||
if (Heap->CommitRoutine)
|
||||
{
|
||||
|
@ -692,7 +767,7 @@ RtlpDeCommitFreeBlock(PHEAP Heap,
|
|||
}
|
||||
|
||||
/* Get the next entry */
|
||||
NextFreeEntry = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)FreeEntry + (Size >> HEAP_ENTRY_SHIFT));
|
||||
NextFreeEntry = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)FreeEntry + Size);
|
||||
DecommitSize = ROUND_DOWN(NextFreeEntry, PAGE_SIZE);
|
||||
NextSize = (PHEAP_ENTRY)NextFreeEntry - (PHEAP_ENTRY)DecommitSize;
|
||||
|
||||
|
@ -708,14 +783,17 @@ RtlpDeCommitFreeBlock(PHEAP Heap,
|
|||
NextInUseEntry = (PHEAP_ENTRY)NextFreeEntry;
|
||||
}
|
||||
|
||||
NextFreeEntry = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)NextFreeEntry - NextSize);
|
||||
NextFreeEntry = (PHEAP_FREE_ENTRY)((PHEAP_ENTRY)NextFreeEntry - NextSize);
|
||||
|
||||
/* Calculate real decommit size */
|
||||
if (DecommitSize > DecommitBase)
|
||||
{
|
||||
DecommitSize -= DecommitBase;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to decommit */
|
||||
RtlpInsertFreeBlock(Heap, FreeEntry, PrecedingSize);
|
||||
RtlpInsertFreeBlock(Heap, FreeEntry, Size);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -739,7 +817,7 @@ RtlpDeCommitFreeBlock(PHEAP Heap,
|
|||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
RtlpInsertFreeBlock(Heap, FreeEntry, PrecedingSize);
|
||||
RtlpInsertFreeBlock(Heap, FreeEntry, Size);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -753,18 +831,22 @@ RtlpDeCommitFreeBlock(PHEAP Heap,
|
|||
FreeEntry->Flags = HEAP_ENTRY_LAST_ENTRY;
|
||||
FreeEntry->Size = PrecedingSize;
|
||||
Heap->TotalFreeSize += PrecedingSize;
|
||||
|
||||
/* Set last entry in the segment to this entry */
|
||||
Segment->LastEntryInSegment = (PHEAP_ENTRY)FreeEntry;
|
||||
RtlpInsertFreeBlockHelper(Heap, FreeEntry, PrecedingSize);
|
||||
|
||||
/* Insert it into the free list */
|
||||
RtlpInsertFreeBlockHelper(Heap, FreeEntry, PrecedingSize, FALSE);
|
||||
}
|
||||
else if (NextInUseEntry)
|
||||
else if (PrecedingInUseEntry)
|
||||
{
|
||||
/* Adjust preceding in use entry */
|
||||
PrecedingInUseEntry->Flags |= HEAP_ENTRY_LAST_ENTRY;
|
||||
Segment->LastEntryInSegment = PrecedingInUseEntry;
|
||||
}
|
||||
else if ((Segment->LastEntryInSegment >= (PHEAP_ENTRY)DecommitBase))
|
||||
} else if ((ULONG_PTR)Segment->LastEntryInSegment >= DecommitBase &&
|
||||
((PCHAR)Segment->LastEntryInSegment < ((PCHAR)DecommitBase + DecommitSize)))
|
||||
{
|
||||
/* Adjust last entry in the segment */
|
||||
/* Update this segment's last entry */
|
||||
Segment->LastEntryInSegment = Segment->FirstEntry;
|
||||
}
|
||||
|
||||
|
@ -779,16 +861,13 @@ RtlpDeCommitFreeBlock(PHEAP Heap,
|
|||
|
||||
((PHEAP_FREE_ENTRY)((PHEAP_ENTRY)NextFreeEntry + NextSize))->PreviousSize = NextSize;
|
||||
|
||||
Heap->TotalFreeSize += PrecedingSize;
|
||||
RtlpInsertFreeBlockHelper(Heap, NextFreeEntry, NextSize);
|
||||
Heap->TotalFreeSize += NextSize;
|
||||
RtlpInsertFreeBlockHelper(Heap, NextFreeEntry, NextSize, FALSE);
|
||||
}
|
||||
else if (NextInUseEntry)
|
||||
{
|
||||
NextInUseEntry->PreviousSize = 0;
|
||||
}
|
||||
#else
|
||||
RtlpInsertFreeBlock(Heap, FreeEntry, Size);
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOLEAN NTAPI
|
||||
|
@ -1047,7 +1126,7 @@ RtlpCoalesceFreeBlocks (PHEAP Heap,
|
|||
|
||||
/* Advance FreeEntry and update sizes */
|
||||
FreeEntry = CurrentEntry;
|
||||
*FreeSize += CurrentEntry->Size;
|
||||
*FreeSize = *FreeSize + CurrentEntry->Size;
|
||||
Heap->TotalFreeSize -= CurrentEntry->Size;
|
||||
FreeEntry->Size = *FreeSize;
|
||||
|
||||
|
@ -1086,7 +1165,7 @@ RtlpCoalesceFreeBlocks (PHEAP Heap,
|
|||
RtlpRemoveFreeBlock(Heap, NextEntry, FALSE, FALSE);
|
||||
|
||||
/* Update sizes */
|
||||
*FreeSize += NextEntry->Size;
|
||||
*FreeSize = *FreeSize + NextEntry->Size;
|
||||
Heap->TotalFreeSize -= NextEntry->Size;
|
||||
FreeEntry->Size = *FreeSize;
|
||||
|
||||
|
@ -1648,7 +1727,7 @@ RtlDestroyHeap(HANDLE HeapPtr) /* [in] Handle of heap */
|
|||
{
|
||||
PHEAP Heap = (PHEAP)HeapPtr;
|
||||
PLIST_ENTRY Current;
|
||||
PHEAP_UCR_DESCRIPTOR UcrDescriptor;
|
||||
PHEAP_UCR_SEGMENT UcrSegment;
|
||||
PHEAP_VIRTUAL_ALLOC_ENTRY VirtualEntry;
|
||||
PVOID BaseAddress;
|
||||
SIZE_T Size;
|
||||
|
@ -1695,27 +1774,23 @@ RtlDestroyHeap(HANDLE HeapPtr) /* [in] Handle of heap */
|
|||
Heap->LockVariable = NULL;
|
||||
}
|
||||
|
||||
/* Go through heap's global uncommitted ranges list and free them */
|
||||
DPRINT1("HEAP: Freeing segment's UCRs is not yet implemented!\n");
|
||||
Current = Heap->UCRSegmentList.Flink;
|
||||
while(Current != &Heap->UCRSegmentList)
|
||||
/* Free UCR segments if any were created */
|
||||
Current = Heap->UCRSegments.Flink;
|
||||
while(Current != &Heap->UCRSegments)
|
||||
{
|
||||
UcrDescriptor = CONTAINING_RECORD(Current, HEAP_UCR_DESCRIPTOR, ListEntry);
|
||||
|
||||
if (UcrDescriptor)
|
||||
{
|
||||
BaseAddress = UcrDescriptor->Address;
|
||||
Size = 0;
|
||||
|
||||
/* Release that memory */
|
||||
ZwFreeVirtualMemory(NtCurrentProcess(),
|
||||
&BaseAddress,
|
||||
&Size,
|
||||
MEM_RELEASE);
|
||||
}
|
||||
UcrSegment = CONTAINING_RECORD(Current, HEAP_UCR_SEGMENT, ListEntry);
|
||||
|
||||
/* Advance to the next descriptor */
|
||||
Current = Current->Flink;
|
||||
|
||||
BaseAddress = (PVOID)UcrSegment;
|
||||
Size = 0;
|
||||
|
||||
/* Release that memory */
|
||||
ZwFreeVirtualMemory(NtCurrentProcess(),
|
||||
&BaseAddress,
|
||||
&Size,
|
||||
MEM_RELEASE);
|
||||
}
|
||||
|
||||
/* Go through segments and destroy them */
|
||||
|
@ -2043,7 +2118,7 @@ RtlAllocateHeap(IN PVOID HeapPtr,
|
|||
HEAP_CREATE_ENABLE_TRACING |
|
||||
HEAP_CREATE_ALIGN_16))
|
||||
{
|
||||
DPRINT1("HEAP: RtlAllocateHeap is called with unsupported flags %x, ignoring\n", Flags);
|
||||
DPRINT("HEAP: RtlAllocateHeap is called with unsupported flags %x, ignoring\n", Flags);
|
||||
}
|
||||
|
||||
//DPRINT("RtlAllocateHeap(%p %x %x)\n", Heap, Flags, Size);
|
||||
|
@ -3000,7 +3075,7 @@ RtlReAllocateHeap(HANDLE HeapPtr,
|
|||
if (Size > OldSize &&
|
||||
(Flags & HEAP_ZERO_MEMORY))
|
||||
{
|
||||
RtlZeroMemory((PCHAR)NewBaseAddress + OldSize, Size - OldSize );
|
||||
RtlZeroMemory((PCHAR)NewBaseAddress + OldSize, Size - OldSize);
|
||||
}
|
||||
|
||||
/* Free the old block */
|
||||
|
@ -3701,7 +3776,7 @@ RtlEnumProcessHeaps(PHEAP_ENUMERATION_ROUTINE HeapEnumerationRoutine,
|
|||
*/
|
||||
ULONG NTAPI
|
||||
RtlGetProcessHeaps(ULONG count,
|
||||
HANDLE *heaps )
|
||||
HANDLE *heaps)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return 0;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue