149 lines
2.7 KiB
C++
149 lines
2.7 KiB
C++
|
#include "KePageAllocator.h"
|
||
|
|
||
|
using namespace Knight;
|
||
|
|
||
|
struct PageInfo
|
||
|
{
|
||
|
PageInfo *next;
|
||
|
void *base;
|
||
|
};
|
||
|
|
||
|
class Knight::KePageAllocator
|
||
|
{
|
||
|
public:
|
||
|
size_t page_size;
|
||
|
size_t page_granularity;
|
||
|
PageInfo *free_pages;
|
||
|
PageInfo *page_blocks;
|
||
|
};
|
||
|
|
||
|
static void *ke_LumpPageAlloc(KePageAllocator *alloc)
|
||
|
{
|
||
|
void *base;
|
||
|
char *page;
|
||
|
PageInfo *lump;
|
||
|
size_t pagesInBlock;
|
||
|
|
||
|
#if defined KE_PLATFORM_WINDOWS
|
||
|
base = VirtualAlloc(
|
||
|
NULL,
|
||
|
alloc->page_granularity,
|
||
|
MEM_COMMIT|MEM_RESERVE,
|
||
|
PAGE_READWRITE);
|
||
|
#elif defined KE_PLATFORM_POSIX
|
||
|
base = valloc(alloc->page_granularity);
|
||
|
#else
|
||
|
#error "Unsupported platform"
|
||
|
#endif
|
||
|
|
||
|
if (base == NULL)
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
lump = new PageInfo;
|
||
|
lump->base = base;
|
||
|
lump->next = alloc->page_blocks;
|
||
|
alloc->page_blocks = lump->next;
|
||
|
|
||
|
page = (char *)base + alloc->page_size;
|
||
|
pagesInBlock = alloc->page_granularity / alloc->page_size;
|
||
|
|
||
|
for (size_t i = 1; i < pagesInBlock; i++)
|
||
|
{
|
||
|
lump = new PageInfo;
|
||
|
lump->base = page;
|
||
|
lump->next = alloc->free_pages;
|
||
|
alloc->free_pages = lump;
|
||
|
page += alloc->page_size;
|
||
|
}
|
||
|
|
||
|
return base;
|
||
|
}
|
||
|
|
||
|
KePageAllocator *Knight::KE_CreatePageAllocator()
|
||
|
{
|
||
|
KePageAllocator *alloc;
|
||
|
|
||
|
alloc = new KePageAllocator;
|
||
|
|
||
|
#if defined KE_PLATFORM_WINDOWS
|
||
|
SYSTEM_INFO info;
|
||
|
|
||
|
GetSystemInfo(&info);
|
||
|
alloc->page_size = info.dwPageSize;
|
||
|
alloc->page_granularity = info.dwAllocationGranularity;
|
||
|
#elif defined KE_PLATFORM_POSIX
|
||
|
alloc->page_size = sysconf(_SC_PAGESIZE);
|
||
|
alloc->page_granularity = alloc->page_size * 16;
|
||
|
#else
|
||
|
#error "Unsupported platform"
|
||
|
#endif
|
||
|
|
||
|
alloc->free_pages = NULL;
|
||
|
alloc->page_blocks = NULL;
|
||
|
|
||
|
return alloc;
|
||
|
}
|
||
|
|
||
|
void Knight::KE_DestroyPageAllocator(KePageAllocator *alloc)
|
||
|
{
|
||
|
PageInfo *info, *next;
|
||
|
|
||
|
info = alloc->page_blocks;
|
||
|
while (info != NULL)
|
||
|
{
|
||
|
next = info->next;
|
||
|
#if defined KE_PLATFORM_WINDOWS
|
||
|
VirtualFree(info->base, 0, MEM_RELEASE);
|
||
|
#elif defined KE_PLATFORM_WINDOWS
|
||
|
free(info->base);
|
||
|
#else
|
||
|
#error "Unsupported platform"
|
||
|
#endif
|
||
|
delete info;
|
||
|
next = info;
|
||
|
}
|
||
|
|
||
|
info = alloc->free_pages;
|
||
|
while (info != NULL)
|
||
|
{
|
||
|
next = info->next;
|
||
|
delete info;
|
||
|
info = next;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void *Knight::KE_PageAlloc(KePageAllocator *alloc)
|
||
|
{
|
||
|
if (alloc->free_pages != NULL)
|
||
|
{
|
||
|
void *base;
|
||
|
PageInfo *info;
|
||
|
|
||
|
info = alloc->free_pages;
|
||
|
alloc->free_pages = info->next;
|
||
|
base = info->base;
|
||
|
delete info;
|
||
|
|
||
|
return base;
|
||
|
}
|
||
|
|
||
|
return ke_LumpPageAlloc(alloc);
|
||
|
}
|
||
|
|
||
|
void Knight::KE_PageFree(KePageAllocator *alloc, void *page)
|
||
|
{
|
||
|
PageInfo *info;
|
||
|
|
||
|
info = new PageInfo;
|
||
|
info->base = page;
|
||
|
info->next = alloc->free_pages;
|
||
|
alloc->free_pages = info->next;
|
||
|
}
|
||
|
|
||
|
size_t Knight::KE_PageSize(KePageAllocator *alloc)
|
||
|
{
|
||
|
return alloc->page_size;
|
||
|
}
|