diff options
Diffstat (limited to 'src/osd/windows/winmisc.c')
-rw-r--r-- | src/osd/windows/winmisc.c | 86 |
1 files changed, 85 insertions, 1 deletions
diff --git a/src/osd/windows/winmisc.c b/src/osd/windows/winmisc.c index f1aa4d0668e..90c8dad9e9e 100644 --- a/src/osd/windows/winmisc.c +++ b/src/osd/windows/winmisc.c @@ -45,7 +45,7 @@ #include <tchar.h> // MAME headers -#include "osdcore.h" +#include "emucore.h" // MAMEOS headers #include "winutf8.h" @@ -53,6 +53,90 @@ //============================================================ +// MACROS +//============================================================ + +// presumed size of a page of memory +#define PAGE_SIZE 4096 + +// allocations this size and larger get guard pages +#define GUARD_PAGE_THRESH 32 + +// align allocations to start or end of the page? +#define GUARD_ALIGN_START 0 + + + +//============================================================ +// osd_malloc +//============================================================ + +void *osd_malloc(size_t size) +{ +#ifndef MALLOC_DEBUG + return HeapAlloc(GetProcessHeap(), 0, size); +#else + // add in space for the base pointer + size += sizeof(size_t); + + // small items just come from the heap + void *result; + if (size < GUARD_PAGE_THRESH) + result = HeapAlloc(GetProcessHeap(), 0, size); + + // large items get guard pages + else + { + // round the size up to a page boundary + size_t rounded_size = ((size + sizeof(void *) + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE; + + // reserve that much memory, plus two guard pages + void *page_base = VirtualAlloc(NULL, rounded_size + 2 * PAGE_SIZE, MEM_RESERVE, PAGE_NOACCESS); + if (page_base == NULL) + return NULL; + + // now allow access to everything but the first and last pages + page_base = VirtualAlloc(reinterpret_cast<UINT8 *>(page_base) + PAGE_SIZE, rounded_size, MEM_COMMIT, PAGE_READWRITE); + if (page_base == NULL) + return NULL; + + // work backwards from the page base to get to the block base + result = GUARD_ALIGN_START ? page_base : (reinterpret_cast<UINT8 *>(page_base) + rounded_size - size); + } + + // store the page_base at the start + *reinterpret_cast<size_t *>(result) = size; + return reinterpret_cast<UINT8 *>(result) + sizeof(size_t); +#endif +} + + +//============================================================ +// osd_free +//============================================================ + +void osd_free(void *ptr) +{ +#ifndef MALLOC_DEBUG + HeapFree(GetProcessHeap(), 0, ptr); +#else + size_t size = reinterpret_cast<size_t *>(ptr)[-1]; + + // small items just get freed + if (size < GUARD_PAGE_THRESH) + HeapFree(GetProcessHeap(), 0, ptr); + + // large items need more care + else + { + FPTR page_base = (reinterpret_cast<FPTR>(ptr) - sizeof(size_t)) & ~(PAGE_SIZE - 1); + VirtualFree(reinterpret_cast<void *>(page_base - PAGE_SIZE), 0, MEM_RELEASE); + } +#endif +} + + +//============================================================ // osd_alloc_executable //============================================================ |