Debugger can pause/resume threads.

This commit is contained in:
Ben Vanik 2015-06-09 20:14:23 -07:00
parent 8dc20eb5cd
commit d482885378
3 changed files with 31 additions and 55 deletions

View File

@ -45,10 +45,6 @@ class ThreadState {
uint32_t pcr_address() const { return pcr_address_; } uint32_t pcr_address() const { return pcr_address_; }
xe::cpu::frontend::PPCContext* context() const { return context_; } xe::cpu::frontend::PPCContext* context() const { return context_; }
bool Suspend() { return Suspend(~0); }
bool Suspend(uint32_t timeout_ms) { return false; }
bool Resume(bool force = false) { return false; }
static void Bind(ThreadState* thread_state); static void Bind(ThreadState* thread_state);
static ThreadState* Get(); static ThreadState* Get();
static uint32_t GetThreadID(); static uint32_t GetThreadID();

View File

@ -24,6 +24,7 @@
#include "xenia/emulator.h" #include "xenia/emulator.h"
#include "xenia/kernel/objects/xkernel_module.h" #include "xenia/kernel/objects/xkernel_module.h"
#include "xenia/kernel/objects/xmodule.h" #include "xenia/kernel/objects/xmodule.h"
#include "xenia/kernel/objects/xthread.h"
#include "xenia/kernel/objects/xuser_module.h" #include "xenia/kernel/objects/xuser_module.h"
// Autogenerated Flatbuffers files: // Autogenerated Flatbuffers files:
@ -127,6 +128,8 @@ void SendResponse(SOCKET client_socket, flatbuffers::FlatBufferBuilder& fbb,
void Debugger::PreLaunch() { void Debugger::PreLaunch() {
accept_thread_ = std::thread([this]() { accept_thread_ = std::thread([this]() {
xe::threading::set_name("Debugger Server");
while (listen_socket_ != INVALID_SOCKET) { while (listen_socket_ != INVALID_SOCKET) {
sockaddr_in6 client_addr; sockaddr_in6 client_addr;
int client_count = sizeof(client_addr); int client_count = sizeof(client_addr);
@ -148,6 +151,8 @@ void Debugger::PreLaunch() {
// Setup recv thread. // Setup recv thread.
client_socket_ = client_socket_id; client_socket_ = client_socket_id;
receive_thread_ = std::thread([this]() { receive_thread_ = std::thread([this]() {
xe::threading::set_name("Debugger Connection");
while (client_socket_ != INVALID_SOCKET) { while (client_socket_ != INVALID_SOCKET) {
// Read length prefix. // Read length prefix.
uint32_t length = 0; uint32_t length = 0;
@ -471,51 +476,36 @@ uint8_t* Debugger::AllocateFunctionTraceData(size_t size) {
return functions_trace_file_->Allocate(size); return functions_trace_file_->Allocate(size);
} }
int Debugger::SuspendAllThreads(uint32_t timeout_ms) { bool Debugger::SuspendAllThreads() {
std::lock_guard<std::mutex> guard(threads_lock_); auto threads =
emulator_->kernel_state()->object_table()->GetObjectsByType<XThread>(
int result = 0; XObject::kTypeThread);
for (auto thread_state : threads_) { for (auto& thread : threads) {
if (thread_state.second->Suspend(timeout_ms)) { if (!XSUCCEEDED(thread->Suspend(nullptr))) {
result = 1; return false;
} }
} }
return result; return true;
} }
int Debugger::ResumeThread(uint32_t thread_id) { bool Debugger::ResumeThread(uint32_t thread_id) {
std::lock_guard<std::mutex> guard(threads_lock_); auto thread = emulator_->kernel_state()->GetThreadByID(thread_id);
if (!thread) {
auto it = threads_.find(thread_id); return false;
if (it == threads_.end()) {
return 1;
} }
return XSUCCEEDED(thread->Resume());
// Found thread. Note that it could be deleted as soon as we unlock.
ThreadState* thread_state = it->second;
int result = thread_state->Resume();
return result;
} }
int Debugger::ResumeAllThreads(bool force) { bool Debugger::ResumeAllThreads() {
std::lock_guard<std::mutex> guard(threads_lock_); auto threads =
emulator_->kernel_state()->object_table()->GetObjectsByType<XThread>(
int result = 0; XObject::kTypeThread);
for (auto thread_state : threads_) { for (auto& thread : threads) {
if (thread_state.second->Resume(force)) { if (!XSUCCEEDED(thread->Resume())) {
result = 1; return false;
} }
} }
return result; return true;
}
void Debugger::ForEachThread(std::function<void(ThreadState*)> callback) {
std::lock_guard<std::mutex> guard(threads_lock_);
for (auto thread_state : threads_) {
callback(thread_state.second);
}
} }
int Debugger::AddBreakpoint(Breakpoint* breakpoint) { int Debugger::AddBreakpoint(Breakpoint* breakpoint) {
@ -591,16 +581,11 @@ void Debugger::FindBreakpoints(uint32_t address,
} }
void Debugger::OnThreadCreated(ThreadState* thread_state) { void Debugger::OnThreadCreated(ThreadState* thread_state) {
std::lock_guard<std::mutex> guard(threads_lock_); //
threads_[thread_state->thread_id()] = thread_state;
} }
void Debugger::OnThreadDestroyed(ThreadState* thread_state) { void Debugger::OnThreadDestroyed(ThreadState* thread_state) {
std::lock_guard<std::mutex> guard(threads_lock_); //
auto it = threads_.find(thread_state->thread_id());
if (it != threads_.end()) {
threads_.erase(it);
}
} }
void Debugger::OnFunctionDefined(cpu::FunctionInfo* symbol_info, void Debugger::OnFunctionDefined(cpu::FunctionInfo* symbol_info,

View File

@ -81,11 +81,9 @@ class Debugger {
uint8_t* AllocateFunctionData(size_t size); uint8_t* AllocateFunctionData(size_t size);
uint8_t* AllocateFunctionTraceData(size_t size); uint8_t* AllocateFunctionTraceData(size_t size);
int SuspendAllThreads(uint32_t timeout_ms = UINT_MAX); bool SuspendAllThreads();
int ResumeThread(uint32_t thread_id); bool ResumeThread(uint32_t thread_id);
int ResumeAllThreads(bool force = false); bool ResumeAllThreads();
void ForEachThread(std::function<void(cpu::ThreadState*)> callback);
int AddBreakpoint(Breakpoint* breakpoint); int AddBreakpoint(Breakpoint* breakpoint);
int RemoveBreakpoint(Breakpoint* breakpoint); int RemoveBreakpoint(Breakpoint* breakpoint);
@ -121,9 +119,6 @@ class Debugger {
std::wstring functions_trace_path_; std::wstring functions_trace_path_;
std::unique_ptr<ChunkedMappedMemoryWriter> functions_trace_file_; std::unique_ptr<ChunkedMappedMemoryWriter> functions_trace_file_;
std::mutex threads_lock_;
std::unordered_map<uint32_t, cpu::ThreadState*> threads_;
std::mutex breakpoints_lock_; std::mutex breakpoints_lock_;
std::multimap<uint32_t, Breakpoint*> breakpoints_; std::multimap<uint32_t, Breakpoint*> breakpoints_;
}; };