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