From c6d88f213c6939467dd6c9e85dca9a19cb20760e Mon Sep 17 00:00:00 2001 From: asvitkine <> Date: Tue, 11 Aug 2009 07:43:46 +0000 Subject: [PATCH] [Michael Schmitt] SheepShaver includes the C errno string in many error messages. One case is when it calls the memory allocation routines in the Basilisk II vm_alloc.cpp program. This works when the memory allocation routine uses functions that set errno (such as mmap or malloc). For example, running SheepShaver on a Linux hosts produces meaningful error messages. The problem is that when run on an OS X host, the memory allocation uses Mach routines such as vm_allocate, which do not set errno. So when SheepShaver reported the error, it used a stale value of errno, which happened to be 17. The result was an extremely misleading error message: "Cannot map RAM: File already exists". The fix is to change vm_alloc so that it translates Mac return codes into POSIX errno values. It also initializes errno to 0 at the start of the memory allocation routine, so that no matter what path it takes, it won't return a stale value. --- BasiliskII/src/Unix/vm_alloc.cpp | 33 ++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/BasiliskII/src/Unix/vm_alloc.cpp b/BasiliskII/src/Unix/vm_alloc.cpp index a5a94cbb..a4195a5c 100644 --- a/BasiliskII/src/Unix/vm_alloc.cpp +++ b/BasiliskII/src/Unix/vm_alloc.cpp @@ -32,6 +32,7 @@ #include #endif +#include #include #include #include @@ -151,6 +152,24 @@ static int translate_prot_flags(int prot_flags) } #endif +/* Translate Mach return codes to POSIX errno values. */ +#ifdef HAVE_MACH_VM +static int vm_error(kern_return_t ret_code) +{ + switch (ret_code) { + case KERN_SUCCESS: + return 0; + case KERN_INVALID_ADDRESS: + case KERN_NO_SPACE: + return ENOMEM; + case KERN_PROTECTION_FAILURE: + return EACCES; + default: + return EINVAL; + } +} +#endif + /* Initialize the VM system. Returns 0 if successful, -1 for errors. */ int vm_init(void) @@ -186,6 +205,8 @@ void vm_exit(void) void * vm_acquire(size_t size, int options) { void * addr; + + errno = 0; // VM_MAP_FIXED are to be used with vm_acquire_fixed() only if (options & VM_MAP_FIXED) @@ -198,8 +219,11 @@ void * vm_acquire(size_t size, int options) #ifdef HAVE_MACH_VM // vm_allocate() returns a zero-filled memory region - if (vm_allocate(mach_task_self(), (vm_address_t *)&addr, size, TRUE) != KERN_SUCCESS) + kern_return_t ret_code = vm_allocate(mach_task_self(), (vm_address_t *)&addr, size, TRUE); + if (ret_code != KERN_SUCCESS) { + errno = vm_error(ret_code); return VM_MAP_FAILED; + } #else #ifdef HAVE_MMAP_VM int fd = zero_fd; @@ -244,6 +268,8 @@ void * vm_acquire(size_t size, int options) 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; @@ -255,8 +281,11 @@ int vm_acquire_fixed(void * addr, size_t size, int options) #ifdef HAVE_MACH_VM // vm_allocate() returns a zero-filled memory region - if (vm_allocate(mach_task_self(), (vm_address_t *)&addr, size, 0) != KERN_SUCCESS) + 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; + } #else #ifdef HAVE_MMAP_VM int fd = zero_fd;