--- BasiliskII/src/Unix/main_unix.cpp 2004/01/12 15:29:25 1.58 +++ BasiliskII/src/Unix/main_unix.cpp 2006/02/27 07:24:58 1.72 @@ -1,7 +1,7 @@ /* * main_unix.cpp - Startup code for Unix * - * Basilisk II (C) 1997-2004 Christian Bauer + * Basilisk II (C) 1997-2005 Christian Bauer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,7 +24,14 @@ #include #include #include -#include + +#ifdef USE_SDL +# include +#endif + +#ifndef USE_SDL_VIDEO +# include +#endif #ifdef HAVE_PTHREADS # include @@ -116,11 +123,17 @@ int CPUType; bool CPUIs68060; int FPUType; bool TwentyFourBitAddressing; +bool ThirtyThreeBitAddressing = false; // Global variables -char *x_display_name = NULL; // X11 display name -Display *x_display = NULL; // X11 display handle +#ifndef USE_SDL_VIDEO +extern char *x_display_name; // X11 display name +extern Display *x_display; // X11 display handle +#ifdef X11_LOCK_TYPE +X11_LOCK_TYPE x_display_lock = X11_LOCK_INIT; // X11 display lock +#endif +#endif static uint8 last_xpram[XPRAM_SIZE]; // Buffer for monitoring XPRAM changes @@ -210,6 +223,38 @@ char *strdup(const char *s) /* + * Helpers to map memory that can be accessed from the Mac side + */ + +// NOTE: VM_MAP_33BIT is only used when compiling a 64-bit JIT on specific platforms +void *vm_acquire_mac(size_t size) +{ + void *m = vm_acquire(size, VM_MAP_DEFAULT | VM_MAP_33BIT); +#ifdef USE_33BIT_ADDRESSING + if (m == VM_MAP_FAILED) { + printf("WARNING: Cannot acquire memory in 33-bit address space (%s)\n", strerror(errno)); + ThirtyThreeBitAddressing = false; + m = vm_acquire(size); + } +#endif + return m; +} + +static int vm_acquire_mac_fixed(void *addr, size_t size) +{ + int ret = vm_acquire_fixed(addr, size, VM_MAP_DEFAULT | VM_MAP_33BIT); +#ifdef USE_33BIT_ADDRESSING + if (ret < 0) { + printf("WARNING: Cannot acquire fixed memory in 33-bit address space (%s)\n", strerror(errno)); + ThirtyThreeBitAddressing = false; + ret = vm_acquire_fixed(addr, size); + } +#endif + return ret; +} + + +/* * SIGSEGV handler */ @@ -258,9 +303,71 @@ static void sigsegv_dump_state(sigsegv_a #ifdef ENABLE_MON char *arg[4] = {"mon", "-m", "-r", NULL}; mon(3, arg); - QuitEmulator(); #endif + QuitEmulator(); +} + + +/* + * Update virtual clock and trigger interrupts if necessary + */ + +#ifdef USE_CPU_EMUL_SERVICES +static uint64 n_check_ticks = 0; +static uint64 emulated_ticks_start = 0; +static uint64 emulated_ticks_count = 0; +static int64 emulated_ticks_current = 0; +static int32 emulated_ticks_quantum = 1000; +int32 emulated_ticks = emulated_ticks_quantum; + +void cpu_do_check_ticks(void) +{ +#if DEBUG + n_check_ticks++; +#endif + + uint64 now; + static uint64 next = 0; + if (next == 0) + next = emulated_ticks_start = GetTicks_usec(); + + // Update total instructions count + if (emulated_ticks <= 0) { + emulated_ticks_current += (emulated_ticks_quantum - emulated_ticks); + // XXX: can you really have a machine fast enough to overflow + // a 63-bit m68k instruction counter within 16 ms? + if (emulated_ticks_current < 0) { + printf("WARNING: Overflowed 63-bit m68k instruction counter in less than 16 ms!\n"); + goto recalibrate_quantum; + } + } + + // Check for interrupt opportunity + now = GetTicks_usec(); + if (next < now) { + one_tick(); + do { + next += 16625; + } while (next < now); + emulated_ticks_count++; + + // Recalibrate 1000 Hz quantum every 10 ticks + static uint64 last = 0; + if (last == 0) + last = now; + else if (now - last > 166250) { + recalibrate_quantum: + emulated_ticks_quantum = ((uint64)emulated_ticks_current * 1000) / (now - last); + emulated_ticks_current = 0; + last = now; + } + } + + // Update countdown + if (emulated_ticks <= 0) + emulated_ticks += emulated_ticks_quantum; } +#endif /* @@ -300,10 +407,12 @@ int main(int argc, char **argv) for (int i=1; i 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 @@ -407,27 +539,33 @@ int main(int argc, char **argv) // Initialize VM system vm_init(); +#ifdef USE_33BIT_ADDRESSING + // Speculatively enables 33-bit addressing + ThirtyThreeBitAddressing = true; +#endif + #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; } @@ -450,17 +588,18 @@ int main(int argc, char **argv) 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(); @@ -475,8 +614,8 @@ int main(int argc, char **argv) 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)); @@ -597,6 +736,7 @@ int main(int argc, char **argv) sigaction(SIGINT, &sigint_sa, NULL); #endif +#ifndef USE_CPU_EMUL_SERVICES #if defined(HAVE_PTHREADS) // POSIX threads available, start 60Hz thread @@ -660,8 +800,9 @@ int main(int argc, char **argv) setitimer(ITIMER_REAL, &req, NULL); #endif +#endif -#ifdef HAVE_PTHREADS +#ifdef USE_PTHREADS_SERVICES // Start XPRAM watchdog thread memcpy(last_xpram, XPRAM, XPRAM_SIZE); xpram_thread_active = (pthread_create(&xpram_thread, NULL, xpram_func, NULL) == 0); @@ -690,7 +831,13 @@ void QuitEmulator(void) Exit680x0(); #endif -#if defined(HAVE_PTHREADS) +#if defined(USE_CPU_EMUL_SERVICES) + // Show statistics + uint64 emulated_ticks_end = GetTicks_usec(); + D(bug("%ld ticks in %ld usec = %f ticks/sec [%ld tick checks]\n", + (long)emulated_ticks_count, (long)(emulated_ticks_end - emulated_ticks_start), + emulated_ticks_count * 1000000.0 / (emulated_ticks_end - emulated_ticks_start), (long)n_check_ticks)); +#elif defined(USE_PTHREADS_SERVICES) // Stop 60Hz thread if (tick_thread_active) { tick_thread_cancel = true; @@ -709,7 +856,7 @@ void QuitEmulator(void) setitimer(ITIMER_REAL, &req, NULL); #endif -#ifdef HAVE_PTHREADS +#ifdef USE_PTHREADS_SERVICES // Stop XPRAM watchdog thread if (xpram_thread_active) { xpram_thread_cancel = true; @@ -725,11 +872,8 @@ void QuitEmulator(void) // 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; } @@ -757,8 +901,10 @@ void QuitEmulator(void) PrefsExit(); // Close X11 server connection +#ifndef USE_SDL_VIDEO if (x_display) XCloseDisplay(x_display); +#endif exit(0); } @@ -846,7 +992,7 @@ struct B2_mutex { pthread_mutexattr_init(&attr); // Initialize the mutex for priority inheritance -- // required for accurate timing. -#ifdef HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL +#if defined(HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL) && !defined(__CYGWIN__) pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT); #endif #if defined(HAVE_PTHREAD_MUTEXATTR_SETTYPE) && defined(PTHREAD_MUTEX_NORMAL) @@ -964,7 +1110,7 @@ static void xpram_watchdog(void) } } -#ifdef HAVE_PTHREADS +#ifdef USE_PTHREADS_SERVICES static void *xpram_func(void *arg) { while (!xpram_thread_cancel) { @@ -989,7 +1135,7 @@ static void one_second(void) SetInterruptFlag(INTFLAG_1HZ); TriggerInterrupt(); -#ifndef HAVE_PTHREADS +#ifndef USE_PTHREADS_SERVICES static int second_counter = 0; if (++second_counter > 60) { second_counter = 0; @@ -1006,9 +1152,13 @@ static void one_tick(...) one_second(); } -#ifndef HAVE_PTHREADS - // No threads available, perform video refresh and networking from here +#ifndef USE_PTHREADS_SERVICES + // Threads not used to trigger interrupts, perform video refresh from here VideoRefresh(); +#endif + +#ifndef HAVE_PTHREADS + // No threads available, perform networking from here SetInterruptFlag(INTFLAG_ETHER); #endif @@ -1019,7 +1169,7 @@ static void one_tick(...) } } -#ifdef HAVE_PTHREADS +#ifdef USE_PTHREADS_SERVICES static void *tick_func(void *arg) { uint64 start = GetTicks_usec(); @@ -1036,7 +1186,7 @@ static void *tick_func(void *arg) ticks++; } uint64 end = GetTicks_usec(); - D(bug("%Ld ticks in %Ld usec = %f ticks/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start))); + D(bug("%lld ticks in %lld usec = %f ticks/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start))); return NULL; } #endif @@ -1396,7 +1546,7 @@ void display_alert(int title_id, int pre void ErrorAlert(const char *text) { -#ifdef ENABLE_GTK +#if defined(ENABLE_GTK) && !defined(USE_SDL_VIDEO) if (PrefsFindBool("nogui") || x_display == NULL) { printf(GetString(STR_SHELL_ERROR_PREFIX), text); return; @@ -1415,7 +1565,7 @@ void ErrorAlert(const char *text) void WarningAlert(const char *text) { -#ifdef ENABLE_GTK +#if defined(ENABLE_GTK) && !defined(USE_SDL_VIDEO) if (PrefsFindBool("nogui") || x_display == NULL) { printf(GetString(STR_SHELL_WARNING_PREFIX), text); return;