Suspend some host threads that make guest callbacks.

This commit is contained in:
Ben Vanik 2015-09-21 21:24:26 -07:00
parent 4c8634bc31
commit 3fc1d02a09
8 changed files with 25 additions and 8 deletions

View File

@ -100,6 +100,8 @@ X_STATUS AudioSystem::Setup(kernel::KernelState* kernel_state) {
WorkerThreadMain();
return 0;
}));
// As we run audio callbacks the debugger must be able to suspend us.
worker_thread_->set_can_debugger_suspend(true);
worker_thread_->set_name("Audio Worker");
worker_thread_->Create();

View File

@ -225,7 +225,7 @@ bool Debugger::SuspendAllThreads() {
thread_info->state == ThreadExecutionInfo::State::kExited) {
// Thread is dead and cannot be suspended - ignore.
continue;
} else if (!thread_info->thread->is_guest_thread()) {
} else if (!thread_info->thread->can_debugger_suspend()) {
// Thread is a host thread, and we aren't suspending those (for now).
continue;
} else if (XThread::IsInThread() &&
@ -266,7 +266,7 @@ bool Debugger::ResumeAllThreads() {
thread_info->state == ThreadExecutionInfo::State::kExited) {
// Thread is dead and cannot be resumed - ignore.
continue;
} else if (!thread_info->thread->is_guest_thread()) {
} else if (!thread_info->thread->can_debugger_suspend()) {
// Thread is a host thread, and we aren't suspending those (for now).
continue;
} else if (XThread::IsInThread() &&
@ -295,7 +295,7 @@ void Debugger::UpdateThreadExecutionStates(uint32_t override_handle,
// Grab PPC context.
// Note that this is only up to date if --store_all_context_values is
// enabled (or --debug).
if (thread->is_guest_thread()) {
if (thread->can_debugger_suspend()) {
std::memcpy(&thread_info->guest_context,
thread->thread_state()->context(),
sizeof(thread_info->guest_context));

View File

@ -1104,7 +1104,7 @@ void DebugWindow::DrawThreadsPane() {
ImGui::SetNextTreeNodeOpened(true, ImGuiSetCond_Always);
}
const char* state_label = "?";
if (thread->is_guest_thread()) {
if (thread->can_debugger_suspend()) {
if (thread->is_running()) {
if (thread->suspend_count() > 1) {
state_label = "SUSPEND";

View File

@ -305,7 +305,7 @@ bool Emulator::ExceptionCallback(Exception* ex) {
kernel::XObject::kTypeThread);
auto current_thread = kernel::XThread::GetCurrentThread();
for (auto thread : threads) {
if (!thread->is_guest_thread()) {
if (!thread->can_debugger_suspend()) {
// Don't pause host threads.
continue;
}
@ -325,7 +325,7 @@ bool Emulator::ExceptionCallback(Exception* ex) {
});
// Now suspend ourself (we should be a guest thread).
assert_true(current_thread->is_guest_thread());
assert_true(current_thread->can_debugger_suspend());
current_thread->Suspend(nullptr);
// We should not arrive here!

View File

@ -130,6 +130,8 @@ X_STATUS GL4GraphicsSystem::Setup(cpu::Processor* processor,
}
return 0;
}));
// As we run vblank interrupts the debugger must be able to suspend us.
worker_thread_->set_can_debugger_suspend(true);
worker_thread_->set_name("GL4 Vsync");
worker_thread_->Create();

View File

@ -263,6 +263,8 @@ void KernelState::SetExecutableModule(object_ref<UserModule> module) {
}
return 0;
}));
// As we run guest callbacks the debugger must be able to suspend us.
dispatch_thread_->set_can_debugger_suspend(true);
dispatch_thread_->set_name("Kernel Dispatch Thread");
dispatch_thread_->Create();
}

View File

@ -702,7 +702,11 @@ X_STATUS XThread::Delay(uint32_t processor_mode, uint32_t alertable,
XHostThread::XHostThread(KernelState* kernel_state, uint32_t stack_size,
uint32_t creation_flags, std::function<int()> host_fn)
: XThread(kernel_state, stack_size, 0, 0, 0, creation_flags, false),
host_fn_(host_fn) {}
host_fn_(host_fn) {
// By default host threads are not debugger suspendable. If the thread runs
// any guest code this must be overridden.
can_debugger_suspend_ = false;
}
void XHostThread::Execute() {
XELOGKERNEL(

View File

@ -125,7 +125,13 @@ class XThread : public XObject {
const CreationParams* creation_params() const { return &creation_params_; }
uint32_t tls_ptr() const { return tls_address_; }
uint32_t pcr_ptr() const { return pcr_address_; }
// True if the thread is created by the guest app.
bool is_guest_thread() const { return guest_thread_; }
// True if the thread should be paused by the debugger.
// All threads that can run guest code must be stopped for the debugger to
// work properly.
bool can_debugger_suspend() const { return can_debugger_suspend_; }
void set_can_debugger_suspend(bool value) { can_debugger_suspend_ = value; }
bool is_running() const { return running_; }
cpu::ThreadState* thread_state() const { return thread_state_; }
@ -182,7 +188,8 @@ class XThread : public XObject {
uint32_t tls_address_ = 0;
uint32_t pcr_address_ = 0;
cpu::ThreadState* thread_state_ = nullptr;
bool guest_thread_ = false; // Launched into guest code?
bool guest_thread_ = false;
bool can_debugger_suspend_ = true;
bool running_ = false;
std::string name_;