204 lines
4.8 KiB
C
204 lines
4.8 KiB
C
|
|
#include "poolmem.h"
|
|
|
|
|
|
|
|
// Tree Memory Allocation structure.
|
|
|
|
|
|
typedef struct _POOLMEMORYBLOCK POOLMEMORYBLOCK, *PPOOLMEMORYBLOCK;
|
|
|
|
struct _POOLMEMORYBLOCK {
|
|
DWORD Index;
|
|
DWORD Size;
|
|
PPOOLMEMORYBLOCK NextBlock;
|
|
PPOOLMEMORYBLOCK PrevBlock;
|
|
PBYTE RawMemory;
|
|
};
|
|
|
|
typedef struct _POOLHEADER {
|
|
PPOOLMEMORYBLOCK PoolHead;
|
|
HANDLE Heap;
|
|
} POOLHEADER, *PPOOLHEADER;
|
|
|
|
|
|
BOOL
|
|
PoolMemAddMemory (
|
|
IN POOLHANDLE Handle,
|
|
IN DWORD Size
|
|
)
|
|
{
|
|
PBYTE allocedMemory;
|
|
PPOOLMEMORYBLOCK newBlock;
|
|
PPOOLHEADER poolHeader = (PPOOLHEADER) Handle;
|
|
DWORD sizeNeeded;
|
|
|
|
assert(poolHeader != NULL);
|
|
|
|
//
|
|
// Determine size needed and attempt to allocate memory.
|
|
//
|
|
if (Size + sizeof(POOLMEMORYBLOCK) > POOLMEMORYBLOCKSIZE) {
|
|
sizeNeeded = Size + sizeof(POOLMEMORYBLOCK);
|
|
}
|
|
else {
|
|
sizeNeeded = POOLMEMORYBLOCKSIZE;
|
|
}
|
|
|
|
allocedMemory = HeapAlloc(poolHeader -> Heap,0,sizeNeeded);
|
|
|
|
if (allocedMemory) {
|
|
|
|
//
|
|
// Use the beginning of the alloc'ed block as the poolblock structure.
|
|
//
|
|
newBlock = (PPOOLMEMORYBLOCK) allocedMemory;
|
|
newBlock -> Size = sizeNeeded - sizeof(POOLMEMORYBLOCK);
|
|
newBlock -> RawMemory = allocedMemory + sizeof(POOLMEMORYBLOCK);
|
|
newBlock -> Index = 0;
|
|
|
|
//
|
|
// Link the block into the list.
|
|
//
|
|
if (poolHeader -> PoolHead) {
|
|
poolHeader -> PoolHead -> PrevBlock = newBlock;
|
|
}
|
|
newBlock -> NextBlock = poolHeader -> PoolHead;
|
|
newBlock -> PrevBlock = NULL;
|
|
poolHeader -> PoolHead = newBlock;
|
|
|
|
|
|
}
|
|
//
|
|
// Assuming allocedMemory is non-NULL, we have succeeded.
|
|
//
|
|
return allocedMemory != NULL;
|
|
}
|
|
|
|
|
|
POOLHANDLE
|
|
WINAPI
|
|
PoolMemInitPool (
|
|
)
|
|
{
|
|
BOOL ableToAddMemory;
|
|
PPOOLHEADER header = NULL;
|
|
HANDLE procHeap;
|
|
|
|
|
|
procHeap = GetProcessHeap();
|
|
//
|
|
// Allocate the header of this pool.
|
|
//
|
|
header = HeapAlloc(procHeap,0,sizeof(POOLHEADER));
|
|
|
|
if (header) {
|
|
|
|
//
|
|
// Allocation was successful. Now, initialize the pool.
|
|
//
|
|
header -> PoolHead = NULL;
|
|
header -> Heap = procHeap;
|
|
|
|
//
|
|
// Actually add some memory to the pool.
|
|
//
|
|
ableToAddMemory = PoolMemAddMemory(header,0);
|
|
|
|
if (!ableToAddMemory) {
|
|
//
|
|
// Unable to add memory to the pool.
|
|
//
|
|
HeapFree(header -> Heap,0,header);
|
|
header = NULL;
|
|
}
|
|
|
|
}
|
|
return (POOLHANDLE) header;
|
|
}
|
|
|
|
|
|
VOID
|
|
WINAPI
|
|
PoolMemDestroyPool (
|
|
POOLHANDLE Handle
|
|
)
|
|
{
|
|
PPOOLMEMORYBLOCK nextBlock;
|
|
PPOOLMEMORYBLOCK blockToFree;
|
|
PPOOLHEADER poolHeader;
|
|
|
|
assert(Handle != NULL);
|
|
|
|
poolHeader = (PPOOLHEADER) Handle;
|
|
|
|
//
|
|
// Walk the list, freeing as we go.
|
|
//
|
|
blockToFree = poolHeader -> PoolHead;
|
|
|
|
while (blockToFree != NULL) {
|
|
|
|
nextBlock = blockToFree->NextBlock;
|
|
HeapFree(poolHeader -> Heap,0,blockToFree);
|
|
blockToFree = nextBlock;
|
|
}
|
|
|
|
//
|
|
// Also, deallocate the poolheader itself.
|
|
//
|
|
HeapFree(poolHeader -> Heap,0,poolHeader);
|
|
|
|
}
|
|
|
|
PVOID
|
|
WINAPI
|
|
PoolMemGetAlignedMemory (
|
|
IN POOLHANDLE Handle,
|
|
IN DWORD Size,
|
|
IN DWORD AlignSize
|
|
)
|
|
|
|
{
|
|
BOOL haveEnoughMemory = TRUE;
|
|
PVOID rMemory = NULL;
|
|
PPOOLHEADER poolHeader = (PPOOLHEADER) Handle;
|
|
PPOOLMEMORYBLOCK currentBlock;
|
|
DWORD sizeNeeded;
|
|
DWORD padLength;
|
|
|
|
assert(poolHeader != NULL);
|
|
|
|
currentBlock = poolHeader -> PoolHead;
|
|
|
|
// Determine if more memory is needed, attempt to add if needed.
|
|
sizeNeeded = Size;
|
|
|
|
if (currentBlock -> Size - currentBlock -> Index < sizeNeeded + AlignSize) {
|
|
|
|
haveEnoughMemory = PoolMemAddMemory(poolHeader,sizeNeeded + AlignSize);
|
|
currentBlock = poolHeader -> PoolHead;
|
|
}
|
|
|
|
// If there is enough memory available, return it.
|
|
if (haveEnoughMemory) {
|
|
if (AlignSize) {
|
|
|
|
padLength = (DWORD) currentBlock + sizeof(POOLMEMORYBLOCK)
|
|
+ currentBlock -> Index;
|
|
currentBlock -> Index += (AlignSize - (padLength % AlignSize)) % AlignSize;
|
|
|
|
}
|
|
|
|
|
|
//Now, get the address of the memory to return.
|
|
rMemory = (PVOID)
|
|
&(currentBlock->RawMemory[currentBlock -> Index]);
|
|
|
|
currentBlock->Index += sizeNeeded;
|
|
}
|
|
|
|
return rMemory;
|
|
}
|
|
|