diff --git a/CHANGES b/CHANGES index 23da04cc9..deee85665 100644 --- a/CHANGES +++ b/CHANGES @@ -75,6 +75,7 @@ Misc: - GBA Video: Start video at the last scanline instead of the first - Debugger: Watchpoints now work on STM/LDM instructions - GBA: Improve accuracy of event timing + - Debugger: Clean up GDB stub network interfacing 0.1.0: (2014-12-13) - Initial release diff --git a/src/debugger/gdb-stub.c b/src/debugger/gdb-stub.c index bc43a1df3..915a1fadd 100644 --- a/src/debugger/gdb-stub.c +++ b/src/debugger/gdb-stub.c @@ -53,15 +53,39 @@ static void _gdbStubEntered(struct ARMDebugger* debugger, enum DebuggerEntryReas static void _gdbStubPoll(struct ARMDebugger* debugger) { struct GDBStub* stub = (struct GDBStub*) debugger; - do { - if (!SOCKET_FAILED(stub->connection)) { - if (!SocketSetBlocking(stub->connection, 1)) { - GDBStubHangup(stub); - return; - } + --stub->untilPoll; + if (stub->untilPoll > 0) { + return; + } + stub->untilPoll = GDB_STUB_INTERVAL; + if (stub->shouldBlock) { + stub->shouldBlock = false; + if (!SocketSetBlocking(stub->socket, false)) { + GDBStubHangup(stub); + return; } - GDBStubUpdate(stub); - } while (stub->d.state == DEBUGGER_PAUSED); + if (!SOCKET_FAILED(stub->connection) && !SocketSetBlocking(stub->connection, false)) { + GDBStubHangup(stub); + return; + } + } + GDBStubUpdate(stub); +} + +static void _gdbStubWait(struct ARMDebugger* debugger) { + struct GDBStub* stub = (struct GDBStub*) debugger; + if (!stub->shouldBlock) { + stub->shouldBlock = true; + if (!SocketSetBlocking(stub->socket, true)) { + GDBStubHangup(stub); + return; + } + if (!SOCKET_FAILED(stub->connection) && !SocketSetBlocking(stub->connection, true)) { + GDBStubHangup(stub); + return; + } + } + GDBStubUpdate(stub); } static void _ack(struct GDBStub* stub) { @@ -170,6 +194,7 @@ static void _writeHostInfo(struct GDBStub* stub) { static void _continue(struct GDBStub* stub, const char* message) { stub->d.state = DEBUGGER_CUSTOM; + stub->untilPoll = GDB_STUB_INTERVAL; if (!SOCKET_FAILED(stub->connection)) { if (!SocketSetBlocking(stub->connection, 0)) { GDBStubHangup(stub); @@ -441,10 +466,11 @@ void GDBStubCreate(struct GDBStub* stub) { stub->connection = INVALID_SOCKET; stub->d.init = 0; stub->d.deinit = _gdbStubDeinit; - stub->d.paused = _gdbStubPoll; + stub->d.paused = _gdbStubWait; stub->d.entered = _gdbStubEntered; stub->d.custom = _gdbStubPoll; stub->d.log = 0; + stub->untilPoll = GDB_STUB_INTERVAL; } int GDBStubListen(struct GDBStub* stub, int port, const struct Address* bindAddress) { @@ -462,9 +488,6 @@ int GDBStubListen(struct GDBStub* stub, int port, const struct Address* bindAddr if (err) { goto cleanup; } - if (!SocketSetBlocking(stub->socket, 0)) { - goto cleanup; - } return 1; @@ -502,9 +525,6 @@ void GDBStubUpdate(struct GDBStub* stub) { if (stub->connection == INVALID_SOCKET) { stub->connection = SocketAccept(stub->socket, 0); if (!SOCKET_FAILED(stub->connection)) { - if (!SocketSetBlocking(stub->connection, 0)) { - goto connectionLost; - } ARMDebuggerEnter(&stub->d, DEBUGGER_ENTER_ATTACHED); } else if (errno == EWOULDBLOCK || errno == EAGAIN) { return; diff --git a/src/debugger/gdb-stub.h b/src/debugger/gdb-stub.h index 5ba14801c..25b435715 100644 --- a/src/debugger/gdb-stub.h +++ b/src/debugger/gdb-stub.h @@ -13,6 +13,7 @@ #include "util/socket.h" #define GDB_STUB_MAX_LINE 1200 +#define GDB_STUB_INTERVAL 32 enum GDBStubAckState { GDB_ACK_PENDING = 0, @@ -30,6 +31,9 @@ struct GDBStub { Socket socket; Socket connection; + + bool shouldBlock; + int untilPoll; }; void GDBStubCreate(struct GDBStub*); diff --git a/src/util/socket.h b/src/util/socket.h index d2049df84..a90680654 100644 --- a/src/util/socket.h +++ b/src/util/socket.h @@ -157,7 +157,7 @@ static inline int SocketClose(Socket socket) { return close(socket) >= 0; } -static inline int SocketSetBlocking(Socket socket, int blocking) { +static inline int SocketSetBlocking(Socket socket, bool blocking) { #ifdef _WIN32 u_long unblocking = !blocking; return ioctlsocket(socket, FIONBIO, &unblocking) == NO_ERROR;