Debugger can pause/resume threads.
This commit is contained in:
parent
8dc20eb5cd
commit
d482885378
|
@ -45,10 +45,6 @@ class ThreadState {
|
|||
uint32_t pcr_address() const { return pcr_address_; }
|
||||
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 ThreadState* Get();
|
||||
static uint32_t GetThreadID();
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "xenia/emulator.h"
|
||||
#include "xenia/kernel/objects/xkernel_module.h"
|
||||
#include "xenia/kernel/objects/xmodule.h"
|
||||
#include "xenia/kernel/objects/xthread.h"
|
||||
#include "xenia/kernel/objects/xuser_module.h"
|
||||
|
||||
// Autogenerated Flatbuffers files:
|
||||
|
@ -127,6 +128,8 @@ void SendResponse(SOCKET client_socket, flatbuffers::FlatBufferBuilder& fbb,
|
|||
|
||||
void Debugger::PreLaunch() {
|
||||
accept_thread_ = std::thread([this]() {
|
||||
xe::threading::set_name("Debugger Server");
|
||||
|
||||
while (listen_socket_ != INVALID_SOCKET) {
|
||||
sockaddr_in6 client_addr;
|
||||
int client_count = sizeof(client_addr);
|
||||
|
@ -148,6 +151,8 @@ void Debugger::PreLaunch() {
|
|||
// Setup recv thread.
|
||||
client_socket_ = client_socket_id;
|
||||
receive_thread_ = std::thread([this]() {
|
||||
xe::threading::set_name("Debugger Connection");
|
||||
|
||||
while (client_socket_ != INVALID_SOCKET) {
|
||||
// Read length prefix.
|
||||
uint32_t length = 0;
|
||||
|
@ -471,51 +476,36 @@ uint8_t* Debugger::AllocateFunctionTraceData(size_t size) {
|
|||
return functions_trace_file_->Allocate(size);
|
||||
}
|
||||
|
||||
int Debugger::SuspendAllThreads(uint32_t timeout_ms) {
|
||||
std::lock_guard<std::mutex> guard(threads_lock_);
|
||||
|
||||
int result = 0;
|
||||
for (auto thread_state : threads_) {
|
||||
if (thread_state.second->Suspend(timeout_ms)) {
|
||||
result = 1;
|
||||
bool Debugger::SuspendAllThreads() {
|
||||
auto threads =
|
||||
emulator_->kernel_state()->object_table()->GetObjectsByType<XThread>(
|
||||
XObject::kTypeThread);
|
||||
for (auto& thread : threads) {
|
||||
if (!XSUCCEEDED(thread->Suspend(nullptr))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return true;
|
||||
}
|
||||
|
||||
int Debugger::ResumeThread(uint32_t thread_id) {
|
||||
std::lock_guard<std::mutex> guard(threads_lock_);
|
||||
|
||||
auto it = threads_.find(thread_id);
|
||||
if (it == threads_.end()) {
|
||||
return 1;
|
||||
bool Debugger::ResumeThread(uint32_t thread_id) {
|
||||
auto thread = emulator_->kernel_state()->GetThreadByID(thread_id);
|
||||
if (!thread) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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;
|
||||
return XSUCCEEDED(thread->Resume());
|
||||
}
|
||||
|
||||
int Debugger::ResumeAllThreads(bool force) {
|
||||
std::lock_guard<std::mutex> guard(threads_lock_);
|
||||
|
||||
int result = 0;
|
||||
for (auto thread_state : threads_) {
|
||||
if (thread_state.second->Resume(force)) {
|
||||
result = 1;
|
||||
bool Debugger::ResumeAllThreads() {
|
||||
auto threads =
|
||||
emulator_->kernel_state()->object_table()->GetObjectsByType<XThread>(
|
||||
XObject::kTypeThread);
|
||||
for (auto& thread : threads) {
|
||||
if (!XSUCCEEDED(thread->Resume())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int Debugger::AddBreakpoint(Breakpoint* breakpoint) {
|
||||
|
@ -591,16 +581,11 @@ void Debugger::FindBreakpoints(uint32_t address,
|
|||
}
|
||||
|
||||
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) {
|
||||
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,
|
||||
|
|
|
@ -81,11 +81,9 @@ class Debugger {
|
|||
uint8_t* AllocateFunctionData(size_t size);
|
||||
uint8_t* AllocateFunctionTraceData(size_t size);
|
||||
|
||||
int SuspendAllThreads(uint32_t timeout_ms = UINT_MAX);
|
||||
int ResumeThread(uint32_t thread_id);
|
||||
int ResumeAllThreads(bool force = false);
|
||||
|
||||
void ForEachThread(std::function<void(cpu::ThreadState*)> callback);
|
||||
bool SuspendAllThreads();
|
||||
bool ResumeThread(uint32_t thread_id);
|
||||
bool ResumeAllThreads();
|
||||
|
||||
int AddBreakpoint(Breakpoint* breakpoint);
|
||||
int RemoveBreakpoint(Breakpoint* breakpoint);
|
||||
|
@ -121,9 +119,6 @@ class Debugger {
|
|||
std::wstring functions_trace_path_;
|
||||
std::unique_ptr<ChunkedMappedMemoryWriter> functions_trace_file_;
|
||||
|
||||
std::mutex threads_lock_;
|
||||
std::unordered_map<uint32_t, cpu::ThreadState*> threads_;
|
||||
|
||||
std::mutex breakpoints_lock_;
|
||||
std::multimap<uint32_t, Breakpoint*> breakpoints_;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue