Windows memory allocators

This commit is contained in:
gbeauche 2004-11-13 23:39:58 +00:00
parent 7533cac203
commit 347f7ce77b

View File

@ -27,7 +27,11 @@
#include <fcntl.h>
#endif
// TODO: Win32 VMs ?
#ifdef HAVE_WIN32_VM
#define WIN32_LEAN_AND_MEAN /* avoid including junk */
#include <windows.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -173,6 +177,40 @@ static int translate_map_flags(int vm_flags)
}
#endif
/* Align ADDR and SIZE to 64K boundaries. */
#ifdef HAVE_WIN32_VM
static inline LPVOID align_addr_segment(LPVOID addr)
{
return (LPVOID)(((DWORD)addr) & -65536);
}
static inline DWORD align_size_segment(LPVOID addr, DWORD size)
{
return size + ((DWORD)addr - (DWORD)align_addr_segment(addr));
}
#endif
/* Translate generic VM prot flags to host values. */
#ifdef HAVE_WIN32_VM
static int translate_prot_flags(int prot_flags)
{
int prot = PAGE_READWRITE;
if (prot_flags == (VM_PAGE_EXECUTE | VM_PAGE_READ | VM_PAGE_WRITE))
prot = PAGE_EXECUTE_READWRITE;
else if (prot_flags == (VM_PAGE_EXECUTE | VM_PAGE_READ))
prot = PAGE_EXECUTE_READ;
else if (prot_flags == (VM_PAGE_READ | VM_PAGE_WRITE))
prot = PAGE_READWRITE;
else if (prot_flags == VM_PAGE_READ)
prot = PAGE_READONLY;
else if (prot_flags == 0)
prot = PAGE_NOACCESS;
return prot;
}
#endif
/* Initialize the VM system. Returns 0 if successful, -1 for errors. */
int vm_init(void)
@ -262,6 +300,14 @@ void * vm_acquire(size_t size, int options)
close(fd);
}
#endif
#else
#ifdef HAVE_WIN32_VM
if ((addr = VirtualAlloc(NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE)) == NULL)
return VM_MAP_FAILED;
// Zero newly allocated memory
if (memset(addr, 0, size) != addr)
return VM_MAP_FAILED;
#else
if ((addr = calloc(size, 1)) == 0)
return VM_MAP_FAILED;
@ -269,6 +315,7 @@ void * vm_acquire(size_t size, int options)
// Omit changes for protections because they are not supported in this mode
return addr;
#endif
#endif
#endif
// Explicitely protect the newly mapped region here because on some systems,
@ -302,10 +349,27 @@ int vm_acquire_fixed(void * addr, size_t size, int options)
// Since I don't know the standard behavior of mmap(), zero-fill here
if (memset(addr, 0, size) != addr)
return -1;
#else
#ifdef HAVE_WIN32_VM
// Windows cannot allocate Low Memory
if (addr == NULL)
return -1;
// Allocate a possibly offset region to align on 64K boundaries
LPVOID req_addr = align_addr_segment(addr);
DWORD req_size = align_size_segment(addr, size);
LPVOID ret_addr = VirtualAlloc(req_addr, req_size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (ret_addr != req_addr)
return -1;
// Zero newly allocated memory
if (memset(addr, 0, size) != addr)
return -1;
#else
// Unsupported
return -1;
#endif
#endif
#endif
// Explicitely protect the newly mapped region here because on some systems,
@ -347,9 +411,14 @@ int vm_release(void * addr, size_t size)
return -1;
}
#endif
#else
#ifdef HAVE_WIN32_VM
if (VirtualFree(align_addr_segment(addr), 0, MEM_RELEASE) == 0)
return -1;
#else
free(addr);
#endif
#endif
#endif
return 0;
@ -367,11 +436,17 @@ int vm_protect(void * addr, size_t size, int prot)
#ifdef HAVE_MMAP_VM
int ret_code = mprotect((caddr_t)addr, size, prot);
return ret_code == 0 ? 0 : -1;
#else
#ifdef HAVE_WIN32_VM
DWORD old_prot;
int ret_code = VirtualProtect(addr, size, translate_prot_flags(prot), &old_prot);
return ret_code != 0 ? 0 : -1;
#else
// Unsupported
return -1;
#endif
#endif
#endif
}
#ifdef CONFIGURE_TEST_VM_MAP
@ -384,7 +459,11 @@ int main(void)
vm_init();
#define page_align(address) ((char *)((unsigned long)(address) & -page_size))
#ifdef _WIN32
const unsigned long page_size = 4096;
#else
unsigned long page_size = getpagesize();
#endif
const int area_size = 6 * page_size;
volatile char * area = (volatile char *) vm_acquire(area_size);