From eed73f3b01ac3ae40771c85f6603ae3e4d22914a Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sun, 7 Sep 2014 11:28:56 +0300 Subject: [PATCH] QEMU thread sync experiment: try spinlocks. --- events.cpp | 36 ++++++++++++- include/uae/ppc.h | 6 +++ newcpu.cpp | 24 +++------ ppc/ppc.cpp | 125 +++++++++++++++++++++++++++++++++++++++------- 4 files changed, 155 insertions(+), 36 deletions(-) diff --git a/events.cpp b/events.cpp index adc83386..e847b341 100644 --- a/events.cpp +++ b/events.cpp @@ -13,6 +13,11 @@ #include "options.h" #include "events.h" +#include "memory.h" +#include "newcpu.h" +#include "uae/ppc.h" + +static const int pissoff_nojit_value = 256 * CYCLE_UNIT; unsigned long int event_cycles, nextevent, currcycle; int is_syncline, is_syncline_end; @@ -62,14 +67,41 @@ void do_cycles_slow (unsigned long cycles_to_add) v = 0; } if (v < 0 && v2 < 0) { - pissoff = pissoff_value; +#ifdef WITH_PPC + if (regs.halted < 0) { + + uae_ppc_execute_quick(); + + } else { +#endif + if (currprefs.cachesize) + pissoff = pissoff_value; + else + pissoff = pissoff_nojit_value; +#ifdef WITH_PPC + } +#endif return; } } else if (is_syncline < 0) { int rpt = read_processor_time (); int v = rpt - is_syncline_end; if (v < 0) { - pissoff = pissoff_value; +#ifdef WITH_PPC + if (regs.halted < 0) { + + if (v < -vsynctimebase / 20) + uae_ppc_execute_quick(); + + } else { +#endif + if (currprefs.cachesize) + pissoff = pissoff_value; + else + pissoff = pissoff_nojit_value; +#ifdef WITH_PPC + } +#endif return; } } diff --git a/include/uae/ppc.h b/include/uae/ppc.h index caf3191c..cbdd8ccf 100644 --- a/include/uae/ppc.h +++ b/include/uae/ppc.h @@ -40,6 +40,12 @@ void uae_ppc_emulate(void); void uae_ppc_reset(bool hardreset); void uae_ppc_hsync_handler(void); void uae_ppc_wakeup(void); + +void uae_ppc_execute_quick(void); +void uae_ppc_spinlock_reset(void); +void uae_ppc_spinlock_get(void); +void uae_ppc_spinlock_release(void); + /** * Pauses the PPC emulation (for some implementations). Currently triggers * a simple pause implementation intended only for debugging. diff --git a/newcpu.cpp b/newcpu.cpp index b9fc120e..3cf5763f 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -3155,24 +3155,20 @@ static void do_trace (void) #ifdef WITH_PPC static void uae_ppc_poll_check(void) { - static int checkcnt; - - checkcnt--; - if (checkcnt > 0) - return; uae_ppc_poll_queue(); - checkcnt = 128; - return; } #endif static bool haltloop(void) { #ifdef WITH_PPC - bool ppc_main_thread = false; + int lastintr = -1; // m68k stopped? Move PPC emulator to main thread. if (regs.halted < 0) { - ppc_main_thread = uae_ppc_to_main_thread(); + uae_ppc_to_main_thread(); + uae_ppc_spinlock_reset(); + uae_ppc_spinlock_get(); + write_log(_T("Entered m68k haltloop with PPC active\n")); } #endif @@ -3187,21 +3183,15 @@ static bool haltloop(void) prevvpos = 1; x_do_cycles(8 * CYCLE_UNIT); } else { - x_do_cycles(16 * CYCLE_UNIT); + x_do_cycles(32 * CYCLE_UNIT); } if (regs.spcflags & SPCFLAG_COPPER) do_copper(); #ifdef WITH_PPC - if (ppc_main_thread && regs.halted < 0) + if (regs.halted < 0) uae_ppc_emulate(); - else - uae_ppc_poll_check(); - if (ppc_state) { - int intr = intlev(); - ppc_interrupt(intr); - } #endif if (regs.spcflags) { diff --git a/ppc/ppc.cpp b/ppc/ppc.cpp index 77f41cca..0f3efd84 100644 --- a/ppc/ppc.cpp +++ b/ppc/ppc.cpp @@ -1,3 +1,4 @@ + #include "sysconfig.h" #include "sysdeps.h" @@ -12,6 +13,9 @@ #include "uae/ppc.h" +#define PPC_DEBUG_ADDR_FROM 0xf00000 +#define PPC_DEBUG_ADDR_TO 0xf40000 + #ifdef WITH_PEARPC_CPU #include "pearpc/cpu/cpu.h" #include "pearpc/io/io.h" @@ -23,6 +27,29 @@ #define TRACE(format, ...) write_log(_T("PPC: ---------------- ") format, ## __VA_ARGS__) + +volatile uae_u32 ppc_spinlock; + +void uae_ppc_spinlock_get(void) +{ +#ifdef _WIN32 + int exchange = 1, compare = 0; + while (true) + { + if(InterlockedCompareExchange(&ppc_spinlock, exchange, compare) == 0) + break; + } +#endif +} +void uae_ppc_spinlock_release(void) +{ + ppc_spinlock = 0; +} +void uae_ppc_spinlock_reset(void) +{ + uae_ppc_spinlock_release(); +} + volatile int ppc_state; static volatile bool ppc_thread_running; @@ -32,6 +59,8 @@ int ppc_cycle_count; static volatile bool ppc_access; static volatile int ppc_cpu_lock_state; static bool ppc_main_thread; +static bool ppc_io_pipe; +static bool ppc_use_spinlock; static bool ppc_init_done; static int ppc_implementation; @@ -272,6 +301,9 @@ static void *ppc_thread(void *v) uae_u32 v = read_comm_pipe_u32_blocking(&ppcrequests); if (v == 0xffffffff) break; + uae_ppc_spinlock_reset(); + ppc_io_pipe = true; + ppc_use_spinlock = false; uae_ppc_cpu_reset(); g_ppc_cpu_run_continuous(); if (ppc_state == PPC_STATE_ACTIVE || ppc_state == PPC_STATE_SLEEP) @@ -288,9 +320,12 @@ bool uae_ppc_to_main_thread(void) { TRACE(_T("uae_ppc_to_main_thread\n")); - // QEMU: not yet supported - if (ppc_implementation == PPC_IMPLEMENTATION_QEMU) - return false; + // QEMU: keep using thread + if (ppc_implementation == PPC_IMPLEMENTATION_QEMU) { + ppc_io_pipe = false; + ppc_use_spinlock = true; + return true; + } if (ppc_thread_running) { write_log(_T("PPC: transferring PPC emulation to main thread.\n")); @@ -304,18 +339,40 @@ bool uae_ppc_to_main_thread(void) } ppc_state = PPC_STATE_ACTIVE; ppc_main_thread = true; + ppc_io_pipe = false; return true; } +void uae_ppc_execute_quick(void) +{ + uae_ppc_spinlock_release(); + sleep_millis(1); + uae_ppc_spinlock_get(); +} + void uae_ppc_emulate(void) { + if (ppc_implementation == PPC_IMPLEMENTATION_QEMU) + return; + + ppc_interrupt(intlev()); + //TRACE(_T("uae_ppc_emulate\n")); if (ppc_state == PPC_STATE_ACTIVE || ppc_state == PPC_STATE_SLEEP) g_ppc_cpu_run_single(10); } +static bool ppc_safe_addr(uaecptr addr) +{ + if (addr >= 0x08000000 && addr < 0x10000000) + return true; + return false; +} + bool uae_ppc_poll_queue(void) { + if (!ppc_io_pipe) + return true; // ppc locked? if (ppc_cpu_lock_state < 0) return false; @@ -394,9 +451,10 @@ bool uae_ppc_direct_physical_memory_handle(uint32_t addr, uint8_t *&ptr) bool UAECALL uae_ppc_io_mem_write(uint32_t addr, uint32_t data, int size) { + bool valid = false; while (ppc_thread_running && ppc_cpu_lock_state < 0 && ppc_state); - if (ppc_thread_running && !valid_address(addr, size)) { + if (ppc_io_pipe && !valid_address(addr, size)) { write_comm_pipe_u32(&ppcquery, addr, 0); write_comm_pipe_u32(&ppcquery, size | 0x80, 0); write_comm_pipe_u32(&ppcquery, data, 1); @@ -411,10 +469,16 @@ bool UAECALL uae_ppc_io_mem_write(uint32_t addr, uint32_t data, int size) return true; } #if PPC_ACCESS_LOG > 0 - if (!ppc_thread_running && !valid_address(addr, size)) { - write_log(_T("PPC io write %08x = %08x %d\n"), addr, data, size); + if (!ppc_io_pipe && !valid_address(addr, size)) { + if (addr >= PPC_DEBUG_ADDR_FROM && addr < PPC_DEBUG_ADDR_TO) + write_log(_T("PPC io write %08x = %08x %d\n"), addr, data, size); } #endif + if (ppc_use_spinlock) { + valid = valid_address(addr, size) != 0; + if (!valid) + uae_ppc_spinlock_get(); + } switch (size) { case 4: @@ -426,9 +490,13 @@ bool UAECALL uae_ppc_io_mem_write(uint32_t addr, uint32_t data, int size) case 1: put_byte(addr, data); break; - default: - write_log(_T("unknown ppc write %d %08x\n"), addr, size); - return false; + } + if (ppc_use_spinlock && !valid) { + if (addr == 0xdff09c || addr == 0xdff09a) { + int lev = intlev(); + ppc_interrupt(lev); + } + uae_ppc_spinlock_release(); } #if PPC_ACCESS_LOG > 2 write_log(_T("PPC mem write %08x = %08x %d\n"), addr, data, size); @@ -439,10 +507,11 @@ bool UAECALL uae_ppc_io_mem_write(uint32_t addr, uint32_t data, int size) bool UAECALL uae_ppc_io_mem_read(uint32_t addr, uint32_t *data, int size) { uint32_t v; + bool valid = false; while (ppc_thread_running && ppc_cpu_lock_state < 0 && ppc_state); - if (ppc_thread_running && !valid_address(addr, size)) { + if (ppc_io_pipe && !valid_address(addr, size)) { write_comm_pipe_u32(&ppcquery, addr, 0); write_comm_pipe_u32(&ppcquery, size, 1); v = read_comm_pipe_u32_blocking(&ppcreply); @@ -453,6 +522,12 @@ bool UAECALL uae_ppc_io_mem_read(uint32_t addr, uint32_t *data, int size) *data = v; return true; } + + if (ppc_use_spinlock) { + valid = valid_address(addr, size) != 0; + if (!valid) + uae_ppc_spinlock_get(); + } switch (size) { case 4: @@ -464,15 +539,15 @@ bool UAECALL uae_ppc_io_mem_read(uint32_t addr, uint32_t *data, int size) case 1: v = get_byte(addr); break; - default: - write_log(_T("unknown ppc read %d %08x\n"), addr, size); - return false; } *data = v; + if (ppc_use_spinlock && !valid) + uae_ppc_spinlock_release(); #if PPC_ACCESS_LOG > 0 - if (!ppc_thread_running && !valid_address(addr, size)) { - write_log(_T("PPC io read %08x=%08x %d\n"), addr, v, size); + if (!ppc_io_pipe && !valid_address(addr, size)) { + if (addr >= PPC_DEBUG_ADDR_FROM && addr < PPC_DEBUG_ADDR_TO) + write_log(_T("PPC io read %08x=%08x %d\n"), addr, v, size); } #endif #if PPC_ACCESS_LOG > 2 @@ -483,9 +558,10 @@ bool UAECALL uae_ppc_io_mem_read(uint32_t addr, uint32_t *data, int size) bool UAECALL uae_ppc_io_mem_write64(uint32_t addr, uint64_t data) { + bool valid = false; while (ppc_thread_running && ppc_cpu_lock_state < 0 && ppc_state); - if (ppc_thread_running && !valid_address(addr, 8)) { + if (ppc_io_pipe && !valid_address(addr, 8)) { #if PPC_ACCESS_LOG > 0 write_log(_T("PPC io write64 %08x = %08llx\n"), addr, (unsigned long long) data); #endif @@ -500,8 +576,15 @@ bool UAECALL uae_ppc_io_mem_write64(uint32_t addr, uint64_t data) #endif return true; } + if (ppc_use_spinlock) { + valid = valid_address(addr, 8) != 0; + if (!valid) + uae_ppc_spinlock_get(); + } put_long(addr + 0, data >> 32); put_long(addr + 4, data & 0xffffffff); + if (ppc_use_spinlock && !valid) + uae_ppc_spinlock_release(); #if PPC_ACCESS_LOG > 2 write_log(_T("PPC mem write64 %08x = %08llx\n"), addr, data); #endif @@ -510,11 +593,12 @@ bool UAECALL uae_ppc_io_mem_write64(uint32_t addr, uint64_t data) bool UAECALL uae_ppc_io_mem_read64(uint32_t addr, uint64_t *data) { + bool valid = false; uint32_t v1, v2; while (ppc_thread_running && ppc_cpu_lock_state < 0 && ppc_state); - if (ppc_thread_running && !valid_address(addr, 8)) { + if (ppc_io_pipe && !valid_address(addr, 8)) { write_comm_pipe_u32(&ppcquery, addr, 0); write_comm_pipe_u32(&ppcquery, 8, 0); v1 = read_comm_pipe_u32_blocking(&ppcreply); @@ -525,9 +609,16 @@ bool UAECALL uae_ppc_io_mem_read64(uint32_t addr, uint64_t *data) #endif return true; } + if (ppc_use_spinlock) { + valid = valid_address(addr, 8) != 0; + if (!valid) + uae_ppc_spinlock_get(); + } v1 = get_long(addr + 0); v2 = get_long(addr + 4); *data = ((uint64_t)v1 << 32) | v2; + if (ppc_use_spinlock && !valid) + uae_ppc_spinlock_release(); #if PPC_ACCESS_LOG > 2 write_log(_T("PPC mem read64 %08x = %08llx\n"), addr, *data); #endif -- 2.47.3