mirror of
https://github.com/reactos/reactos.git
synced 2025-06-10 20:34:59 +00:00
[FREELDR]
Revert to using the old heap code, as it broke 2nd stage on some systems svn path=/trunk/; revision=55551
This commit is contained in:
parent
bf9a2b9964
commit
b3c15e9acd
6 changed files with 2204 additions and 446 deletions
|
@ -155,6 +155,7 @@ endif()
|
||||||
list(APPEND FREELDR_BASE_SOURCE
|
list(APPEND FREELDR_BASE_SOURCE
|
||||||
bootmgr.c # This file is compiled with custom definitions
|
bootmgr.c # This file is compiled with custom definitions
|
||||||
freeldr.c
|
freeldr.c
|
||||||
|
rtl/bget.c
|
||||||
rtl/libsupp.c)
|
rtl/libsupp.c)
|
||||||
|
|
||||||
if (NOT MSVC)
|
if (NOT MSVC)
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
<file>binhive.c</file>
|
<file>binhive.c</file>
|
||||||
</directory>
|
</directory>
|
||||||
<directory name="rtl">
|
<directory name="rtl">
|
||||||
|
<file>bget.c</file>
|
||||||
<file>libsupp.c</file>
|
<file>libsupp.c</file>
|
||||||
</directory>
|
</directory>
|
||||||
<directory name="ui">
|
<directory name="ui">
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* FreeLoader
|
* FreeLoader
|
||||||
* Copyright (C) 2011 Timo Kreuzer (timo.kreuzer@reactos.org)
|
* Copyright (C) 2006-2008 Aleksey Bragin <aleksey@reactos.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -20,447 +20,83 @@
|
||||||
#include <freeldr.h>
|
#include <freeldr.h>
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
DBG_DEFAULT_CHANNEL(HEAP);
|
//#define MM_DBG 1 // needs #define BufStats 1 in bget.c
|
||||||
|
|
||||||
#define DEFAULT_HEAP_SIZE (1024 * 1024)
|
ULONG MmMaximumHeapAlloc;
|
||||||
#define TEMP_HEAP_SIZE (1024 * 1024)
|
|
||||||
|
|
||||||
PVOID FrLdrDefaultHeap;
|
DBG_DEFAULT_CHANNEL(MEMORY);
|
||||||
PVOID FrLdrTempHeap;
|
|
||||||
|
|
||||||
typedef struct _BLOCK_DATA
|
VOID MmInitializeHeap(PVOID PageLookupTable)
|
||||||
{
|
{
|
||||||
ULONG_PTR Flink;
|
ULONG PagesNeeded = 0;
|
||||||
ULONG_PTR Blink;
|
ULONG HeapStart = 0;
|
||||||
} BLOCK_DATA, *PBLOCK_DATA;
|
|
||||||
|
|
||||||
typedef struct _HEAP_BLOCK
|
// Find contigious memory block for HEAP:STACK
|
||||||
{
|
PagesNeeded = HEAP_PAGES + STACK_PAGES;
|
||||||
USHORT Size;
|
HeapStart = MmFindAvailablePages(PageLookupTable, TotalPagesInLookupTable, PagesNeeded, FALSE);
|
||||||
USHORT PreviousSize;
|
|
||||||
ULONG Tag;
|
|
||||||
BLOCK_DATA Data[];
|
|
||||||
} HEAP_BLOCK, *PHEAP_BLOCK;
|
|
||||||
|
|
||||||
typedef struct _HEAP
|
if (HeapStart == 0)
|
||||||
|
{
|
||||||
|
UiMessageBox("Critical error: Can't allocate heap!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize BGET
|
||||||
|
bpool((PVOID)(HeapStart << MM_PAGE_SHIFT), PagesNeeded << MM_PAGE_SHIFT);
|
||||||
|
|
||||||
|
// Mark those pages as used
|
||||||
|
MmMarkPagesInLookupTable(PageLookupTableAddress, HeapStart, PagesNeeded, LoaderOsloaderHeap);
|
||||||
|
|
||||||
|
TRACE("Heap initialized, base 0x%08x, pages %d\n", (HeapStart << MM_PAGE_SHIFT), PagesNeeded);
|
||||||
|
}
|
||||||
|
|
||||||
|
PVOID MmHeapAlloc(ULONG MemorySize)
|
||||||
{
|
{
|
||||||
SIZE_T MaximumSize;
|
PVOID Result;
|
||||||
SIZE_T CurrentAllocBytes;
|
|
||||||
SIZE_T MaxAllocBytes;
|
if (MemorySize > MM_PAGE_SIZE)
|
||||||
ULONG NumAllocs;
|
{
|
||||||
ULONG NumFrees;
|
WARN("Consider using other functions to allocate %d bytes of memory!\n", MemorySize);
|
||||||
SIZE_T LargestAllocation;
|
}
|
||||||
ULONGLONG AllocationTime;
|
|
||||||
ULONGLONG FreeTime;
|
// Get the buffer from BGET pool
|
||||||
ULONG_PTR TerminatingBlock;
|
Result = bget(MemorySize);
|
||||||
HEAP_BLOCK Blocks;
|
|
||||||
} HEAP, *PHEAP;
|
if (Result == NULL)
|
||||||
|
{
|
||||||
|
ERR("Heap allocation for %d bytes failed\n", MemorySize);
|
||||||
|
}
|
||||||
|
#ifdef MM_DBG
|
||||||
|
{
|
||||||
|
LONG CurAlloc, TotalFree, MaxFree, NumberOfGets, NumberOfRels;
|
||||||
|
|
||||||
|
// Gather some stats
|
||||||
|
bstats(&CurAlloc, &TotalFree, &MaxFree, &NumberOfGets, &NumberOfRels);
|
||||||
|
if (CurAlloc > MmMaximumHeapAlloc) MmMaximumHeapAlloc = CurAlloc;
|
||||||
|
|
||||||
|
TRACE("Current alloc %d, free %d, max alloc %lx, allocs %d, frees %d\n",
|
||||||
|
CurAlloc, TotalFree, MmMaximumHeapAlloc, NumberOfGets, NumberOfRels);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID MmHeapFree(PVOID MemoryPointer)
|
||||||
|
{
|
||||||
|
// Release the buffer to the pool
|
||||||
|
brel(MemoryPointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
PVOID
|
PVOID
|
||||||
HeapCreate(
|
NTAPI
|
||||||
SIZE_T MaximumSize,
|
ExAllocatePool(
|
||||||
TYPE_OF_MEMORY MemoryType)
|
IN POOL_TYPE PoolType,
|
||||||
|
IN SIZE_T NumberOfBytes)
|
||||||
{
|
{
|
||||||
PHEAP Heap;
|
return MmHeapAlloc(NumberOfBytes);
|
||||||
PHEAP_BLOCK Block;
|
|
||||||
SIZE_T Remaining;
|
|
||||||
USHORT PreviousSize;
|
|
||||||
TRACE("HeapCreate(MemoryType=%ld)\n", MemoryType);
|
|
||||||
|
|
||||||
/* Allocate some memory for the heap */
|
|
||||||
MaximumSize = ALIGN_UP_BY(MaximumSize, MM_PAGE_SIZE);
|
|
||||||
Heap = MmAllocateMemoryWithType(MaximumSize, MemoryType);
|
|
||||||
if (!Heap)
|
|
||||||
{
|
|
||||||
ERR("HEAP: Failed to allocate heap of size 0x%lx, Type\n",
|
|
||||||
MaximumSize, MemoryType);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize the heap header */
|
|
||||||
Heap->MaximumSize = MaximumSize;
|
|
||||||
Heap->CurrentAllocBytes = 0;
|
|
||||||
Heap->MaxAllocBytes = 0;
|
|
||||||
Heap->NumAllocs = 0;
|
|
||||||
Heap->NumFrees = 0;
|
|
||||||
Heap->LargestAllocation = 0;
|
|
||||||
|
|
||||||
/* Calculate what's left to process */
|
|
||||||
Remaining = (MaximumSize - sizeof(HEAP)) / sizeof(HEAP_BLOCK);
|
|
||||||
TRACE("Remaining = %ld\n", Remaining);
|
|
||||||
|
|
||||||
/* Substract 2 for the terminating entry (header + free entry) */
|
|
||||||
Remaining -= 2;
|
|
||||||
|
|
||||||
Block = &Heap->Blocks;
|
|
||||||
PreviousSize = 0;
|
|
||||||
|
|
||||||
/* Create free blocks */
|
|
||||||
while (Remaining > 1)
|
|
||||||
{
|
|
||||||
/* Initialize this free block */
|
|
||||||
Block->Size = (USHORT)min(MAXUSHORT, Remaining - 1);
|
|
||||||
Block->PreviousSize = PreviousSize;
|
|
||||||
Block->Tag = 0;
|
|
||||||
Block->Data[0].Flink = (Block - &Heap->Blocks) + Block->Size + 1;
|
|
||||||
Block->Data[0].Blink = (Block - &Heap->Blocks) - 1 - PreviousSize;
|
|
||||||
|
|
||||||
/* Substract current block size from remainder */
|
|
||||||
Remaining -= (Block->Size + 1);
|
|
||||||
|
|
||||||
/* Go to next block */
|
|
||||||
PreviousSize = Block->Size;
|
|
||||||
Block = Block + Block->Size + 1;
|
|
||||||
|
|
||||||
TRACE("Remaining = %ld\n", Remaining);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now finish with a terminating block */
|
|
||||||
Heap->TerminatingBlock = Block - &Heap->Blocks;
|
|
||||||
Block->Size = 0;
|
|
||||||
Block->PreviousSize = PreviousSize;
|
|
||||||
Block->Tag = 'dnE#';
|
|
||||||
Block->Data[0].Flink = 0;
|
|
||||||
Block->Data[0].Blink = (Block - &Heap->Blocks) - 1 - PreviousSize;
|
|
||||||
Heap->Blocks.Data[0].Blink = Heap->TerminatingBlock;
|
|
||||||
|
|
||||||
return Heap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
|
||||||
HeapDestroy(
|
|
||||||
PVOID HeapHandle)
|
|
||||||
{
|
|
||||||
PHEAP Heap = HeapHandle;
|
|
||||||
|
|
||||||
/* Mark all pages as firmware temporary, so they are free for the kernel */
|
|
||||||
MmMarkPagesInLookupTable(PageLookupTableAddress,
|
|
||||||
(ULONG_PTR)Heap / MM_PAGE_SIZE,
|
|
||||||
(PFN_COUNT)(Heap->MaximumSize / MM_PAGE_SIZE),
|
|
||||||
LoaderFirmwareTemporary);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
HeapRelease(
|
|
||||||
PVOID HeapHandle)
|
|
||||||
{
|
|
||||||
PHEAP Heap = HeapHandle;
|
|
||||||
PHEAP_BLOCK Block;
|
|
||||||
PUCHAR StartAddress, EndAddress;
|
|
||||||
PFN_COUNT FreePages, AllFreePages = 0;
|
|
||||||
TRACE("HeapRelease(%p)\n", HeapHandle);
|
|
||||||
|
|
||||||
/* Loop all heap chunks */
|
|
||||||
for (Block = &Heap->Blocks;
|
|
||||||
Block->Size != 0;
|
|
||||||
Block = Block + 1 + Block->Size)
|
|
||||||
{
|
|
||||||
/* Continue, if its not free */
|
|
||||||
if (Block->Tag != 0) continue;
|
|
||||||
|
|
||||||
/* Calculate page aligned start address of the free region */
|
|
||||||
StartAddress = ALIGN_UP_POINTER_BY(Block->Data, PAGE_SIZE);
|
|
||||||
|
|
||||||
/* Walk over adjacent free blocks */
|
|
||||||
while (Block->Tag == 0) Block = Block + Block->Size + 1;
|
|
||||||
|
|
||||||
/* Check if this was the last block */
|
|
||||||
if (Block->Size == 0)
|
|
||||||
{
|
|
||||||
/* Align the end address up to cover the end of the heap */
|
|
||||||
EndAddress = ALIGN_DOWN_POINTER_BY(Block->Data, PAGE_SIZE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Align the end address down to not cover any allocations */
|
|
||||||
EndAddress = ALIGN_DOWN_POINTER_BY(Block->Data, PAGE_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
FreePages = (PFN_COUNT)((EndAddress - StartAddress) / MM_PAGE_SIZE);
|
|
||||||
AllFreePages += FreePages;
|
|
||||||
|
|
||||||
/* Now mark the pages free */
|
|
||||||
MmMarkPagesInLookupTable(PageLookupTableAddress,
|
|
||||||
(ULONG_PTR)StartAddress / MM_PAGE_SIZE,
|
|
||||||
FreePages,
|
|
||||||
LoaderFree);
|
|
||||||
|
|
||||||
/* bail out, if it was the last block */
|
|
||||||
if (Block->Size == 0) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ERR("HeapRelease() done, freed %ld pages\n", AllFreePages);
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
HeapCleanupAll(VOID)
|
|
||||||
{
|
|
||||||
PHEAP Heap;
|
|
||||||
|
|
||||||
Heap = FrLdrDefaultHeap;
|
|
||||||
ERR("Heap statistics for default heap:\n"
|
|
||||||
"CurrentAlloc=0x%lx, MaxAlloc=0x%lx, LargestAllocation=0x%lx\n"
|
|
||||||
"NumAllocs=%ld, NumFrees=%ld\n",
|
|
||||||
Heap->CurrentAllocBytes, Heap->MaxAllocBytes, Heap->LargestAllocation,
|
|
||||||
Heap->NumAllocs, Heap->NumFrees);
|
|
||||||
ERR("AllocTime = %I64d, FreeTime = %I64d, sum = %I64d\n",
|
|
||||||
Heap->AllocationTime, Heap->FreeTime, Heap->AllocationTime + Heap->FreeTime);
|
|
||||||
|
|
||||||
|
|
||||||
/* Release fre pages */
|
|
||||||
HeapRelease(FrLdrDefaultHeap);
|
|
||||||
|
|
||||||
Heap = FrLdrTempHeap;
|
|
||||||
ERR("Heap statistics for temp heap:\n"
|
|
||||||
"CurrentAlloc=0x%lx, MaxAlloc=0x%lx, LargestAllocation=0x%lx\n"
|
|
||||||
"NumAllocs=%ld, NumFrees=%ld\n",
|
|
||||||
Heap->CurrentAllocBytes, Heap->MaxAllocBytes, Heap->LargestAllocation,
|
|
||||||
Heap->NumAllocs, Heap->NumFrees);
|
|
||||||
|
|
||||||
/* Destroy the heap */
|
|
||||||
HeapDestroy(FrLdrTempHeap);
|
|
||||||
}
|
|
||||||
|
|
||||||
static VOID
|
|
||||||
HeapRemoveFreeList(
|
|
||||||
PHEAP Heap,
|
|
||||||
PHEAP_BLOCK Block)
|
|
||||||
{
|
|
||||||
PHEAP_BLOCK Previous, Next;
|
|
||||||
|
|
||||||
Next = &Heap->Blocks + Block->Data[0].Flink;
|
|
||||||
Previous = &Heap->Blocks + Block->Data[0].Blink;
|
|
||||||
ASSERT((Next->Tag == 0) || (Next->Tag == 'dnE#'));
|
|
||||||
ASSERT(Next->Data[0].Blink == Block - &Heap->Blocks);
|
|
||||||
ASSERT((Previous->Tag == 0) || (Previous->Tag == 'dnE#'));
|
|
||||||
ASSERT(Previous->Data[0].Flink == Block - &Heap->Blocks);
|
|
||||||
|
|
||||||
Next->Data[0].Blink = Previous - &Heap->Blocks;
|
|
||||||
Previous->Data[0].Flink = Next - &Heap->Blocks;
|
|
||||||
}
|
|
||||||
|
|
||||||
static VOID
|
|
||||||
HeapInsertFreeList(
|
|
||||||
PHEAP Heap,
|
|
||||||
PHEAP_BLOCK FreeBlock)
|
|
||||||
{
|
|
||||||
PHEAP_BLOCK ListHead, NextBlock;
|
|
||||||
ASSERT(FreeBlock->Tag == 0);
|
|
||||||
|
|
||||||
/* Terminating block serves as free list head */
|
|
||||||
ListHead = &Heap->Blocks + Heap->TerminatingBlock;
|
|
||||||
|
|
||||||
for (NextBlock = &Heap->Blocks + ListHead->Data[0].Flink;
|
|
||||||
NextBlock < FreeBlock;
|
|
||||||
NextBlock = &Heap->Blocks + NextBlock->Data[0].Flink);
|
|
||||||
|
|
||||||
FreeBlock->Data[0].Flink = NextBlock - &Heap->Blocks;
|
|
||||||
FreeBlock->Data[0].Blink = NextBlock->Data[0].Blink;
|
|
||||||
NextBlock->Data[0].Blink = FreeBlock - &Heap->Blocks;
|
|
||||||
NextBlock = &Heap->Blocks + FreeBlock->Data[0].Blink;
|
|
||||||
NextBlock->Data[0].Flink = FreeBlock - &Heap->Blocks;
|
|
||||||
}
|
|
||||||
|
|
||||||
PVOID
|
|
||||||
HeapAllocate(
|
|
||||||
PVOID HeapHandle,
|
|
||||||
SIZE_T ByteSize,
|
|
||||||
ULONG Tag)
|
|
||||||
{
|
|
||||||
PHEAP Heap = HeapHandle;
|
|
||||||
PHEAP_BLOCK Block, NextBlock;
|
|
||||||
USHORT BlockSize, Remaining;
|
|
||||||
ULONGLONG Time = __rdtsc();
|
|
||||||
|
|
||||||
/* Check if the allocation is too large */
|
|
||||||
if ((ByteSize + sizeof(HEAP_BLOCK)) > MAXUSHORT * sizeof(HEAP_BLOCK))
|
|
||||||
{
|
|
||||||
ERR("HEAP: Allocation of 0x%lx bytes too large\n", ByteSize);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We need a proper tag */
|
|
||||||
if (Tag == 0) Tag = 'enoN';
|
|
||||||
|
|
||||||
/* Calculate alloc size */
|
|
||||||
BlockSize = (USHORT)((ByteSize + sizeof(HEAP_BLOCK) - 1) / sizeof(HEAP_BLOCK));
|
|
||||||
|
|
||||||
/* Walk the free block list */
|
|
||||||
Block = &Heap->Blocks + Heap->TerminatingBlock;
|
|
||||||
for (Block = &Heap->Blocks + Block->Data[0].Flink;
|
|
||||||
Block->Size != 0;
|
|
||||||
Block = &Heap->Blocks + Block->Data[0].Flink)
|
|
||||||
{
|
|
||||||
ASSERT(Block->Tag == 0);
|
|
||||||
|
|
||||||
/* Continue, if its too small */
|
|
||||||
if (Block->Size < BlockSize) continue;
|
|
||||||
|
|
||||||
/* This block is just fine, use it */
|
|
||||||
Block->Tag = Tag;
|
|
||||||
|
|
||||||
/* Remove this entry from the free list */
|
|
||||||
HeapRemoveFreeList(Heap, Block);
|
|
||||||
|
|
||||||
/* Calculate the remaining size */
|
|
||||||
Remaining = Block->Size - BlockSize;
|
|
||||||
|
|
||||||
/* Check if the remaining space is large enough for a new block */
|
|
||||||
if (Remaining > 1)
|
|
||||||
{
|
|
||||||
/* Make the allocated block as large as neccessary */
|
|
||||||
Block->Size = BlockSize;
|
|
||||||
|
|
||||||
/* Get pointer to the new block */
|
|
||||||
NextBlock = Block + 1 + BlockSize;
|
|
||||||
|
|
||||||
/* Make it a free block */
|
|
||||||
NextBlock->Tag = 0;
|
|
||||||
NextBlock->Size = Remaining - 1;
|
|
||||||
NextBlock->PreviousSize = BlockSize;
|
|
||||||
BlockSize = NextBlock->Size;
|
|
||||||
HeapInsertFreeList(Heap, NextBlock);
|
|
||||||
|
|
||||||
/* Advance to the next block */
|
|
||||||
NextBlock = NextBlock + 1 + BlockSize;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Not enough left, use the full block */
|
|
||||||
BlockSize = Block->Size;
|
|
||||||
|
|
||||||
/* Get the next block */
|
|
||||||
NextBlock = Block + 1 + BlockSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update the next blocks back link */
|
|
||||||
NextBlock->PreviousSize = BlockSize;
|
|
||||||
|
|
||||||
/* Update heap usage */
|
|
||||||
Heap->NumAllocs++;
|
|
||||||
Heap->CurrentAllocBytes += Block->Size * sizeof(HEAP_BLOCK);
|
|
||||||
Heap->MaxAllocBytes = max(Heap->MaxAllocBytes, Heap->CurrentAllocBytes);
|
|
||||||
Heap->LargestAllocation = max(Heap->LargestAllocation,
|
|
||||||
Block->Size * sizeof(HEAP_BLOCK));
|
|
||||||
Heap->AllocationTime += (__rdtsc() - Time);
|
|
||||||
|
|
||||||
TRACE("HeapAllocate(%p, %ld, %.4s) -> return %p\n",
|
|
||||||
HeapHandle, ByteSize, &Tag, Block->Data);
|
|
||||||
|
|
||||||
/* Return pointer to the data */
|
|
||||||
return Block->Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We found nothing */
|
|
||||||
WARN("HEAP: nothing suitable found for 0x%lx bytes\n", ByteSize);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
HeapFree(
|
|
||||||
PVOID HeapHandle,
|
|
||||||
PVOID Pointer,
|
|
||||||
ULONG Tag)
|
|
||||||
{
|
|
||||||
PHEAP Heap = HeapHandle;
|
|
||||||
PHEAP_BLOCK Block, PrevBlock, NextBlock;
|
|
||||||
ULONGLONG Time = __rdtsc();
|
|
||||||
TRACE("HeapFree(%p, %p)\n", HeapHandle, Pointer);
|
|
||||||
ASSERT(Tag != 'dnE#');
|
|
||||||
|
|
||||||
/* Check if the block is really inside this heap */
|
|
||||||
if ((Pointer < (PVOID)(Heap + 1)) ||
|
|
||||||
(Pointer > (PVOID)((PUCHAR)Heap + Heap->MaximumSize)))
|
|
||||||
{
|
|
||||||
ERR("HEAP: trying to free %p outside of heap %p\n", Pointer, Heap);
|
|
||||||
ASSERT(FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
Block = ((PHEAP_BLOCK)Pointer) - 1;
|
|
||||||
|
|
||||||
/* Check if the tag matches */
|
|
||||||
if ((Tag && (Block->Tag != Tag)) || (Block->Tag == 0))
|
|
||||||
{
|
|
||||||
ERR("HEAP: Bad tag! Pointer=%p: block tag '%.4s', requested '%.4s', size=0x%lx\n",
|
|
||||||
Pointer, &Block->Tag, &Tag, Block->Size);
|
|
||||||
ASSERT(FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Mark as free */
|
|
||||||
Block->Tag = 0;
|
|
||||||
|
|
||||||
/* Update heap usage */
|
|
||||||
Heap->NumFrees++;
|
|
||||||
Heap->CurrentAllocBytes -= Block->Size * sizeof(HEAP_BLOCK);
|
|
||||||
|
|
||||||
/* Get pointers to the next and previous block */
|
|
||||||
PrevBlock = Block - Block->PreviousSize - 1;
|
|
||||||
NextBlock = Block + Block->Size + 1;
|
|
||||||
|
|
||||||
/* Check if next block is free */
|
|
||||||
if ((NextBlock->Tag == 0) &&
|
|
||||||
((Block->Size + NextBlock->Size + 1) <= MAXUSHORT))
|
|
||||||
{
|
|
||||||
/* Merge next block into current */
|
|
||||||
Block->Size += NextBlock->Size + 1;
|
|
||||||
HeapRemoveFreeList(Heap, NextBlock);
|
|
||||||
|
|
||||||
NextBlock = Block + Block->Size + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if there is a block before and it's free */
|
|
||||||
if ((Block->PreviousSize != 0) && (PrevBlock->Tag == 0) &&
|
|
||||||
((PrevBlock->Size + Block->Size + 1) <= MAXUSHORT))
|
|
||||||
{
|
|
||||||
/* Merge current block into previous */
|
|
||||||
PrevBlock->Size += Block->Size + 1;
|
|
||||||
Block = PrevBlock;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Insert the entry into the free list */
|
|
||||||
HeapInsertFreeList(Heap, Block);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update the next block's back link */
|
|
||||||
NextBlock->PreviousSize = Block->Size;
|
|
||||||
|
|
||||||
Heap->FreeTime += (__rdtsc() - Time);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Wrapper functions *********************************************************/
|
|
||||||
|
|
||||||
VOID
|
|
||||||
MmInitializeHeap(PVOID PageLookupTable)
|
|
||||||
{
|
|
||||||
TRACE("MmInitializeHeap()\n");
|
|
||||||
|
|
||||||
/* Create the default heap */
|
|
||||||
FrLdrDefaultHeap = HeapCreate(DEFAULT_HEAP_SIZE, LoaderOsloaderHeap);
|
|
||||||
ASSERT(FrLdrDefaultHeap);
|
|
||||||
|
|
||||||
/* Create a temporary heap */
|
|
||||||
FrLdrTempHeap = HeapCreate(TEMP_HEAP_SIZE, LoaderFirmwareTemporary);
|
|
||||||
ASSERT(FrLdrTempHeap);
|
|
||||||
|
|
||||||
TRACE("MmInitializeHeap() done, default heap %p, temp heap %p\n",
|
|
||||||
FrLdrDefaultHeap, FrLdrTempHeap);
|
|
||||||
}
|
|
||||||
|
|
||||||
PVOID
|
|
||||||
MmHeapAlloc(SIZE_T MemorySize)
|
|
||||||
{
|
|
||||||
return HeapAllocate(FrLdrDefaultHeap, MemorySize, 'pHmM');
|
|
||||||
}
|
|
||||||
|
|
||||||
VOID
|
|
||||||
MmHeapFree(PVOID MemoryPointer)
|
|
||||||
{
|
|
||||||
HeapFree(FrLdrDefaultHeap, MemoryPointer, 'pHmM');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#undef ExAllocatePoolWithTag
|
#undef ExAllocatePoolWithTag
|
||||||
PVOID
|
PVOID
|
||||||
NTAPI
|
NTAPI
|
||||||
|
@ -469,16 +105,7 @@ ExAllocatePoolWithTag(
|
||||||
IN SIZE_T NumberOfBytes,
|
IN SIZE_T NumberOfBytes,
|
||||||
IN ULONG Tag)
|
IN ULONG Tag)
|
||||||
{
|
{
|
||||||
return HeapAllocate(FrLdrDefaultHeap, NumberOfBytes, Tag);
|
return MmHeapAlloc(NumberOfBytes);
|
||||||
}
|
|
||||||
|
|
||||||
PVOID
|
|
||||||
NTAPI
|
|
||||||
ExAllocatePool(
|
|
||||||
IN POOL_TYPE PoolType,
|
|
||||||
IN SIZE_T NumberOfBytes)
|
|
||||||
{
|
|
||||||
return HeapAllocate(FrLdrDefaultHeap, NumberOfBytes, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef ExFreePool
|
#undef ExFreePool
|
||||||
|
@ -487,7 +114,7 @@ NTAPI
|
||||||
ExFreePool(
|
ExFreePool(
|
||||||
IN PVOID P)
|
IN PVOID P)
|
||||||
{
|
{
|
||||||
HeapFree(FrLdrDefaultHeap, P, 0);
|
MmHeapFree(P);
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef ExFreePoolWithTag
|
#undef ExFreePoolWithTag
|
||||||
|
@ -497,7 +124,7 @@ ExFreePoolWithTag(
|
||||||
IN PVOID P,
|
IN PVOID P,
|
||||||
IN ULONG Tag)
|
IN ULONG Tag)
|
||||||
{
|
{
|
||||||
HeapFree(FrLdrDefaultHeap, P, Tag);
|
ExFreePool(P);
|
||||||
}
|
}
|
||||||
|
|
||||||
PVOID
|
PVOID
|
||||||
|
@ -509,7 +136,7 @@ RtlAllocateHeap(
|
||||||
{
|
{
|
||||||
PVOID ptr;
|
PVOID ptr;
|
||||||
|
|
||||||
ptr = HeapAllocate(FrLdrDefaultHeap, Size, ' ltR');
|
ptr = MmHeapAlloc(Size);
|
||||||
if (ptr && (Flags & HEAP_ZERO_MEMORY))
|
if (ptr && (Flags & HEAP_ZERO_MEMORY))
|
||||||
{
|
{
|
||||||
RtlZeroMemory(ptr, Size);
|
RtlZeroMemory(ptr, Size);
|
||||||
|
@ -525,7 +152,6 @@ RtlFreeHeap(
|
||||||
IN ULONG Flags,
|
IN ULONG Flags,
|
||||||
IN PVOID HeapBase)
|
IN PVOID HeapBase)
|
||||||
{
|
{
|
||||||
HeapFree(FrLdrDefaultHeap, HeapBase, ' ltR');
|
MmHeapFree(HeapBase);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
531
reactos/boot/freeldr/freeldr/mm/heap_new.c
Normal file
531
reactos/boot/freeldr/freeldr/mm/heap_new.c
Normal file
|
@ -0,0 +1,531 @@
|
||||||
|
/*
|
||||||
|
* FreeLoader
|
||||||
|
* Copyright (C) 2011 Timo Kreuzer (timo.kreuzer@reactos.org)
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <freeldr.h>
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
DBG_DEFAULT_CHANNEL(HEAP);
|
||||||
|
|
||||||
|
#define DEFAULT_HEAP_SIZE (1024 * 1024)
|
||||||
|
#define TEMP_HEAP_SIZE (1024 * 1024)
|
||||||
|
|
||||||
|
PVOID FrLdrDefaultHeap;
|
||||||
|
PVOID FrLdrTempHeap;
|
||||||
|
|
||||||
|
typedef struct _BLOCK_DATA
|
||||||
|
{
|
||||||
|
ULONG_PTR Flink;
|
||||||
|
ULONG_PTR Blink;
|
||||||
|
} BLOCK_DATA, *PBLOCK_DATA;
|
||||||
|
|
||||||
|
typedef struct _HEAP_BLOCK
|
||||||
|
{
|
||||||
|
USHORT Size;
|
||||||
|
USHORT PreviousSize;
|
||||||
|
ULONG Tag;
|
||||||
|
BLOCK_DATA Data[];
|
||||||
|
} HEAP_BLOCK, *PHEAP_BLOCK;
|
||||||
|
|
||||||
|
typedef struct _HEAP
|
||||||
|
{
|
||||||
|
SIZE_T MaximumSize;
|
||||||
|
SIZE_T CurrentAllocBytes;
|
||||||
|
SIZE_T MaxAllocBytes;
|
||||||
|
ULONG NumAllocs;
|
||||||
|
ULONG NumFrees;
|
||||||
|
SIZE_T LargestAllocation;
|
||||||
|
ULONGLONG AllocationTime;
|
||||||
|
ULONGLONG FreeTime;
|
||||||
|
ULONG_PTR TerminatingBlock;
|
||||||
|
HEAP_BLOCK Blocks;
|
||||||
|
} HEAP, *PHEAP;
|
||||||
|
|
||||||
|
PVOID
|
||||||
|
HeapCreate(
|
||||||
|
SIZE_T MaximumSize,
|
||||||
|
TYPE_OF_MEMORY MemoryType)
|
||||||
|
{
|
||||||
|
PHEAP Heap;
|
||||||
|
PHEAP_BLOCK Block;
|
||||||
|
SIZE_T Remaining;
|
||||||
|
USHORT PreviousSize;
|
||||||
|
TRACE("HeapCreate(MemoryType=%ld)\n", MemoryType);
|
||||||
|
|
||||||
|
/* Allocate some memory for the heap */
|
||||||
|
MaximumSize = ALIGN_UP_BY(MaximumSize, MM_PAGE_SIZE);
|
||||||
|
Heap = MmAllocateMemoryWithType(MaximumSize, MemoryType);
|
||||||
|
if (!Heap)
|
||||||
|
{
|
||||||
|
ERR("HEAP: Failed to allocate heap of size 0x%lx, Type\n",
|
||||||
|
MaximumSize, MemoryType);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize the heap header */
|
||||||
|
Heap->MaximumSize = MaximumSize;
|
||||||
|
Heap->CurrentAllocBytes = 0;
|
||||||
|
Heap->MaxAllocBytes = 0;
|
||||||
|
Heap->NumAllocs = 0;
|
||||||
|
Heap->NumFrees = 0;
|
||||||
|
Heap->LargestAllocation = 0;
|
||||||
|
|
||||||
|
/* Calculate what's left to process */
|
||||||
|
Remaining = (MaximumSize - sizeof(HEAP)) / sizeof(HEAP_BLOCK);
|
||||||
|
TRACE("Remaining = %ld\n", Remaining);
|
||||||
|
|
||||||
|
/* Substract 2 for the terminating entry (header + free entry) */
|
||||||
|
Remaining -= 2;
|
||||||
|
|
||||||
|
Block = &Heap->Blocks;
|
||||||
|
PreviousSize = 0;
|
||||||
|
|
||||||
|
/* Create free blocks */
|
||||||
|
while (Remaining > 1)
|
||||||
|
{
|
||||||
|
/* Initialize this free block */
|
||||||
|
Block->Size = (USHORT)min(MAXUSHORT, Remaining - 1);
|
||||||
|
Block->PreviousSize = PreviousSize;
|
||||||
|
Block->Tag = 0;
|
||||||
|
Block->Data[0].Flink = (Block - &Heap->Blocks) + Block->Size + 1;
|
||||||
|
Block->Data[0].Blink = (Block - &Heap->Blocks) - 1 - PreviousSize;
|
||||||
|
|
||||||
|
/* Substract current block size from remainder */
|
||||||
|
Remaining -= (Block->Size + 1);
|
||||||
|
|
||||||
|
/* Go to next block */
|
||||||
|
PreviousSize = Block->Size;
|
||||||
|
Block = Block + Block->Size + 1;
|
||||||
|
|
||||||
|
TRACE("Remaining = %ld\n", Remaining);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now finish with a terminating block */
|
||||||
|
Heap->TerminatingBlock = Block - &Heap->Blocks;
|
||||||
|
Block->Size = 0;
|
||||||
|
Block->PreviousSize = PreviousSize;
|
||||||
|
Block->Tag = 'dnE#';
|
||||||
|
Block->Data[0].Flink = 0;
|
||||||
|
Block->Data[0].Blink = (Block - &Heap->Blocks) - 1 - PreviousSize;
|
||||||
|
Heap->Blocks.Data[0].Blink = Heap->TerminatingBlock;
|
||||||
|
|
||||||
|
return Heap;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
HeapDestroy(
|
||||||
|
PVOID HeapHandle)
|
||||||
|
{
|
||||||
|
PHEAP Heap = HeapHandle;
|
||||||
|
|
||||||
|
/* Mark all pages as firmware temporary, so they are free for the kernel */
|
||||||
|
MmMarkPagesInLookupTable(PageLookupTableAddress,
|
||||||
|
(ULONG_PTR)Heap / MM_PAGE_SIZE,
|
||||||
|
(PFN_COUNT)(Heap->MaximumSize / MM_PAGE_SIZE),
|
||||||
|
LoaderFirmwareTemporary);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
HeapRelease(
|
||||||
|
PVOID HeapHandle)
|
||||||
|
{
|
||||||
|
PHEAP Heap = HeapHandle;
|
||||||
|
PHEAP_BLOCK Block;
|
||||||
|
PUCHAR StartAddress, EndAddress;
|
||||||
|
PFN_COUNT FreePages, AllFreePages = 0;
|
||||||
|
TRACE("HeapRelease(%p)\n", HeapHandle);
|
||||||
|
|
||||||
|
/* Loop all heap chunks */
|
||||||
|
for (Block = &Heap->Blocks;
|
||||||
|
Block->Size != 0;
|
||||||
|
Block = Block + 1 + Block->Size)
|
||||||
|
{
|
||||||
|
/* Continue, if its not free */
|
||||||
|
if (Block->Tag != 0) continue;
|
||||||
|
|
||||||
|
/* Calculate page aligned start address of the free region */
|
||||||
|
StartAddress = ALIGN_UP_POINTER_BY(Block->Data, PAGE_SIZE);
|
||||||
|
|
||||||
|
/* Walk over adjacent free blocks */
|
||||||
|
while (Block->Tag == 0) Block = Block + Block->Size + 1;
|
||||||
|
|
||||||
|
/* Check if this was the last block */
|
||||||
|
if (Block->Size == 0)
|
||||||
|
{
|
||||||
|
/* Align the end address up to cover the end of the heap */
|
||||||
|
EndAddress = ALIGN_DOWN_POINTER_BY(Block->Data, PAGE_SIZE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Align the end address down to not cover any allocations */
|
||||||
|
EndAddress = ALIGN_DOWN_POINTER_BY(Block->Data, PAGE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
FreePages = (PFN_COUNT)((EndAddress - StartAddress) / MM_PAGE_SIZE);
|
||||||
|
AllFreePages += FreePages;
|
||||||
|
|
||||||
|
/* Now mark the pages free */
|
||||||
|
MmMarkPagesInLookupTable(PageLookupTableAddress,
|
||||||
|
(ULONG_PTR)StartAddress / MM_PAGE_SIZE,
|
||||||
|
FreePages,
|
||||||
|
LoaderFree);
|
||||||
|
|
||||||
|
/* bail out, if it was the last block */
|
||||||
|
if (Block->Size == 0) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ERR("HeapRelease() done, freed %ld pages\n", AllFreePages);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
HeapCleanupAll(VOID)
|
||||||
|
{
|
||||||
|
PHEAP Heap;
|
||||||
|
|
||||||
|
Heap = FrLdrDefaultHeap;
|
||||||
|
ERR("Heap statistics for default heap:\n"
|
||||||
|
"CurrentAlloc=0x%lx, MaxAlloc=0x%lx, LargestAllocation=0x%lx\n"
|
||||||
|
"NumAllocs=%ld, NumFrees=%ld\n",
|
||||||
|
Heap->CurrentAllocBytes, Heap->MaxAllocBytes, Heap->LargestAllocation,
|
||||||
|
Heap->NumAllocs, Heap->NumFrees);
|
||||||
|
ERR("AllocTime = %I64d, FreeTime = %I64d, sum = %I64d\n",
|
||||||
|
Heap->AllocationTime, Heap->FreeTime, Heap->AllocationTime + Heap->FreeTime);
|
||||||
|
|
||||||
|
|
||||||
|
/* Release fre pages */
|
||||||
|
HeapRelease(FrLdrDefaultHeap);
|
||||||
|
|
||||||
|
Heap = FrLdrTempHeap;
|
||||||
|
ERR("Heap statistics for temp heap:\n"
|
||||||
|
"CurrentAlloc=0x%lx, MaxAlloc=0x%lx, LargestAllocation=0x%lx\n"
|
||||||
|
"NumAllocs=%ld, NumFrees=%ld\n",
|
||||||
|
Heap->CurrentAllocBytes, Heap->MaxAllocBytes, Heap->LargestAllocation,
|
||||||
|
Heap->NumAllocs, Heap->NumFrees);
|
||||||
|
|
||||||
|
/* Destroy the heap */
|
||||||
|
HeapDestroy(FrLdrTempHeap);
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID
|
||||||
|
HeapRemoveFreeList(
|
||||||
|
PHEAP Heap,
|
||||||
|
PHEAP_BLOCK Block)
|
||||||
|
{
|
||||||
|
PHEAP_BLOCK Previous, Next;
|
||||||
|
|
||||||
|
Next = &Heap->Blocks + Block->Data[0].Flink;
|
||||||
|
Previous = &Heap->Blocks + Block->Data[0].Blink;
|
||||||
|
ASSERT((Next->Tag == 0) || (Next->Tag == 'dnE#'));
|
||||||
|
ASSERT(Next->Data[0].Blink == Block - &Heap->Blocks);
|
||||||
|
ASSERT((Previous->Tag == 0) || (Previous->Tag == 'dnE#'));
|
||||||
|
ASSERT(Previous->Data[0].Flink == Block - &Heap->Blocks);
|
||||||
|
|
||||||
|
Next->Data[0].Blink = Previous - &Heap->Blocks;
|
||||||
|
Previous->Data[0].Flink = Next - &Heap->Blocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
static VOID
|
||||||
|
HeapInsertFreeList(
|
||||||
|
PHEAP Heap,
|
||||||
|
PHEAP_BLOCK FreeBlock)
|
||||||
|
{
|
||||||
|
PHEAP_BLOCK ListHead, NextBlock;
|
||||||
|
ASSERT(FreeBlock->Tag == 0);
|
||||||
|
|
||||||
|
/* Terminating block serves as free list head */
|
||||||
|
ListHead = &Heap->Blocks + Heap->TerminatingBlock;
|
||||||
|
|
||||||
|
for (NextBlock = &Heap->Blocks + ListHead->Data[0].Flink;
|
||||||
|
NextBlock < FreeBlock;
|
||||||
|
NextBlock = &Heap->Blocks + NextBlock->Data[0].Flink);
|
||||||
|
|
||||||
|
FreeBlock->Data[0].Flink = NextBlock - &Heap->Blocks;
|
||||||
|
FreeBlock->Data[0].Blink = NextBlock->Data[0].Blink;
|
||||||
|
NextBlock->Data[0].Blink = FreeBlock - &Heap->Blocks;
|
||||||
|
NextBlock = &Heap->Blocks + FreeBlock->Data[0].Blink;
|
||||||
|
NextBlock->Data[0].Flink = FreeBlock - &Heap->Blocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
PVOID
|
||||||
|
HeapAllocate(
|
||||||
|
PVOID HeapHandle,
|
||||||
|
SIZE_T ByteSize,
|
||||||
|
ULONG Tag)
|
||||||
|
{
|
||||||
|
PHEAP Heap = HeapHandle;
|
||||||
|
PHEAP_BLOCK Block, NextBlock;
|
||||||
|
USHORT BlockSize, Remaining;
|
||||||
|
ULONGLONG Time = __rdtsc();
|
||||||
|
|
||||||
|
/* Check if the allocation is too large */
|
||||||
|
if ((ByteSize + sizeof(HEAP_BLOCK)) > MAXUSHORT * sizeof(HEAP_BLOCK))
|
||||||
|
{
|
||||||
|
ERR("HEAP: Allocation of 0x%lx bytes too large\n", ByteSize);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We need a proper tag */
|
||||||
|
if (Tag == 0) Tag = 'enoN';
|
||||||
|
|
||||||
|
/* Calculate alloc size */
|
||||||
|
BlockSize = (USHORT)((ByteSize + sizeof(HEAP_BLOCK) - 1) / sizeof(HEAP_BLOCK));
|
||||||
|
|
||||||
|
/* Walk the free block list */
|
||||||
|
Block = &Heap->Blocks + Heap->TerminatingBlock;
|
||||||
|
for (Block = &Heap->Blocks + Block->Data[0].Flink;
|
||||||
|
Block->Size != 0;
|
||||||
|
Block = &Heap->Blocks + Block->Data[0].Flink)
|
||||||
|
{
|
||||||
|
ASSERT(Block->Tag == 0);
|
||||||
|
|
||||||
|
/* Continue, if its too small */
|
||||||
|
if (Block->Size < BlockSize) continue;
|
||||||
|
|
||||||
|
/* This block is just fine, use it */
|
||||||
|
Block->Tag = Tag;
|
||||||
|
|
||||||
|
/* Remove this entry from the free list */
|
||||||
|
HeapRemoveFreeList(Heap, Block);
|
||||||
|
|
||||||
|
/* Calculate the remaining size */
|
||||||
|
Remaining = Block->Size - BlockSize;
|
||||||
|
|
||||||
|
/* Check if the remaining space is large enough for a new block */
|
||||||
|
if (Remaining > 1)
|
||||||
|
{
|
||||||
|
/* Make the allocated block as large as neccessary */
|
||||||
|
Block->Size = BlockSize;
|
||||||
|
|
||||||
|
/* Get pointer to the new block */
|
||||||
|
NextBlock = Block + 1 + BlockSize;
|
||||||
|
|
||||||
|
/* Make it a free block */
|
||||||
|
NextBlock->Tag = 0;
|
||||||
|
NextBlock->Size = Remaining - 1;
|
||||||
|
NextBlock->PreviousSize = BlockSize;
|
||||||
|
BlockSize = NextBlock->Size;
|
||||||
|
HeapInsertFreeList(Heap, NextBlock);
|
||||||
|
|
||||||
|
/* Advance to the next block */
|
||||||
|
NextBlock = NextBlock + 1 + BlockSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Not enough left, use the full block */
|
||||||
|
BlockSize = Block->Size;
|
||||||
|
|
||||||
|
/* Get the next block */
|
||||||
|
NextBlock = Block + 1 + BlockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update the next blocks back link */
|
||||||
|
NextBlock->PreviousSize = BlockSize;
|
||||||
|
|
||||||
|
/* Update heap usage */
|
||||||
|
Heap->NumAllocs++;
|
||||||
|
Heap->CurrentAllocBytes += Block->Size * sizeof(HEAP_BLOCK);
|
||||||
|
Heap->MaxAllocBytes = max(Heap->MaxAllocBytes, Heap->CurrentAllocBytes);
|
||||||
|
Heap->LargestAllocation = max(Heap->LargestAllocation,
|
||||||
|
Block->Size * sizeof(HEAP_BLOCK));
|
||||||
|
Heap->AllocationTime += (__rdtsc() - Time);
|
||||||
|
|
||||||
|
TRACE("HeapAllocate(%p, %ld, %.4s) -> return %p\n",
|
||||||
|
HeapHandle, ByteSize, &Tag, Block->Data);
|
||||||
|
|
||||||
|
/* Return pointer to the data */
|
||||||
|
return Block->Data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We found nothing */
|
||||||
|
WARN("HEAP: nothing suitable found for 0x%lx bytes\n", ByteSize);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
HeapFree(
|
||||||
|
PVOID HeapHandle,
|
||||||
|
PVOID Pointer,
|
||||||
|
ULONG Tag)
|
||||||
|
{
|
||||||
|
PHEAP Heap = HeapHandle;
|
||||||
|
PHEAP_BLOCK Block, PrevBlock, NextBlock;
|
||||||
|
ULONGLONG Time = __rdtsc();
|
||||||
|
TRACE("HeapFree(%p, %p)\n", HeapHandle, Pointer);
|
||||||
|
ASSERT(Tag != 'dnE#');
|
||||||
|
|
||||||
|
/* Check if the block is really inside this heap */
|
||||||
|
if ((Pointer < (PVOID)(Heap + 1)) ||
|
||||||
|
(Pointer > (PVOID)((PUCHAR)Heap + Heap->MaximumSize)))
|
||||||
|
{
|
||||||
|
ERR("HEAP: trying to free %p outside of heap %p\n", Pointer, Heap);
|
||||||
|
ASSERT(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
Block = ((PHEAP_BLOCK)Pointer) - 1;
|
||||||
|
|
||||||
|
/* Check if the tag matches */
|
||||||
|
if ((Tag && (Block->Tag != Tag)) || (Block->Tag == 0))
|
||||||
|
{
|
||||||
|
ERR("HEAP: Bad tag! Pointer=%p: block tag '%.4s', requested '%.4s', size=0x%lx\n",
|
||||||
|
Pointer, &Block->Tag, &Tag, Block->Size);
|
||||||
|
ASSERT(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mark as free */
|
||||||
|
Block->Tag = 0;
|
||||||
|
|
||||||
|
/* Update heap usage */
|
||||||
|
Heap->NumFrees++;
|
||||||
|
Heap->CurrentAllocBytes -= Block->Size * sizeof(HEAP_BLOCK);
|
||||||
|
|
||||||
|
/* Get pointers to the next and previous block */
|
||||||
|
PrevBlock = Block - Block->PreviousSize - 1;
|
||||||
|
NextBlock = Block + Block->Size + 1;
|
||||||
|
|
||||||
|
/* Check if next block is free */
|
||||||
|
if ((NextBlock->Tag == 0) &&
|
||||||
|
((Block->Size + NextBlock->Size + 1) <= MAXUSHORT))
|
||||||
|
{
|
||||||
|
/* Merge next block into current */
|
||||||
|
Block->Size += NextBlock->Size + 1;
|
||||||
|
HeapRemoveFreeList(Heap, NextBlock);
|
||||||
|
|
||||||
|
NextBlock = Block + Block->Size + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if there is a block before and it's free */
|
||||||
|
if ((Block->PreviousSize != 0) && (PrevBlock->Tag == 0) &&
|
||||||
|
((PrevBlock->Size + Block->Size + 1) <= MAXUSHORT))
|
||||||
|
{
|
||||||
|
/* Merge current block into previous */
|
||||||
|
PrevBlock->Size += Block->Size + 1;
|
||||||
|
Block = PrevBlock;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Insert the entry into the free list */
|
||||||
|
HeapInsertFreeList(Heap, Block);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update the next block's back link */
|
||||||
|
NextBlock->PreviousSize = Block->Size;
|
||||||
|
|
||||||
|
Heap->FreeTime += (__rdtsc() - Time);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Wrapper functions *********************************************************/
|
||||||
|
|
||||||
|
VOID
|
||||||
|
MmInitializeHeap(PVOID PageLookupTable)
|
||||||
|
{
|
||||||
|
TRACE("MmInitializeHeap()\n");
|
||||||
|
|
||||||
|
/* Create the default heap */
|
||||||
|
FrLdrDefaultHeap = HeapCreate(DEFAULT_HEAP_SIZE, LoaderOsloaderHeap);
|
||||||
|
ASSERT(FrLdrDefaultHeap);
|
||||||
|
|
||||||
|
/* Create a temporary heap */
|
||||||
|
FrLdrTempHeap = HeapCreate(TEMP_HEAP_SIZE, LoaderFirmwareTemporary);
|
||||||
|
ASSERT(FrLdrTempHeap);
|
||||||
|
|
||||||
|
TRACE("MmInitializeHeap() done, default heap %p, temp heap %p\n",
|
||||||
|
FrLdrDefaultHeap, FrLdrTempHeap);
|
||||||
|
}
|
||||||
|
|
||||||
|
PVOID
|
||||||
|
MmHeapAlloc(SIZE_T MemorySize)
|
||||||
|
{
|
||||||
|
return HeapAllocate(FrLdrDefaultHeap, MemorySize, 'pHmM');
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
MmHeapFree(PVOID MemoryPointer)
|
||||||
|
{
|
||||||
|
HeapFree(FrLdrDefaultHeap, MemoryPointer, 'pHmM');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#undef ExAllocatePoolWithTag
|
||||||
|
PVOID
|
||||||
|
NTAPI
|
||||||
|
ExAllocatePoolWithTag(
|
||||||
|
IN POOL_TYPE PoolType,
|
||||||
|
IN SIZE_T NumberOfBytes,
|
||||||
|
IN ULONG Tag)
|
||||||
|
{
|
||||||
|
return HeapAllocate(FrLdrDefaultHeap, NumberOfBytes, Tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
PVOID
|
||||||
|
NTAPI
|
||||||
|
ExAllocatePool(
|
||||||
|
IN POOL_TYPE PoolType,
|
||||||
|
IN SIZE_T NumberOfBytes)
|
||||||
|
{
|
||||||
|
return HeapAllocate(FrLdrDefaultHeap, NumberOfBytes, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef ExFreePool
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
ExFreePool(
|
||||||
|
IN PVOID P)
|
||||||
|
{
|
||||||
|
HeapFree(FrLdrDefaultHeap, P, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef ExFreePoolWithTag
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
ExFreePoolWithTag(
|
||||||
|
IN PVOID P,
|
||||||
|
IN ULONG Tag)
|
||||||
|
{
|
||||||
|
HeapFree(FrLdrDefaultHeap, P, Tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
PVOID
|
||||||
|
NTAPI
|
||||||
|
RtlAllocateHeap(
|
||||||
|
IN PVOID HeapHandle,
|
||||||
|
IN ULONG Flags,
|
||||||
|
IN SIZE_T Size)
|
||||||
|
{
|
||||||
|
PVOID ptr;
|
||||||
|
|
||||||
|
ptr = HeapAllocate(FrLdrDefaultHeap, Size, ' ltR');
|
||||||
|
if (ptr && (Flags & HEAP_ZERO_MEMORY))
|
||||||
|
{
|
||||||
|
RtlZeroMemory(ptr, Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
NTAPI
|
||||||
|
RtlFreeHeap(
|
||||||
|
IN PVOID HeapHandle,
|
||||||
|
IN ULONG Flags,
|
||||||
|
IN PVOID HeapBase)
|
||||||
|
{
|
||||||
|
HeapFree(FrLdrDefaultHeap, HeapBase, ' ltR');
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
1599
reactos/boot/freeldr/freeldr/rtl/bget.c
Normal file
1599
reactos/boot/freeldr/freeldr/rtl/bget.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -203,7 +203,7 @@ WinLdrSetupMemoryLayout(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||||
//BOOLEAN Status;
|
//BOOLEAN Status;
|
||||||
|
|
||||||
/* Cleanup heap */
|
/* Cleanup heap */
|
||||||
HeapCleanupAll();
|
//HeapCleanupAll();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Creating a suitable memory map for Windows can be tricky, so let's
|
// Creating a suitable memory map for Windows can be tricky, so let's
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue