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