Remove xenia-cpu dependency on xenia-kernel
This commit is contained in:
parent
b66f10f2b8
commit
4c55039c22
|
@ -12,9 +12,6 @@ project("xenia-cpu-ppc-tests")
|
||||||
"xenia-core",
|
"xenia-core",
|
||||||
"xenia-cpu",
|
"xenia-cpu",
|
||||||
"xenia-cpu-backend-x64",
|
"xenia-cpu-backend-x64",
|
||||||
|
|
||||||
-- TODO(benvanik): remove these dependencies.
|
|
||||||
"xenia-kernel"
|
|
||||||
})
|
})
|
||||||
files({
|
files({
|
||||||
"ppc_testing_main.cc",
|
"ppc_testing_main.cc",
|
||||||
|
|
|
@ -28,12 +28,10 @@
|
||||||
#include "xenia/cpu/ppc/ppc_decode_data.h"
|
#include "xenia/cpu/ppc/ppc_decode_data.h"
|
||||||
#include "xenia/cpu/ppc/ppc_frontend.h"
|
#include "xenia/cpu/ppc/ppc_frontend.h"
|
||||||
#include "xenia/cpu/stack_walker.h"
|
#include "xenia/cpu/stack_walker.h"
|
||||||
|
#include "xenia/cpu/thread.h"
|
||||||
#include "xenia/cpu/thread_state.h"
|
#include "xenia/cpu/thread_state.h"
|
||||||
#include "xenia/cpu/xex_module.h"
|
#include "xenia/cpu/xex_module.h"
|
||||||
|
|
||||||
// HACK(benvanik): XThread has too much stuff :/
|
|
||||||
#include "xenia/kernel/xthread.h"
|
|
||||||
|
|
||||||
// TODO(benvanik): based on compiler support
|
// TODO(benvanik): based on compiler support
|
||||||
#include "xenia/cpu/backend/x64/x64_backend.h"
|
#include "xenia/cpu/backend/x64/x64_backend.h"
|
||||||
|
|
||||||
|
@ -49,6 +47,10 @@ DEFINE_string(trace_function_data_path, "", "File to write trace data to.");
|
||||||
DEFINE_bool(break_on_start, false, "Break into the debugger on startup.");
|
DEFINE_bool(break_on_start, false, "Break into the debugger on startup.");
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
|
namespace kernel {
|
||||||
|
class XThread;
|
||||||
|
} // namespace kernel
|
||||||
|
|
||||||
namespace cpu {
|
namespace cpu {
|
||||||
|
|
||||||
using xe::cpu::ppc::PPCOpcode;
|
using xe::cpu::ppc::PPCOpcode;
|
||||||
|
@ -491,8 +493,7 @@ void Processor::OnFunctionDefined(Function* function) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Processor::OnThreadCreated(uint32_t thread_handle,
|
void Processor::OnThreadCreated(uint32_t thread_handle,
|
||||||
ThreadState* thread_state,
|
ThreadState* thread_state, Thread* thread) {
|
||||||
kernel::XThread* thread) {
|
|
||||||
auto global_lock = global_critical_region_.Acquire();
|
auto global_lock = global_critical_region_.Acquire();
|
||||||
auto thread_info = std::make_unique<ThreadDebugInfo>();
|
auto thread_info = std::make_unique<ThreadDebugInfo>();
|
||||||
thread_info->thread_handle = thread_handle;
|
thread_info->thread_handle = thread_handle;
|
||||||
|
@ -683,7 +684,7 @@ bool Processor::OnThreadBreakpointHit(Exception* ex) {
|
||||||
debug_listener_->OnExecutionPaused();
|
debug_listener_->OnExecutionPaused();
|
||||||
}
|
}
|
||||||
|
|
||||||
thread_info->thread->Suspend(nullptr);
|
thread_info->thread->thread()->Suspend();
|
||||||
|
|
||||||
// Apply thread context changes.
|
// Apply thread context changes.
|
||||||
// TODO(benvanik): apply to all threads?
|
// TODO(benvanik): apply to all threads?
|
||||||
|
@ -711,7 +712,7 @@ bool Processor::OnUnhandledException(Exception* ex) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this isn't a managed thread, fail - let VS handle it for now.
|
// If this isn't a managed thread, fail - let VS handle it for now.
|
||||||
if (!XThread::IsInThread()) {
|
if (!Thread::IsInThread()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -720,7 +721,7 @@ bool Processor::OnUnhandledException(Exception* ex) {
|
||||||
// Suspend all guest threads (but this one).
|
// Suspend all guest threads (but this one).
|
||||||
SuspendAllThreads();
|
SuspendAllThreads();
|
||||||
|
|
||||||
UpdateThreadExecutionStates(XThread::GetCurrentThreadId(),
|
UpdateThreadExecutionStates(Thread::GetCurrentThreadId(),
|
||||||
ex->thread_context());
|
ex->thread_context());
|
||||||
|
|
||||||
// Stop and notify the listener.
|
// Stop and notify the listener.
|
||||||
|
@ -733,7 +734,7 @@ bool Processor::OnUnhandledException(Exception* ex) {
|
||||||
debug_listener_->OnExecutionPaused();
|
debug_listener_->OnExecutionPaused();
|
||||||
|
|
||||||
// Suspend self.
|
// Suspend self.
|
||||||
XThread::GetCurrentThread()->Suspend(nullptr);
|
Thread::GetCurrentThread()->thread()->Suspend();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -757,8 +758,8 @@ bool Processor::SuspendAllThreads() {
|
||||||
thread_info->state == ThreadDebugInfo::State::kExited) {
|
thread_info->state == ThreadDebugInfo::State::kExited) {
|
||||||
// Thread is dead and cannot be suspended - ignore.
|
// Thread is dead and cannot be suspended - ignore.
|
||||||
continue;
|
continue;
|
||||||
} else if (XThread::IsInThread() &&
|
} else if (Thread::IsInThread() &&
|
||||||
thread_info->thread_id == XThread::GetCurrentThreadId()) {
|
thread_info->thread_id == Thread::GetCurrentThreadId()) {
|
||||||
// Can't suspend ourselves.
|
// Can't suspend ourselves.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -767,7 +768,7 @@ bool Processor::SuspendAllThreads() {
|
||||||
// Thread is a host thread, and we aren't suspending those (for now).
|
// Thread is a host thread, and we aren't suspending those (for now).
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
bool did_suspend = XSUCCEEDED(thread->Suspend(nullptr));
|
bool did_suspend = thread->thread()->Suspend(nullptr);
|
||||||
assert_true(did_suspend);
|
assert_true(did_suspend);
|
||||||
thread_info->suspended = true;
|
thread_info->suspended = true;
|
||||||
}
|
}
|
||||||
|
@ -786,7 +787,7 @@ bool Processor::ResumeThread(uint32_t thread_id) {
|
||||||
thread_info->state == ThreadDebugInfo::State::kZombie);
|
thread_info->state == ThreadDebugInfo::State::kZombie);
|
||||||
thread_info->suspended = false;
|
thread_info->suspended = false;
|
||||||
auto thread = thread_info->thread;
|
auto thread = thread_info->thread;
|
||||||
return XSUCCEEDED(thread->Resume());
|
return thread->thread()->Resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Processor::ResumeAllThreads() {
|
bool Processor::ResumeAllThreads() {
|
||||||
|
@ -800,8 +801,8 @@ bool Processor::ResumeAllThreads() {
|
||||||
thread_info->state == ThreadDebugInfo::State::kExited) {
|
thread_info->state == ThreadDebugInfo::State::kExited) {
|
||||||
// Thread is dead and cannot be resumed - ignore.
|
// Thread is dead and cannot be resumed - ignore.
|
||||||
continue;
|
continue;
|
||||||
} else if (XThread::IsInThread() &&
|
} else if (Thread::IsInThread() &&
|
||||||
thread_info->thread_id == XThread::GetCurrentThreadId()) {
|
thread_info->thread_id == Thread::GetCurrentThreadId()) {
|
||||||
// Can't resume ourselves.
|
// Can't resume ourselves.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -811,7 +812,7 @@ bool Processor::ResumeAllThreads() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
thread_info->suspended = false;
|
thread_info->suspended = false;
|
||||||
bool did_resume = XSUCCEEDED(thread->Resume());
|
bool did_resume = thread->thread()->Resume();
|
||||||
assert_true(did_resume);
|
assert_true(did_resume);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -987,7 +988,7 @@ bool Processor::StepToGuestAddress(uint32_t thread_id, uint32_t pc) {
|
||||||
if (functions.empty()) {
|
if (functions.empty()) {
|
||||||
// Function hasn't been generated yet. Generate it.
|
// Function hasn't been generated yet. Generate it.
|
||||||
if (!ResolveFunction(pc)) {
|
if (!ResolveFunction(pc)) {
|
||||||
XELOGE("XThread::StepToAddress(%.8X) - Function could not be resolved",
|
XELOGE("Processor::StepToAddress(%.8X) - Function could not be resolved",
|
||||||
pc);
|
pc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1005,7 +1006,7 @@ bool Processor::StepToGuestAddress(uint32_t thread_id, uint32_t pc) {
|
||||||
auto thread_info = QueryThreadDebugInfo(thread_id);
|
auto thread_info = QueryThreadDebugInfo(thread_id);
|
||||||
uint32_t suspend_count = 1;
|
uint32_t suspend_count = 1;
|
||||||
while (suspend_count) {
|
while (suspend_count) {
|
||||||
thread_info->thread->Resume(&suspend_count);
|
thread_info->thread->thread()->Resume(&suspend_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
fence.Wait();
|
fence.Wait();
|
||||||
|
@ -1075,7 +1076,7 @@ uint32_t Processor::StepIntoGuestBranchTarget(uint32_t thread_id, uint32_t pc) {
|
||||||
// HACK
|
// HACK
|
||||||
uint32_t suspend_count = 1;
|
uint32_t suspend_count = 1;
|
||||||
while (suspend_count) {
|
while (suspend_count) {
|
||||||
thread->Resume(&suspend_count);
|
thread->thread()->Resume(&suspend_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
fence.Wait();
|
fence.Wait();
|
||||||
|
@ -1090,7 +1091,7 @@ uint32_t Processor::StepToGuestSafePoint(uint32_t thread_id, bool ignore_host) {
|
||||||
// This cannot be done if we're the calling thread!
|
// This cannot be done if we're the calling thread!
|
||||||
if (thread_id == ThreadState::GetThreadID()) {
|
if (thread_id == ThreadState::GetThreadID()) {
|
||||||
assert_always(
|
assert_always(
|
||||||
"XThread::StepToSafePoint(): target thread is the calling thread!");
|
"Processor::StepToSafePoint(): target thread is the calling thread!");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
auto thread_info = QueryThreadDebugInfo(thread_id);
|
auto thread_info = QueryThreadDebugInfo(thread_id);
|
||||||
|
@ -1213,11 +1214,15 @@ uint32_t Processor::StepToGuestSafePoint(uint32_t thread_id, bool ignore_host) {
|
||||||
} else {
|
} else {
|
||||||
// We've managed to catch a thread before it called into the guest.
|
// We've managed to catch a thread before it called into the guest.
|
||||||
// Set a breakpoint on its startup procedure and capture it there.
|
// Set a breakpoint on its startup procedure and capture it there.
|
||||||
|
// TODO(DrChat): Reimplement
|
||||||
|
assert_always("Unimplemented");
|
||||||
|
/*
|
||||||
auto creation_params = thread->creation_params();
|
auto creation_params = thread->creation_params();
|
||||||
pc = creation_params->xapi_thread_startup
|
pc = creation_params->xapi_thread_startup
|
||||||
? creation_params->xapi_thread_startup
|
? creation_params->xapi_thread_startup
|
||||||
: creation_params->start_address;
|
: creation_params->start_address;
|
||||||
StepToGuestAddress(thread_id, pc);
|
StepToGuestAddress(thread_id, pc);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -189,7 +189,7 @@ class Processor {
|
||||||
public:
|
public:
|
||||||
// TODO(benvanik): hide.
|
// TODO(benvanik): hide.
|
||||||
void OnThreadCreated(uint32_t handle, ThreadState* thread_state,
|
void OnThreadCreated(uint32_t handle, ThreadState* thread_state,
|
||||||
kernel::XThread* thread);
|
Thread* thread);
|
||||||
void OnThreadExit(uint32_t thread_id);
|
void OnThreadExit(uint32_t thread_id);
|
||||||
void OnThreadDestroyed(uint32_t thread_id);
|
void OnThreadDestroyed(uint32_t thread_id);
|
||||||
void OnThreadEnteringWait(uint32_t thread_id);
|
void OnThreadEnteringWait(uint32_t thread_id);
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2017 Ben Vanik. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "xenia/cpu/thread.h"
|
||||||
|
#include "xenia/cpu/thread_state.h"
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace cpu {
|
||||||
|
|
||||||
|
thread_local Thread* Thread::current_thread_tls_ = nullptr;
|
||||||
|
|
||||||
|
Thread::Thread() {}
|
||||||
|
Thread::~Thread() {}
|
||||||
|
|
||||||
|
bool Thread::IsInThread() { return current_thread_tls_ != nullptr; }
|
||||||
|
|
||||||
|
Thread* Thread::GetCurrentThread() { return current_thread_tls_; }
|
||||||
|
uint32_t Thread::GetCurrentThreadId() {
|
||||||
|
return Thread::GetCurrentThread()->thread_state()->thread_id();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cpu
|
||||||
|
} // namespace xe
|
|
@ -0,0 +1,55 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* Xenia : Xbox 360 Emulator Research Project *
|
||||||
|
******************************************************************************
|
||||||
|
* Copyright 2017 Ben Vanik. All rights reserved. *
|
||||||
|
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||||
|
******************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef XENIA_CPU_THREAD_H_
|
||||||
|
#define XENIA_CPU_THREAD_H_
|
||||||
|
|
||||||
|
#include "xenia/base/threading.h"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace cpu {
|
||||||
|
|
||||||
|
class ThreadState;
|
||||||
|
|
||||||
|
// Represents a thread that runs guest code.
|
||||||
|
class Thread {
|
||||||
|
public:
|
||||||
|
Thread();
|
||||||
|
~Thread();
|
||||||
|
|
||||||
|
static bool IsInThread();
|
||||||
|
static Thread* GetCurrentThread();
|
||||||
|
static uint32_t GetCurrentThreadId();
|
||||||
|
ThreadState* thread_state() const { return thread_state_; }
|
||||||
|
|
||||||
|
// 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; }
|
||||||
|
|
||||||
|
xe::threading::Thread* thread() { return thread_.get(); }
|
||||||
|
const std::string& thread_name() const { return thread_name_; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static thread_local Thread* current_thread_tls_;
|
||||||
|
|
||||||
|
ThreadState* thread_state_ = nullptr;
|
||||||
|
std::unique_ptr<xe::threading::Thread> thread_ = nullptr;
|
||||||
|
|
||||||
|
bool can_debugger_suspend_ = true;
|
||||||
|
std::string thread_name_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace cpu
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
#endif // XENIA_CPU_THREAD_H_
|
|
@ -13,14 +13,9 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "xenia/base/x64_context.h"
|
#include "xenia/base/x64_context.h"
|
||||||
|
#include "xenia/cpu/thread.h"
|
||||||
#include "xenia/cpu/thread_state.h"
|
#include "xenia/cpu/thread_state.h"
|
||||||
|
|
||||||
namespace xe {
|
|
||||||
namespace kernel {
|
|
||||||
class XThread;
|
|
||||||
} // namespace kernel
|
|
||||||
} // namespace xe
|
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace cpu {
|
namespace cpu {
|
||||||
|
|
||||||
|
@ -53,8 +48,8 @@ struct ThreadDebugInfo {
|
||||||
// XThread::handle() of the thread.
|
// XThread::handle() of the thread.
|
||||||
// This will be invalidated when the thread dies.
|
// This will be invalidated when the thread dies.
|
||||||
uint32_t thread_handle = 0;
|
uint32_t thread_handle = 0;
|
||||||
// Kernel thread object. Only valid when the thread is alive.
|
// Thread object. Only valid when the thread is alive.
|
||||||
kernel::XThread* thread = nullptr;
|
Thread* thread = nullptr;
|
||||||
// Current state of the thread.
|
// Current state of the thread.
|
||||||
State state = State::kAlive;
|
State state = State::kAlive;
|
||||||
// Whether the debugger has forcefully suspended this thread.
|
// Whether the debugger has forcefully suspended this thread.
|
||||||
|
|
|
@ -288,7 +288,7 @@ void DebugWindow::DrawToolbar() {
|
||||||
current_thread_index = i;
|
current_thread_index = i;
|
||||||
}
|
}
|
||||||
if (thread_info->state != cpu::ThreadDebugInfo::State::kZombie) {
|
if (thread_info->state != cpu::ThreadDebugInfo::State::kZombie) {
|
||||||
thread_combo.Append(thread_info->thread->name());
|
thread_combo.Append(thread_info->thread->thread_name());
|
||||||
} else {
|
} else {
|
||||||
thread_combo.Append("(zombie)");
|
thread_combo.Append("(zombie)");
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,6 @@ const uint32_t XAPC::kDummyRundownRoutine;
|
||||||
using xe::cpu::ppc::PPCOpcode;
|
using xe::cpu::ppc::PPCOpcode;
|
||||||
|
|
||||||
uint32_t next_xthread_id_ = 0;
|
uint32_t next_xthread_id_ = 0;
|
||||||
thread_local XThread* current_thread_tls_ = nullptr;
|
|
||||||
|
|
||||||
XThread::XThread(KernelState* kernel_state)
|
XThread::XThread(KernelState* kernel_state)
|
||||||
: XObject(kernel_state, kTypeThread), guest_thread_(true) {}
|
: XObject(kernel_state, kTypeThread), guest_thread_(true) {}
|
||||||
|
@ -102,13 +101,14 @@ XThread::~XThread() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool XThread::IsInThread() { return Thread::IsInThread(); }
|
||||||
|
|
||||||
bool XThread::IsInThread(XThread* other) {
|
bool XThread::IsInThread(XThread* other) {
|
||||||
return current_thread_tls_ == other;
|
return current_thread_tls_ == other;
|
||||||
}
|
}
|
||||||
bool XThread::IsInThread() { return current_thread_tls_ != nullptr; }
|
|
||||||
|
|
||||||
XThread* XThread::GetCurrentThread() {
|
XThread* XThread::GetCurrentThread() {
|
||||||
XThread* thread = current_thread_tls_;
|
XThread* thread = reinterpret_cast<XThread*>(current_thread_tls_);
|
||||||
if (!thread) {
|
if (!thread) {
|
||||||
assert_always("Attempting to use kernel stuff from a non-kernel thread");
|
assert_always("Attempting to use kernel stuff from a non-kernel thread");
|
||||||
}
|
}
|
||||||
|
@ -142,12 +142,12 @@ void XThread::set_last_error(uint32_t error_code) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void XThread::set_name(const std::string& name) {
|
void XThread::set_name(const std::string& name) {
|
||||||
name_ = xe::format_string("%s (%.8X)", name.c_str(), handle());
|
thread_name_ = xe::format_string("%s (%.8X)", name.c_str(), handle());
|
||||||
|
|
||||||
if (thread_) {
|
if (thread_) {
|
||||||
// May be getting set before the thread is created.
|
// May be getting set before the thread is created.
|
||||||
// One the thread is ready it will handle it.
|
// One the thread is ready it will handle it.
|
||||||
thread_->set_name(name_);
|
thread_->set_name(thread_name_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,10 +393,13 @@ X_STATUS XThread::Create() {
|
||||||
XELOGE("CreateThread failed");
|
XELOGE("CreateThread failed");
|
||||||
return X_STATUS_NO_MEMORY;
|
return X_STATUS_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!FLAGS_ignore_thread_affinities) {
|
||||||
thread_->set_affinity_mask(proc_mask);
|
thread_->set_affinity_mask(proc_mask);
|
||||||
|
}
|
||||||
|
|
||||||
// Set the thread name based on host ID (for easier debugging).
|
// Set the thread name based on host ID (for easier debugging).
|
||||||
if (name_.empty()) {
|
if (thread_name_.empty()) {
|
||||||
char thread_name[32];
|
char thread_name[32];
|
||||||
snprintf(thread_name, xe::countof(thread_name), "XThread%.04X",
|
snprintf(thread_name, xe::countof(thread_name), "XThread%.04X",
|
||||||
thread_->system_id());
|
thread_->system_id());
|
||||||
|
@ -472,7 +475,7 @@ X_STATUS XThread::Terminate(int exit_code) {
|
||||||
|
|
||||||
void XThread::Execute() {
|
void XThread::Execute() {
|
||||||
XELOGKERNEL("XThread::Execute thid %d (handle=%.8X, '%s', native=%.8X)",
|
XELOGKERNEL("XThread::Execute thid %d (handle=%.8X, '%s', native=%.8X)",
|
||||||
thread_id_, handle(), name_.c_str(), thread_->system_id());
|
thread_id_, handle(), thread_name_.c_str(), thread_->system_id());
|
||||||
|
|
||||||
// Let the kernel know we are starting.
|
// Let the kernel know we are starting.
|
||||||
kernel_state()->OnThreadExecute(this);
|
kernel_state()->OnThreadExecute(this);
|
||||||
|
@ -852,7 +855,7 @@ bool XThread::Save(ByteStream* stream) {
|
||||||
}
|
}
|
||||||
|
|
||||||
stream->Write('THRD');
|
stream->Write('THRD');
|
||||||
stream->Write(name_);
|
stream->Write(thread_name_);
|
||||||
|
|
||||||
ThreadSavedState state;
|
ThreadSavedState state;
|
||||||
state.thread_id = thread_id_;
|
state.thread_id = thread_id_;
|
||||||
|
@ -918,7 +921,7 @@ object_ref<XThread> XThread::Restore(KernelState* kernel_state,
|
||||||
|
|
||||||
XELOGD("XThread %.8X", thread->handle());
|
XELOGD("XThread %.8X", thread->handle());
|
||||||
|
|
||||||
thread->name_ = stream->Read<std::string>();
|
thread->thread_name_ = stream->Read<std::string>();
|
||||||
|
|
||||||
ThreadSavedState state;
|
ThreadSavedState state;
|
||||||
stream->Read(&state, sizeof(ThreadSavedState));
|
stream->Read(&state, sizeof(ThreadSavedState));
|
||||||
|
@ -1030,7 +1033,7 @@ XHostThread::XHostThread(KernelState* kernel_state, uint32_t stack_size,
|
||||||
void XHostThread::Execute() {
|
void XHostThread::Execute() {
|
||||||
XELOGKERNEL(
|
XELOGKERNEL(
|
||||||
"XThread::Execute thid %d (handle=%.8X, '%s', native=%.8X, <host>)",
|
"XThread::Execute thid %d (handle=%.8X, '%s', native=%.8X, <host>)",
|
||||||
thread_id_, handle(), name_.c_str(), thread_->system_id());
|
thread_id_, handle(), thread_name_.c_str(), thread_->system_id());
|
||||||
|
|
||||||
// Let the kernel know we are starting.
|
// Let the kernel know we are starting.
|
||||||
kernel_state()->OnThreadExecute(this);
|
kernel_state()->OnThreadExecute(this);
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
|
|
||||||
#include "xenia/base/mutex.h"
|
#include "xenia/base/mutex.h"
|
||||||
#include "xenia/base/threading.h"
|
#include "xenia/base/threading.h"
|
||||||
|
#include "xenia/cpu/thread.h"
|
||||||
#include "xenia/cpu/thread_state.h"
|
#include "xenia/cpu/thread_state.h"
|
||||||
#include "xenia/kernel/util/native_list.h"
|
#include "xenia/kernel/util/native_list.h"
|
||||||
#include "xenia/kernel/xmutant.h"
|
#include "xenia/kernel/xmutant.h"
|
||||||
|
@ -102,7 +103,7 @@ struct X_KTHREAD {
|
||||||
};
|
};
|
||||||
static_assert_size(X_KTHREAD, 0xAB0);
|
static_assert_size(X_KTHREAD, 0xAB0);
|
||||||
|
|
||||||
class XThread : public XObject {
|
class XThread : public XObject, public cpu::Thread {
|
||||||
public:
|
public:
|
||||||
static const Type kType = kTypeThread;
|
static const Type kType = kTypeThread;
|
||||||
|
|
||||||
|
@ -136,18 +137,11 @@ class XThread : public XObject {
|
||||||
// True if the thread is created by the guest app.
|
// True if the thread is created by the guest app.
|
||||||
bool is_guest_thread() const { return guest_thread_; }
|
bool is_guest_thread() const { return guest_thread_; }
|
||||||
bool main_thread() const { return main_thread_; }
|
bool main_thread() const { return main_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_; }
|
bool is_running() const { return running_; }
|
||||||
|
|
||||||
cpu::ThreadState* thread_state() const { return thread_state_; }
|
|
||||||
uint32_t thread_id() const { return thread_id_; }
|
uint32_t thread_id() const { return thread_id_; }
|
||||||
uint32_t last_error();
|
uint32_t last_error();
|
||||||
void set_last_error(uint32_t error_code);
|
void set_last_error(uint32_t error_code);
|
||||||
const std::string& name() const { return name_; }
|
|
||||||
void set_name(const std::string& name);
|
void set_name(const std::string& name);
|
||||||
|
|
||||||
X_STATUS Create();
|
X_STATUS Create();
|
||||||
|
@ -211,7 +205,6 @@ class XThread : public XObject {
|
||||||
std::vector<object_ref<XMutant>> pending_mutant_acquires_;
|
std::vector<object_ref<XMutant>> pending_mutant_acquires_;
|
||||||
|
|
||||||
uint32_t thread_id_ = 0;
|
uint32_t thread_id_ = 0;
|
||||||
std::unique_ptr<xe::threading::Thread> thread_;
|
|
||||||
uint32_t scratch_address_ = 0;
|
uint32_t scratch_address_ = 0;
|
||||||
uint32_t scratch_size_ = 0;
|
uint32_t scratch_size_ = 0;
|
||||||
uint32_t tls_static_address_ = 0;
|
uint32_t tls_static_address_ = 0;
|
||||||
|
@ -222,14 +215,10 @@ class XThread : public XObject {
|
||||||
uint32_t stack_alloc_size_ = 0; // Stack alloc size
|
uint32_t stack_alloc_size_ = 0; // Stack alloc size
|
||||||
uint32_t stack_base_ = 0; // High address
|
uint32_t stack_base_ = 0; // High address
|
||||||
uint32_t stack_limit_ = 0; // Low address
|
uint32_t stack_limit_ = 0; // Low address
|
||||||
cpu::ThreadState* thread_state_ = nullptr;
|
|
||||||
bool guest_thread_ = false;
|
bool guest_thread_ = false;
|
||||||
bool main_thread_ = false; // Entry-point thread
|
bool main_thread_ = false; // Entry-point thread
|
||||||
bool can_debugger_suspend_ = true;
|
|
||||||
bool running_ = false;
|
bool running_ = false;
|
||||||
|
|
||||||
std::string name_;
|
|
||||||
|
|
||||||
int32_t priority_ = 0;
|
int32_t priority_ = 0;
|
||||||
uint32_t affinity_ = 0;
|
uint32_t affinity_ = 0;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue