--- BasiliskII/src/MacOSX/main_macosx.mm 2005/01/30 21:42:13 1.13 +++ BasiliskII/src/MacOSX/main_macosx.mm 2007/12/30 08:47:34 1.18 @@ -1,5 +1,5 @@ /* - * $Id: main_macosx.mm,v 1.13 2005/01/30 21:42:13 gbeauche Exp $ + * $Id: main_macosx.mm,v 1.18 2007/12/30 08:47:34 gbeauche Exp $ * * main_macosx.mm - Startup code for MacOS X * Based (in a small way) on the default main.m, @@ -21,6 +21,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#import +#undef check + #define PTHREADS // Why is this here? #include "sysdeps.h" @@ -50,7 +54,7 @@ using std::string; #include "xpram.h" #if USE_JIT -extern void flush_icache_range(uint32 start, uint32 size); // from compemu_support.cpp +extern void flush_icache_range(uint8 *start, uint32 size); // from compemu_support.cpp #endif #ifdef ENABLE_MON @@ -61,8 +65,6 @@ extern void flush_icache_range(uint32 st #include "debug.h" -#import - #include "main_macosx.h" // To bridge between main() and misc. classes @@ -108,16 +110,32 @@ static bool lm_area_mapped = false; // F /* + * Helpers to map memory that can be accessed from the Mac side + */ + +// NOTE: VM_MAP_32BIT is only used when compiling a 64-bit JIT on specific platforms +void *vm_acquire_mac(size_t size) +{ + return vm_acquire(size, VM_MAP_DEFAULT | VM_MAP_32BIT); +} + +static int vm_acquire_mac_fixed(void *addr, size_t size) +{ + return vm_acquire_fixed(addr, size, VM_MAP_DEFAULT | VM_MAP_32BIT); +} + + +/* * SIGSEGV handler */ -static sigsegv_return_t sigsegv_handler(sigsegv_address_t fault_address, - sigsegv_address_t fault_instruction) +static sigsegv_return_t sigsegv_handler(sigsegv_info_t *sip) { + const uintptr fault_address = (uintptr)sigsegv_get_fault_address(sip); #if ENABLE_VOSF // Handle screen fault - extern bool Screen_fault_handler(sigsegv_address_t, sigsegv_address_t); - if (Screen_fault_handler(fault_address, fault_instruction)) + extern bool Screen_fault_handler(sigsegv_info_t *sip); + if (Screen_fault_handler(sip)) return SIGSEGV_RETURN_SUCCESS; #endif @@ -139,10 +157,12 @@ static sigsegv_return_t sigsegv_handler( * Dump state when everything went wrong after a SEGV */ -static void sigsegv_dump_state(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction) +static void sigsegv_dump_state(sigsegv_info_t *sip) { + const sigsegv_address_t fault_address = sigsegv_get_fault_address(sip); + const sigsegv_address_t fault_instruction = sigsegv_get_fault_instruction_address(sip); fprintf(stderr, "Caught SIGSEGV at address %p", fault_address); - if (fault_instruction != SIGSEGV_INVALID_PC) + if (fault_instruction != SIGSEGV_INVALID_ADDRESS) fprintf(stderr, " [IP=%p]", fault_instruction); fprintf(stderr, "\n"); uaecptr nextpc; @@ -156,8 +176,8 @@ static void sigsegv_dump_state(sigsegv_a #ifdef ENABLE_MON char *arg[4] = {"mon", "-m", "-r", NULL}; mon(3, arg); - QuitEmulator(); #endif + QuitEmulator(); } @@ -258,6 +278,8 @@ bool InitEmulator (void) WarningAlert(GetString(STR_SMALL_RAM_WARN)); RAMSize = 1024*1024; } + if (RAMSize > 1023*1024*1024) // Cap to 1023MB (APD crashes at 1GB) + RAMSize = 1023*1024*1024; #if REAL_ADDRESSING || DIRECT_ADDRESSING RAMSize = RAMSize & -getpagesize(); // Round down to page boundary @@ -269,24 +291,25 @@ bool InitEmulator (void) #if REAL_ADDRESSING // Flag: RAM and ROM are contigously allocated from address 0 bool memory_mapped_from_zero = false; - - // Under Solaris/SPARC and NetBSD/m68k, Basilisk II is known to crash - // when trying to map a too big chunk of memory starting at address 0 -#if defined(OS_solaris) || defined(OS_netbsd) || defined(PAGEZERO_HACK) - const bool can_map_all_memory = false; -#else + + // Make sure to map RAM & ROM at address 0 only on platforms that + // supports linker scripts to relocate the Basilisk II executable + // above 0x70000000 +#if HAVE_LINKER_SCRIPT const bool can_map_all_memory = true; +#else + const bool can_map_all_memory = false; #endif // Try to allocate all memory from 0x0000, if it is not known to crash - if (can_map_all_memory && (vm_acquire_fixed(0, RAMSize + 0x100000) == 0)) { + if (can_map_all_memory && (vm_acquire_mac_fixed(0, RAMSize + 0x100000) == 0)) { D(bug("Could allocate RAM and ROM from 0x0000\n")); memory_mapped_from_zero = true; } - + #ifndef PAGEZERO_HACK // Otherwise, just create the Low Memory area (0x0000..0x2000) - else if (vm_acquire_fixed(0, 0x2000) == 0) { + else if (vm_acquire_mac_fixed(0, 0x2000) == 0) { D(bug("Could allocate the Low Memory globals\n")); lm_area_mapped = true; } @@ -311,17 +334,18 @@ bool InitEmulator (void) else #endif { - RAMBaseHost = (uint8 *)vm_acquire(RAMSize); - ROMBaseHost = (uint8 *)vm_acquire(0x100000); - if (RAMBaseHost == VM_MAP_FAILED || ROMBaseHost == VM_MAP_FAILED) { + uint8 *ram_rom_area = (uint8 *)vm_acquire_mac(RAMSize + 0x100000); + if (ram_rom_area == VM_MAP_FAILED) { ErrorAlert(STR_NO_MEM_ERR); QuitEmulator(); } + RAMBaseHost = ram_rom_area; + ROMBaseHost = RAMBaseHost + RAMSize; } #if USE_SCRATCHMEM_SUBTERFUGE // Allocate scratch memory - ScratchMem = (uint8 *)vm_acquire(SCRATCH_MEM_SIZE); + ScratchMem = (uint8 *)vm_acquire_mac(SCRATCH_MEM_SIZE); if (ScratchMem == VM_MAP_FAILED) { ErrorAlert(STR_NO_MEM_ERR); QuitEmulator(); @@ -336,8 +360,8 @@ bool InitEmulator (void) ROMBaseMac = Host2MacAddr(ROMBaseHost); #endif #if REAL_ADDRESSING - RAMBaseMac = (uint32)RAMBaseHost; - ROMBaseMac = (uint32)ROMBaseHost; + RAMBaseMac = Host2MacAddr(RAMBaseHost); + ROMBaseMac = Host2MacAddr(ROMBaseHost); #endif D(bug("Mac RAM starts at %p (%08x)\n", RAMBaseHost, RAMBaseMac)); D(bug("Mac ROM starts at %p (%08x)\n", ROMBaseHost, ROMBaseMac)); @@ -405,11 +429,8 @@ void QuitEmuNoExit() // Free ROM/RAM areas if (RAMBaseHost != VM_MAP_FAILED) { - vm_release(RAMBaseHost, RAMSize); + vm_release(RAMBaseHost, RAMSize + 0x100000); RAMBaseHost = NULL; - } - if (ROMBaseHost != VM_MAP_FAILED) { - vm_release(ROMBaseHost, 0x100000); ROMBaseHost = NULL; } @@ -439,9 +460,6 @@ void QuitEmuNoExit() void QuitEmulator(void) { - extern NSApplication *NSApp; - - QuitEmuNoExit(); // Stop run loop? @@ -460,7 +478,7 @@ void FlushCodeCache(void *start, uint32 { #if USE_JIT if (UseJIT) - flush_icache_range((uintptr)start, size); + flush_icache_range((uint8 *)start, size); #endif } @@ -483,6 +501,39 @@ static void sigint_handler(...) #endif +#ifdef HAVE_PTHREADS +/* + * Pthread configuration + */ + +void Set_pthread_attr(pthread_attr_t *attr, int priority) +{ + pthread_attr_init(attr); +#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) + // Some of these only work for superuser + if (geteuid() == 0) { + pthread_attr_setinheritsched(attr, PTHREAD_EXPLICIT_SCHED); + pthread_attr_setschedpolicy(attr, SCHED_FIFO); + struct sched_param fifo_param; + fifo_param.sched_priority = ((sched_get_priority_min(SCHED_FIFO) + + sched_get_priority_max(SCHED_FIFO)) + / 2 + priority); + pthread_attr_setschedparam(attr, &fifo_param); + } + if (pthread_attr_setscope(attr, PTHREAD_SCOPE_SYSTEM) != 0) { +#ifdef PTHREAD_SCOPE_BOUND_NP + // If system scope is not available (eg. we're not running + // with CAP_SCHED_MGT capability on an SGI box), try bound + // scope. It exposes pthread scheduling to the kernel, + // without setting realtime priority. + pthread_attr_setscope(attr, PTHREAD_SCOPE_BOUND_NP); +#endif + } +#endif +} +#endif // HAVE_PTHREADS + + /* * Mutexes */