| author | Kyle Sanderson <kyle.leet@gmail.com> |
| Tue May 20 20:33:50 2014 -0700 (2014-05-20) | |
| changeset 4374 | a7a9f550d4e6 |
| parent 2226 | d10b38524be3 |
| permissions | -rw-r--r-- |
| dvander@2226 | 1 |
#include "KePageAllocator.h" |
| dvander@2226 | 2 |
|
| dvander@2226 | 3 |
using namespace Knight; |
| dvander@2226 | 4 |
|
| dvander@2226 | 5 |
struct PageInfo |
| dvander@2226 | 6 |
{ |
| dvander@2226 | 7 |
PageInfo *next; |
| dvander@2226 | 8 |
void *base; |
| dvander@2226 | 9 |
}; |
| dvander@2226 | 10 |
|
| dvander@2226 | 11 |
class Knight::KePageAllocator |
| dvander@2226 | 12 |
{ |
| dvander@2226 | 13 |
public: |
| dvander@2226 | 14 |
size_t page_size; |
| dvander@2226 | 15 |
size_t page_granularity; |
| dvander@2226 | 16 |
PageInfo *free_pages; |
| dvander@2226 | 17 |
PageInfo *page_blocks; |
| dvander@2226 | 18 |
}; |
| dvander@2226 | 19 |
|
| dvander@2226 | 20 |
static void *ke_LumpPageAlloc(KePageAllocator *alloc) |
| dvander@2226 | 21 |
{ |
| dvander@2226 | 22 |
void *base; |
| dvander@2226 | 23 |
char *page; |
| dvander@2226 | 24 |
PageInfo *lump; |
| dvander@2226 | 25 |
size_t pagesInBlock; |
| dvander@2226 | 26 |
|
| dvander@2226 | 27 |
#if defined KE_PLATFORM_WINDOWS |
| dvander@2226 | 28 |
base = VirtualAlloc( |
| dvander@2226 | 29 |
NULL, |
| dvander@2226 | 30 |
alloc->page_granularity, |
| dvander@2226 | 31 |
MEM_COMMIT|MEM_RESERVE, |
| dvander@2226 | 32 |
PAGE_READWRITE); |
| dvander@2226 | 33 |
#elif defined KE_PLATFORM_POSIX |
| dvander@2226 | 34 |
base = valloc(alloc->page_granularity); |
| dvander@2226 | 35 |
#else |
| dvander@2226 | 36 |
#error "Unsupported platform" |
| dvander@2226 | 37 |
#endif |
| dvander@2226 | 38 |
|
| dvander@2226 | 39 |
if (base == NULL) |
| dvander@2226 | 40 |
{ |
| dvander@2226 | 41 |
return NULL; |
| dvander@2226 | 42 |
} |
| dvander@2226 | 43 |
|
| dvander@2226 | 44 |
lump = new PageInfo; |
| dvander@2226 | 45 |
lump->base = base; |
| dvander@2226 | 46 |
lump->next = alloc->page_blocks; |
| dvander@2226 | 47 |
alloc->page_blocks = lump->next; |
| dvander@2226 | 48 |
|
| dvander@2226 | 49 |
page = (char *)base + alloc->page_size; |
| dvander@2226 | 50 |
pagesInBlock = alloc->page_granularity / alloc->page_size; |
| dvander@2226 | 51 |
|
| dvander@2226 | 52 |
for (size_t i = 1; i < pagesInBlock; i++) |
| dvander@2226 | 53 |
{ |
| dvander@2226 | 54 |
lump = new PageInfo; |
| dvander@2226 | 55 |
lump->base = page; |
| dvander@2226 | 56 |
lump->next = alloc->free_pages; |
| dvander@2226 | 57 |
alloc->free_pages = lump; |
| dvander@2226 | 58 |
page += alloc->page_size; |
| dvander@2226 | 59 |
} |
| dvander@2226 | 60 |
|
| dvander@2226 | 61 |
return base; |
| dvander@2226 | 62 |
} |
| dvander@2226 | 63 |
|
| dvander@2226 | 64 |
KePageAllocator *Knight::KE_CreatePageAllocator() |
| dvander@2226 | 65 |
{ |
| dvander@2226 | 66 |
KePageAllocator *alloc; |
| dvander@2226 | 67 |
|
| dvander@2226 | 68 |
alloc = new KePageAllocator; |
| dvander@2226 | 69 |
|
| dvander@2226 | 70 |
#if defined KE_PLATFORM_WINDOWS |
| dvander@2226 | 71 |
SYSTEM_INFO info; |
| dvander@2226 | 72 |
|
| dvander@2226 | 73 |
GetSystemInfo(&info); |
| dvander@2226 | 74 |
alloc->page_size = info.dwPageSize; |
| dvander@2226 | 75 |
alloc->page_granularity = info.dwAllocationGranularity; |
| dvander@2226 | 76 |
#elif defined KE_PLATFORM_POSIX |
| dvander@2226 | 77 |
alloc->page_size = sysconf(_SC_PAGESIZE); |
| dvander@2226 | 78 |
alloc->page_granularity = alloc->page_size * 16; |
| dvander@2226 | 79 |
#else |
| dvander@2226 | 80 |
#error "Unsupported platform" |
| dvander@2226 | 81 |
#endif |
| dvander@2226 | 82 |
|
| dvander@2226 | 83 |
alloc->free_pages = NULL; |
| dvander@2226 | 84 |
alloc->page_blocks = NULL; |
| dvander@2226 | 85 |
|
| dvander@2226 | 86 |
return alloc; |
| dvander@2226 | 87 |
} |
| dvander@2226 | 88 |
|
| dvander@2226 | 89 |
void Knight::KE_DestroyPageAllocator(KePageAllocator *alloc) |
| dvander@2226 | 90 |
{ |
| dvander@2226 | 91 |
PageInfo *info, *next; |
| dvander@2226 | 92 |
|
| dvander@2226 | 93 |
info = alloc->page_blocks; |
| dvander@2226 | 94 |
while (info != NULL) |
| dvander@2226 | 95 |
{ |
| dvander@2226 | 96 |
next = info->next; |
| dvander@2226 | 97 |
#if defined KE_PLATFORM_WINDOWS |
| dvander@2226 | 98 |
VirtualFree(info->base, 0, MEM_RELEASE); |
| dvander@2226 | 99 |
#elif defined KE_PLATFORM_WINDOWS |
| dvander@2226 | 100 |
free(info->base); |
| dvander@2226 | 101 |
#else |
| dvander@2226 | 102 |
#error "Unsupported platform" |
| dvander@2226 | 103 |
#endif |
| dvander@2226 | 104 |
delete info; |
| dvander@2226 | 105 |
next = info; |
| dvander@2226 | 106 |
} |
| dvander@2226 | 107 |
|
| dvander@2226 | 108 |
info = alloc->free_pages; |
| dvander@2226 | 109 |
while (info != NULL) |
| dvander@2226 | 110 |
{ |
| dvander@2226 | 111 |
next = info->next; |
| dvander@2226 | 112 |
delete info; |
| dvander@2226 | 113 |
info = next; |
| dvander@2226 | 114 |
} |
| dvander@2226 | 115 |
} |
| dvander@2226 | 116 |
|
| dvander@2226 | 117 |
void *Knight::KE_PageAlloc(KePageAllocator *alloc) |
| dvander@2226 | 118 |
{ |
| dvander@2226 | 119 |
if (alloc->free_pages != NULL) |
| dvander@2226 | 120 |
{ |
| dvander@2226 | 121 |
void *base; |
| dvander@2226 | 122 |
PageInfo *info; |
| dvander@2226 | 123 |
|
| dvander@2226 | 124 |
info = alloc->free_pages; |
| dvander@2226 | 125 |
alloc->free_pages = info->next; |
| dvander@2226 | 126 |
base = info->base; |
| dvander@2226 | 127 |
delete info; |
| dvander@2226 | 128 |
|
| dvander@2226 | 129 |
return base; |
| dvander@2226 | 130 |
} |
| dvander@2226 | 131 |
|
| dvander@2226 | 132 |
return ke_LumpPageAlloc(alloc); |
| dvander@2226 | 133 |
} |
| dvander@2226 | 134 |
|
| dvander@2226 | 135 |
void Knight::KE_PageFree(KePageAllocator *alloc, void *page) |
| dvander@2226 | 136 |
{ |
| dvander@2226 | 137 |
PageInfo *info; |
| dvander@2226 | 138 |
|
| dvander@2226 | 139 |
info = new PageInfo; |
| dvander@2226 | 140 |
info->base = page; |
| dvander@2226 | 141 |
info->next = alloc->free_pages; |
| dvander@2226 | 142 |
alloc->free_pages = info->next; |
| dvander@2226 | 143 |
} |
| dvander@2226 | 144 |
|
| dvander@2226 | 145 |
size_t Knight::KE_PageSize(KePageAllocator *alloc) |
| dvander@2226 | 146 |
{ |
| dvander@2226 | 147 |
return alloc->page_size; |
| dvander@2226 | 148 |
} |