int vm_release(void * addr, size_t size) { // Safety check: don't try to release memory that was not allocated if (addr == VM_MAP_FAILED) return 0; #ifdef HAVE_MACH_VM if (vm_deallocate(mach_task_self(), (vm_address_t)addr, size) != KERN_SUCCESS) return -1; #else #ifdef HAVE_MMAP_VM if (munmap((caddr_t)addr, size) != 0) return -1; #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; }
int vm_acquire_fixed(void * addr, size_t size, int options) { errno = 0; // Fixed mappings are required to be private if (options & VM_MAP_SHARED) return -1; #ifndef HAVE_VM_WRITE_WATCH if (options & VM_MAP_WRITE_WATCH) return -1; #endif #if defined(HAVE_MACH_VM) // vm_allocate() returns a zero-filled memory region kern_return_t ret_code = vm_allocate(mach_task_self(), (vm_address_t *)&addr, size, 0); if (ret_code != KERN_SUCCESS) { errno = vm_error(ret_code); return -1; } #elif defined(HAVE_MMAP_VM) int fd = zero_fd; int the_map_flags = translate_map_flags(options) | map_flags | MAP_FIXED; if (mmap((caddr_t)addr, size, VM_PAGE_DEFAULT, the_map_flags, fd, 0) == (void *)MAP_FAILED) return -1; #elif defined(HAVE_WIN32_VM) // Windows cannot allocate Low Memory if (addr == NULL) return -1; int alloc_type = MEM_RESERVE | MEM_COMMIT; if (options & VM_MAP_WRITE_WATCH) alloc_type |= MEM_WRITE_WATCH; // 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, alloc_type, PAGE_EXECUTE_READWRITE); if (ret_addr != req_addr) return -1; #else // Unsupported return -1; #endif // Explicitely protect the newly mapped region here because on some systems, // say MacOS X, mmap() doesn't honour the requested protection flags. if (vm_protect(addr, size, VM_PAGE_DEFAULT) != 0) return -1; return 0; }
static inline DWORD align_size_segment(LPVOID addr, DWORD size) { return size + ((vm_uintptr_t)addr - (vm_uintptr_t)align_addr_segment(addr)); }
static inline DWORD align_size_segment(LPVOID addr, DWORD size) { D(bug("%s\n", __func__)); return size + ((vm_uintptr_t)addr - (vm_uintptr_t)align_addr_segment(addr)); }