summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/core.cpp6
-rw-r--r--src/core/core.h3
-rw-r--r--src/core/debugger/debugger.cpp55
-rw-r--r--src/core/debugger/debugger.h5
-rw-r--r--src/core/debugger/debugger_interface.h5
-rw-r--r--src/core/debugger/gdbstub.cpp2
-rw-r--r--src/core/debugger/gdbstub.h1
-rw-r--r--src/yuzu/main.cpp1
-rw-r--r--src/yuzu_cmd/yuzu.cpp1
9 files changed, 72 insertions, 7 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 7d974ba65..954136adb 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -493,6 +493,12 @@ void System::Shutdown() {
493 impl->Shutdown(); 493 impl->Shutdown();
494} 494}
495 495
496void System::DetachDebugger() {
497 if (impl->debugger) {
498 impl->debugger->NotifyShutdown();
499 }
500}
501
496std::unique_lock<std::mutex> System::StallCPU() { 502std::unique_lock<std::mutex> System::StallCPU() {
497 return impl->StallCPU(); 503 return impl->StallCPU();
498} 504}
diff --git a/src/core/core.h b/src/core/core.h
index 94477206e..5c367349e 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -160,6 +160,9 @@ public:
160 /// Shutdown the emulated system. 160 /// Shutdown the emulated system.
161 void Shutdown(); 161 void Shutdown();
162 162
163 /// Forcibly detach the debugger if it is running.
164 void DetachDebugger();
165
163 std::unique_lock<std::mutex> StallCPU(); 166 std::unique_lock<std::mutex> StallCPU();
164 void UnstallCPU(); 167 void UnstallCPU();
165 168
diff --git a/src/core/debugger/debugger.cpp b/src/core/debugger/debugger.cpp
index 8d64990ed..1d7f9a775 100644
--- a/src/core/debugger/debugger.cpp
+++ b/src/core/debugger/debugger.cpp
@@ -42,6 +42,16 @@ static std::span<const u8> ReceiveInto(Readable& r, Buffer& buffer) {
42 return received_data; 42 return received_data;
43} 43}
44 44
45enum class SignalType {
46 Stopped,
47 ShuttingDown,
48};
49
50struct SignalInfo {
51 SignalType type;
52 Kernel::KThread* thread;
53};
54
45namespace Core { 55namespace Core {
46 56
47class DebuggerImpl : public DebuggerBackend { 57class DebuggerImpl : public DebuggerBackend {
@@ -56,7 +66,7 @@ public:
56 ShutdownServer(); 66 ShutdownServer();
57 } 67 }
58 68
59 bool NotifyThreadStopped(Kernel::KThread* thread) { 69 bool SignalDebugger(SignalInfo signal_info) {
60 std::scoped_lock lk{connection_lock}; 70 std::scoped_lock lk{connection_lock};
61 71
62 if (stopped) { 72 if (stopped) {
@@ -64,9 +74,13 @@ public:
64 // It should be ignored. 74 // It should be ignored.
65 return false; 75 return false;
66 } 76 }
77
78 // Set up the state.
67 stopped = true; 79 stopped = true;
80 info = signal_info;
68 81
69 boost::asio::write(signal_pipe, boost::asio::buffer(&thread, sizeof(thread))); 82 // Write a single byte into the pipe to wake up the debug interface.
83 boost::asio::write(signal_pipe, boost::asio::buffer(&stopped, sizeof(stopped)));
70 return true; 84 return true;
71 } 85 }
72 86
@@ -124,7 +138,7 @@ private:
124 Common::SetCurrentThreadName("yuzu:Debugger"); 138 Common::SetCurrentThreadName("yuzu:Debugger");
125 139
126 // Set up the client signals for new data. 140 // Set up the client signals for new data.
127 AsyncReceiveInto(signal_pipe, active_thread, [&](auto d) { PipeData(d); }); 141 AsyncReceiveInto(signal_pipe, pipe_data, [&](auto d) { PipeData(d); });
128 AsyncReceiveInto(client_socket, client_data, [&](auto d) { ClientData(d); }); 142 AsyncReceiveInto(client_socket, client_data, [&](auto d) { ClientData(d); });
129 143
130 // Stop the emulated CPU. 144 // Stop the emulated CPU.
@@ -142,9 +156,28 @@ private:
142 } 156 }
143 157
144 void PipeData(std::span<const u8> data) { 158 void PipeData(std::span<const u8> data) {
145 AllCoreStop(); 159 switch (info.type) {
146 UpdateActiveThread(); 160 case SignalType::Stopped:
147 frontend->Stopped(active_thread); 161 // Stop emulation.
162 AllCoreStop();
163
164 // Notify the client.
165 active_thread = info.thread;
166 UpdateActiveThread();
167 frontend->Stopped(active_thread);
168
169 break;
170 case SignalType::ShuttingDown:
171 frontend->ShuttingDown();
172
173 // Wait for emulation to shut down gracefully now.
174 suspend.reset();
175 signal_pipe.close();
176 client_socket.shutdown(boost::asio::socket_base::shutdown_both);
177 LOG_INFO(Debug_GDBStub, "Shut down server");
178
179 break;
180 }
148 } 181 }
149 182
150 void ClientData(std::span<const u8> data) { 183 void ClientData(std::span<const u8> data) {
@@ -246,7 +279,9 @@ private:
246 boost::asio::ip::tcp::socket client_socket; 279 boost::asio::ip::tcp::socket client_socket;
247 std::optional<std::unique_lock<std::mutex>> suspend; 280 std::optional<std::unique_lock<std::mutex>> suspend;
248 281
282 SignalInfo info;
249 Kernel::KThread* active_thread; 283 Kernel::KThread* active_thread;
284 bool pipe_data;
250 bool stopped; 285 bool stopped;
251 286
252 std::array<u8, 4096> client_data; 287 std::array<u8, 4096> client_data;
@@ -263,7 +298,13 @@ Debugger::Debugger(Core::System& system, u16 port) {
263Debugger::~Debugger() = default; 298Debugger::~Debugger() = default;
264 299
265bool Debugger::NotifyThreadStopped(Kernel::KThread* thread) { 300bool Debugger::NotifyThreadStopped(Kernel::KThread* thread) {
266 return impl && impl->NotifyThreadStopped(thread); 301 return impl && impl->SignalDebugger(SignalInfo{SignalType::Stopped, thread});
302}
303
304void Debugger::NotifyShutdown() {
305 if (impl) {
306 impl->SignalDebugger(SignalInfo{SignalType::ShuttingDown, nullptr});
307 }
267} 308}
268 309
269} // namespace Core 310} // namespace Core
diff --git a/src/core/debugger/debugger.h b/src/core/debugger/debugger.h
index ea36c6ab2..f9738ca3d 100644
--- a/src/core/debugger/debugger.h
+++ b/src/core/debugger/debugger.h
@@ -35,6 +35,11 @@ public:
35 */ 35 */
36 bool NotifyThreadStopped(Kernel::KThread* thread); 36 bool NotifyThreadStopped(Kernel::KThread* thread);
37 37
38 /**
39 * Notify the debugger that a shutdown is being performed now and disconnect.
40 */
41 void NotifyShutdown();
42
38private: 43private:
39 std::unique_ptr<DebuggerImpl> impl; 44 std::unique_ptr<DebuggerImpl> impl;
40}; 45};
diff --git a/src/core/debugger/debugger_interface.h b/src/core/debugger/debugger_interface.h
index 35ba0bc61..c0bb4ecaf 100644
--- a/src/core/debugger/debugger_interface.h
+++ b/src/core/debugger/debugger_interface.h
@@ -67,6 +67,11 @@ public:
67 virtual void Stopped(Kernel::KThread* thread) = 0; 67 virtual void Stopped(Kernel::KThread* thread) = 0;
68 68
69 /** 69 /**
70 * Called when emulation is shutting down.
71 */
72 virtual void ShuttingDown() = 0;
73
74 /**
70 * Called when new data is asynchronously received on the client socket. 75 * Called when new data is asynchronously received on the client socket.
71 * A list of actions to perform is returned. 76 * A list of actions to perform is returned.
72 */ 77 */
diff --git a/src/core/debugger/gdbstub.cpp b/src/core/debugger/gdbstub.cpp
index f52d78829..52e76f659 100644
--- a/src/core/debugger/gdbstub.cpp
+++ b/src/core/debugger/gdbstub.cpp
@@ -106,6 +106,8 @@ GDBStub::~GDBStub() = default;
106 106
107void GDBStub::Connected() {} 107void GDBStub::Connected() {}
108 108
109void GDBStub::ShuttingDown() {}
110
109void GDBStub::Stopped(Kernel::KThread* thread) { 111void GDBStub::Stopped(Kernel::KThread* thread) {
110 SendReply(arch->ThreadStatus(thread, GDB_STUB_SIGTRAP)); 112 SendReply(arch->ThreadStatus(thread, GDB_STUB_SIGTRAP));
111} 113}
diff --git a/src/core/debugger/gdbstub.h b/src/core/debugger/gdbstub.h
index 1bb638187..ec934c77e 100644
--- a/src/core/debugger/gdbstub.h
+++ b/src/core/debugger/gdbstub.h
@@ -23,6 +23,7 @@ public:
23 23
24 void Connected() override; 24 void Connected() override;
25 void Stopped(Kernel::KThread* thread) override; 25 void Stopped(Kernel::KThread* thread) override;
26 void ShuttingDown() override;
26 std::vector<DebuggerAction> ClientData(std::span<const u8> data) override; 27 std::vector<DebuggerAction> ClientData(std::span<const u8> data) override;
27 28
28private: 29private:
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 80e6d23a5..c9288b4fe 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -1545,6 +1545,7 @@ void GMainWindow::ShutdownGame() {
1545 1545
1546 AllowOSSleep(); 1546 AllowOSSleep();
1547 1547
1548 system->DetachDebugger();
1548 discord_rpc->Pause(); 1549 discord_rpc->Pause();
1549 emu_thread->RequestStop(); 1550 emu_thread->RequestStop();
1550 1551
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp
index a0d619c48..0dce5e274 100644
--- a/src/yuzu_cmd/yuzu.cpp
+++ b/src/yuzu_cmd/yuzu.cpp
@@ -229,6 +229,7 @@ int main(int argc, char** argv) {
229 while (emu_window->IsOpen()) { 229 while (emu_window->IsOpen()) {
230 emu_window->WaitEvent(); 230 emu_window->WaitEvent();
231 } 231 }
232 system.DetachDebugger();
232 void(system.Pause()); 233 void(system.Pause());
233 system.Shutdown(); 234 system.Shutdown();
234 235