154 lines
4.4 KiB
C++
154 lines
4.4 KiB
C++
|
/**********************************************************************/
|
||
|
/** Microsoft Windows/NT **/
|
||
|
/** Copyright(c) Microsoft Corporation, 1997 - 2002 **/
|
||
|
/**********************************************************************/
|
||
|
|
||
|
#include "stdafx.h"
|
||
|
#include "util.h"
|
||
|
|
||
|
|
||
|
PVOID __fastcall MyVirtualAlloc(ULONG Size)
|
||
|
{
|
||
|
return VirtualAlloc( NULL, Size, MEM_COMMIT, PAGE_READWRITE );
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID __fastcall MyVirtualFree(PVOID Allocation)
|
||
|
{
|
||
|
VirtualFree( Allocation, 0, MEM_RELEASE );
|
||
|
}
|
||
|
|
||
|
|
||
|
HANDLE CreateSubAllocator(IN ULONG InitialCommitSize, IN ULONG GrowthCommitSize)
|
||
|
{
|
||
|
PSUBALLOCATOR SubAllocator;
|
||
|
ULONG InitialSize;
|
||
|
ULONG GrowthSize;
|
||
|
|
||
|
InitialSize = ROUNDUP2( InitialCommitSize, MINIMUM_VM_ALLOCATION );
|
||
|
GrowthSize = ROUNDUP2( GrowthCommitSize, MINIMUM_VM_ALLOCATION );
|
||
|
|
||
|
SubAllocator = (PSUBALLOCATOR)MyVirtualAlloc( InitialSize );
|
||
|
|
||
|
//
|
||
|
// If can't allocate entire initial size, back off to minimum size.
|
||
|
// Very large initial requests sometimes cannot be allocated simply
|
||
|
// because there is not enough contiguous address space.
|
||
|
//
|
||
|
|
||
|
if ( SubAllocator == NULL )
|
||
|
{
|
||
|
SubAllocator = (PSUBALLOCATOR)MyVirtualAlloc( GrowthSize );
|
||
|
}
|
||
|
|
||
|
if ( SubAllocator == NULL )
|
||
|
{
|
||
|
SubAllocator = (PSUBALLOCATOR)MyVirtualAlloc( MINIMUM_VM_ALLOCATION );
|
||
|
}
|
||
|
|
||
|
if ( SubAllocator != NULL )
|
||
|
{
|
||
|
SubAllocator->NextAvailable = (PCHAR)SubAllocator + ROUNDUP2( sizeof( SUBALLOCATOR ), SUBALLOCATOR_ALIGNMENT );
|
||
|
SubAllocator->LastAvailable = (PCHAR)SubAllocator + InitialSize;
|
||
|
SubAllocator->VirtualList = (PVOID*)SubAllocator;
|
||
|
SubAllocator->GrowSize = GrowthSize;
|
||
|
}
|
||
|
|
||
|
return (HANDLE) SubAllocator;
|
||
|
}
|
||
|
|
||
|
|
||
|
PVOID __fastcall SubAllocate(IN HANDLE hAllocator, IN ULONG Size)
|
||
|
{
|
||
|
PSUBALLOCATOR SubAllocator = (PSUBALLOCATOR) hAllocator;
|
||
|
PCHAR NewVirtual;
|
||
|
PCHAR Allocation;
|
||
|
ULONG AllocSize;
|
||
|
ULONG_PTR Available;
|
||
|
ULONG GrowSize;
|
||
|
|
||
|
ASSERT( Size < (ULONG)( ~(( SUBALLOCATOR_ALIGNMENT * 2 ) - 1 )));
|
||
|
|
||
|
AllocSize = ROUNDUP2( Size, SUBALLOCATOR_ALIGNMENT );
|
||
|
Available = SubAllocator->LastAvailable - SubAllocator->NextAvailable;
|
||
|
|
||
|
if ( AllocSize <= Available )
|
||
|
{
|
||
|
Allocation = SubAllocator->NextAvailable;
|
||
|
SubAllocator->NextAvailable = Allocation + AllocSize;
|
||
|
return Allocation;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Insufficient VM, so grow it. Make sure we grow it enough to satisfy
|
||
|
// the allocation request in case the request is larger than the grow
|
||
|
// size specified in CreateSubAllocator.
|
||
|
//
|
||
|
|
||
|
|
||
|
GrowSize = SubAllocator->GrowSize;
|
||
|
|
||
|
if ( GrowSize < ( AllocSize + SUBALLOCATOR_ALIGNMENT ))
|
||
|
{
|
||
|
GrowSize = ROUNDUP2(( AllocSize + SUBALLOCATOR_ALIGNMENT ), MINIMUM_VM_ALLOCATION );
|
||
|
}
|
||
|
|
||
|
NewVirtual = (PCHAR)MyVirtualAlloc( GrowSize );
|
||
|
|
||
|
// If failed to alloc GrowSize VM, and the allocation could be satisfied
|
||
|
// with a minimum VM allocation, try allocating minimum VM to satisfy
|
||
|
// this request.
|
||
|
//
|
||
|
|
||
|
if (( NewVirtual == NULL ) && ( AllocSize <= ( MINIMUM_VM_ALLOCATION - SUBALLOCATOR_ALIGNMENT )))
|
||
|
{
|
||
|
GrowSize = MINIMUM_VM_ALLOCATION;
|
||
|
NewVirtual = (PCHAR)MyVirtualAlloc( GrowSize );
|
||
|
}
|
||
|
|
||
|
if ( NewVirtual != NULL )
|
||
|
{
|
||
|
|
||
|
// Set LastAvailable to end of new VM block.
|
||
|
SubAllocator->LastAvailable = NewVirtual + GrowSize;
|
||
|
|
||
|
// Link new VM into list of VM allocations.
|
||
|
|
||
|
*(PVOID*)NewVirtual = SubAllocator->VirtualList;
|
||
|
SubAllocator->VirtualList = (PVOID*)NewVirtual;
|
||
|
|
||
|
// Requested allocation comes next.
|
||
|
Allocation = NewVirtual + SUBALLOCATOR_ALIGNMENT;
|
||
|
|
||
|
// Then set the NextAvailable for what's remaining.
|
||
|
|
||
|
SubAllocator->NextAvailable = Allocation + AllocSize;
|
||
|
|
||
|
// And return the allocation.
|
||
|
|
||
|
return Allocation;
|
||
|
}
|
||
|
|
||
|
// Could not allocate enough VM to satisfy request.
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID DestroySubAllocator(IN HANDLE hAllocator)
|
||
|
{
|
||
|
PSUBALLOCATOR SubAllocator = (PSUBALLOCATOR) hAllocator;
|
||
|
PVOID VirtualBlock = SubAllocator->VirtualList;
|
||
|
PVOID NextVirtualBlock;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
NextVirtualBlock = *(PVOID*)VirtualBlock;
|
||
|
MyVirtualFree( VirtualBlock );
|
||
|
VirtualBlock = NextVirtualBlock;
|
||
|
|
||
|
}while (VirtualBlock != NULL);
|
||
|
}
|
||
|
|
||
|
|
||
|
|