diff --git a/desmume/src/NDSSystem.cpp b/desmume/src/NDSSystem.cpp index 995d880f0..a9953ae17 100644 --- a/desmume/src/NDSSystem.cpp +++ b/desmume/src/NDSSystem.cpp @@ -55,6 +55,10 @@ #include "SPU.h" #include "wifi.h" +#ifdef GDB_STUB +#include "gdbstub.h" +#endif + //int xxctr=0; //#define LOG_ARM9 //#define LOG_ARM7 @@ -1828,6 +1832,10 @@ void NDS_debug_step() template void NDS_exec(s32 nb) { + #ifdef GDB_STUB + gdbstub_mutex_lock(); + #endif + LagFrameFlag=1; sequencer.nds_vblankEnded = false; @@ -1860,7 +1868,13 @@ void NDS_exec(s32 nb) while((NDS_ARM9.stalled || NDS_ARM7.stalled) && execute) { + #ifdef GDB_STUB + gdbstub_mutex_unlock(); + #endif driver->EMU_DebugIdleUpdate(); + #ifdef GDB_STUB + gdbstub_mutex_lock(); + #endif nds_debug_continuing[0] = nds_debug_continuing[1] = true; } @@ -1961,6 +1975,10 @@ void NDS_exec(s32 nb) DEBUG_Notify.NextFrame(); if (cheats) cheats->process(); + + #ifdef GDB_STUB + gdbstub_mutex_unlock(); + #endif } template static void execHardware_interrupts_core() diff --git a/desmume/src/cli/main.cpp b/desmume/src/cli/main.cpp index acd6f215a..4571f9862 100644 --- a/desmume/src/cli/main.cpp +++ b/desmume/src/cli/main.cpp @@ -596,6 +596,8 @@ int main(int argc, char ** argv) { driver = new BaseDriver(); #ifdef GDB_STUB + gdbstub_mutex_init(); + /* * Activate the GDB stubs * This has to come after NDS_Init() where the CPUs are set up. @@ -826,6 +828,8 @@ int main(int argc, char ** argv) { destroyStub_gdb( arm7_gdb_stub); arm7_gdb_stub = NULL; + + gdbstub_mutex_destroy(); #endif SDL_Quit(); diff --git a/desmume/src/cocoa/cocoa_core.mm b/desmume/src/cocoa/cocoa_core.mm index 0f6a46f0b..4ff2aed25 100644 --- a/desmume/src/cocoa/cocoa_core.mm +++ b/desmume/src/cocoa/cocoa_core.mm @@ -371,6 +371,8 @@ volatile bool execute = true; #ifdef GDB_STUB if (theState) { + gdbstub_mutex_init(); + if ([self enableGdbStubARM9]) { const uint16_t arm9Port = (uint16_t)[self gdbStubPortARM9]; @@ -422,6 +424,8 @@ volatile bool execute = true; destroyStub_gdb(gdbStubHandleARM7); gdbStubHandleARM7 = NULL; + + gdbstub_mutex_destroy(); } #endif if (gdbStubHandleARM9 == NULL && gdbStubHandleARM7 == NULL) diff --git a/desmume/src/gdbstub.h b/desmume/src/gdbstub.h index 968e579a9..17d9b13a8 100644 --- a/desmume/src/gdbstub.h +++ b/desmume/src/gdbstub.h @@ -25,6 +25,11 @@ typedef void *gdbstub_handle_t; struct armcpu_t; struct armcpu_memory_iface; +void gdbstub_mutex_init(); +void gdbstub_mutex_destroy(); +void gdbstub_mutex_lock(); +void gdbstub_mutex_unlock(); + /* * The function interface */ diff --git a/desmume/src/gdbstub/gdbstub.cpp b/desmume/src/gdbstub/gdbstub.cpp index cb9287142..ef840ae21 100644 --- a/desmume/src/gdbstub/gdbstub.cpp +++ b/desmume/src/gdbstub/gdbstub.cpp @@ -35,6 +35,25 @@ #include "../armcpu.h" #include "../MMU.h" +// For cpu_mutex +#ifdef HOST_WINDOWS +#include +#else +#include +#if defined HOST_LINUX +#include +#elif defined HOST_BSD || defined HOST_DARWIN +#include +#endif +#endif // HOST_WINDOWS + +#ifndef HOST_WINDOWS +// to access the CPUs in any way, a thread has to get a lock on this first +pthread_mutex_t cpu_mutex; +#else +HANDLE cpu_mutex; +#endif + #ifdef __GNUC__ #define UNUSED_PARM( parm) parm __attribute__((unused)) #else @@ -134,9 +153,53 @@ enum target_signal TARGET_SIGNAL_PRIO = 44, }; +// Try defining/undefining this, if you have problems with the GDB stub on Windows. +#define USE_MUTEX_ON_WINDOWS +void gdbstub_mutex_init() +{ + #ifndef HOST_WINDOWS + pthread_mutex_init(&cpu_mutex, NULL); + #else +#ifdef USE_MUTEX_ON_WINDOWS + cpu_mutex = CreateMutex(NULL, FALSE, NULL); +#endif + #endif +} +void gdbstub_mutex_destroy() +{ + #ifndef HOST_WINDOWS + pthread_mutex_destroy(&cpu_mutex); + #else +#ifdef USE_MUTEX_ON_WINDOWS + CloseHandle(cpu_mutex); +#endif + #endif +} +void gdbstub_mutex_lock() +{ +#ifndef HOST_WINDOWS + pthread_mutex_lock(&cpu_mutex); +#else +#ifdef USE_MUTEX_ON_WINDOWS + // Maybe we should check the return value, but then again what could we do about it anyway. + WaitForSingleObject(cpu_mutex, INFINITE); +#endif +#endif +} + +void gdbstub_mutex_unlock() +{ +#ifndef HOST_WINDOWS + pthread_mutex_unlock(&cpu_mutex); +#else +#ifdef USE_MUTEX_ON_WINDOWS + ReleaseMutex(cpu_mutex); +#endif +#endif +} static void causeQuit_gdb( struct gdb_stub_state *stub) { @@ -527,6 +590,7 @@ processPacket_gdb( SOCKET_TYPE sock, const uint8_t *packet, uint32_t send_size = 0; DEBUG_LOG("Processing packet %c\n", packet[0]); + gdbstub_mutex_lock(); switch( packet[0]) { case 3: @@ -899,6 +963,8 @@ processPacket_gdb( SOCKET_TYPE sock, const uint8_t *packet, break; } + gdbstub_mutex_unlock(); + if ( send_reply) { return putpacket( sock, out_packet, send_size); } diff --git a/desmume/src/gtk/main.cpp b/desmume/src/gtk/main.cpp index 58b809240..76c7d0dae 100644 --- a/desmume/src/gtk/main.cpp +++ b/desmume/src/gtk/main.cpp @@ -2919,6 +2919,8 @@ common_gtk_main( class configured_features *my_config) * where the cpus are set up. */ #ifdef GDB_STUB + gdbstub_mutex_init(); + gdbstub_handle_t arm9_gdb_stub = NULL; gdbstub_handle_t arm7_gdb_stub = NULL; @@ -3277,6 +3279,8 @@ common_gtk_main( class configured_features *my_config) destroyStub_gdb( arm7_gdb_stub); arm7_gdb_stub = NULL; + + gdbstub_mutex_destroy(); #endif return EXIT_SUCCESS; diff --git a/desmume/src/windows/main.cpp b/desmume/src/windows/main.cpp index 33fb73f71..b175a87e0 100644 --- a/desmume/src/windows/main.cpp +++ b/desmume/src/windows/main.cpp @@ -3257,6 +3257,8 @@ int _main() NDS_Init(); #ifdef GDB_STUB + gdbstub_mutex_init(); + // Activate the GDB stubs. This has to come after the NDS_Init() where the CPUs are set up. gdbstub_handle_t arm9_gdb_stub = NULL; gdbstub_handle_t arm7_gdb_stub = NULL; @@ -3460,6 +3462,8 @@ int _main() destroyStub_gdb(arm7_gdb_stub); arm7_gdb_stub = NULL; + + gdbstub_mutex_destroy(); #endif NDS_DeInit();