Suspend some host threads that make guest callbacks.
This commit is contained in:
parent
4c8634bc31
commit
3fc1d02a09
|
@ -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();
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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!
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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_;
|
||||
|
|
Loading…
Reference in New Issue