Starting to clean up thread state.
This commit is contained in:
parent
147a70b9c1
commit
da630cc159
|
@ -197,9 +197,9 @@ class TestRunner {
|
||||||
// Simulate a thread.
|
// Simulate a thread.
|
||||||
uint32_t stack_size = 64 * 1024;
|
uint32_t stack_size = 64 * 1024;
|
||||||
uint32_t stack_address = START_ADDRESS - stack_size;
|
uint32_t stack_address = START_ADDRESS - stack_size;
|
||||||
uint32_t thread_state_address = stack_address - 0x1000;
|
uint32_t pcr_address = stack_address - 0x1000;
|
||||||
thread_state.reset(new ThreadState(processor.get(), 0x100, stack_address,
|
thread_state.reset(new ThreadState(processor.get(), 0x100, stack_address,
|
||||||
stack_size, thread_state_address));
|
stack_size, pcr_address));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,14 +28,14 @@ thread_local ThreadState* thread_state_ = nullptr;
|
||||||
|
|
||||||
ThreadState::ThreadState(Processor* processor, uint32_t thread_id,
|
ThreadState::ThreadState(Processor* processor, uint32_t thread_id,
|
||||||
uint32_t stack_address, uint32_t stack_size,
|
uint32_t stack_address, uint32_t stack_size,
|
||||||
uint32_t thread_state_address)
|
uint32_t pcr_address)
|
||||||
: processor_(processor),
|
: processor_(processor),
|
||||||
memory_(processor->memory()),
|
memory_(processor->memory()),
|
||||||
thread_id_(thread_id),
|
thread_id_(thread_id),
|
||||||
name_(""),
|
name_(""),
|
||||||
backend_data_(0),
|
backend_data_(0),
|
||||||
stack_size_(stack_size),
|
stack_size_(stack_size),
|
||||||
thread_state_address_(thread_state_address) {
|
pcr_address_(pcr_address) {
|
||||||
if (thread_id_ == UINT_MAX) {
|
if (thread_id_ == UINT_MAX) {
|
||||||
// System thread. Assign the system thread ID with a high bit
|
// System thread. Assign the system thread ID with a high bit
|
||||||
// set so people know what's up.
|
// set so people know what's up.
|
||||||
|
@ -87,7 +87,7 @@ ThreadState::ThreadState(Processor* processor, uint32_t thread_id,
|
||||||
|
|
||||||
// Set initial registers.
|
// Set initial registers.
|
||||||
context_->r[1] = stack_position;
|
context_->r[1] = stack_position;
|
||||||
context_->r[13] = thread_state_address_;
|
context_->r[13] = pcr_address_;
|
||||||
|
|
||||||
// Pad out stack a bit, as some games seem to overwrite the caller by about
|
// Pad out stack a bit, as some games seem to overwrite the caller by about
|
||||||
// 16 to 32b.
|
// 16 to 32b.
|
||||||
|
|
|
@ -22,7 +22,7 @@ class Processor;
|
||||||
class ThreadState {
|
class ThreadState {
|
||||||
public:
|
public:
|
||||||
ThreadState(Processor* processor, uint32_t thread_id, uint32_t stack_address,
|
ThreadState(Processor* processor, uint32_t thread_id, uint32_t stack_address,
|
||||||
uint32_t stack_size, uint32_t thread_state_address);
|
uint32_t stack_size, uint32_t pcr_address);
|
||||||
~ThreadState();
|
~ThreadState();
|
||||||
|
|
||||||
Processor* processor() const { return processor_; }
|
Processor* processor() const { return processor_; }
|
||||||
|
@ -33,7 +33,7 @@ class ThreadState {
|
||||||
void* backend_data() const { return backend_data_; }
|
void* backend_data() const { return backend_data_; }
|
||||||
uint32_t stack_address() const { return stack_address_; }
|
uint32_t stack_address() const { return stack_address_; }
|
||||||
uint32_t stack_size() const { return stack_size_; }
|
uint32_t stack_size() const { return stack_size_; }
|
||||||
uint32_t thread_state_address() const { return thread_state_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() { return Suspend(~0); }
|
||||||
|
@ -53,7 +53,7 @@ class ThreadState {
|
||||||
uint32_t stack_address_;
|
uint32_t stack_address_;
|
||||||
bool stack_allocated_;
|
bool stack_allocated_;
|
||||||
uint32_t stack_size_;
|
uint32_t stack_size_;
|
||||||
uint32_t thread_state_address_;
|
uint32_t pcr_address_;
|
||||||
|
|
||||||
// NOTE: must be 64b aligned for SSE ops.
|
// NOTE: must be 64b aligned for SSE ops.
|
||||||
xe::cpu::frontend::PPCContext* context_;
|
xe::cpu::frontend::PPCContext* context_;
|
||||||
|
|
|
@ -34,6 +34,7 @@ XThread::XThread(KernelState* kernel_state, uint32_t stack_size,
|
||||||
: XObject(kernel_state, kTypeThread),
|
: XObject(kernel_state, kTypeThread),
|
||||||
thread_id_(++next_xthread_id),
|
thread_id_(++next_xthread_id),
|
||||||
thread_handle_(0),
|
thread_handle_(0),
|
||||||
|
pcr_address_(0),
|
||||||
thread_state_address_(0),
|
thread_state_address_(0),
|
||||||
thread_state_(0),
|
thread_state_(0),
|
||||||
event_(NULL),
|
event_(NULL),
|
||||||
|
@ -76,7 +77,7 @@ XThread::~XThread() {
|
||||||
}
|
}
|
||||||
kernel_state()->memory()->SystemHeapFree(scratch_address_);
|
kernel_state()->memory()->SystemHeapFree(scratch_address_);
|
||||||
kernel_state()->memory()->SystemHeapFree(tls_address_);
|
kernel_state()->memory()->SystemHeapFree(tls_address_);
|
||||||
kernel_state()->memory()->SystemHeapFree(thread_state_address_);
|
kernel_state()->memory()->SystemHeapFree(pcr_address_);
|
||||||
|
|
||||||
if (thread_handle_) {
|
if (thread_handle_) {
|
||||||
// TODO(benvanik): platform kill
|
// TODO(benvanik): platform kill
|
||||||
|
@ -137,7 +138,8 @@ X_STATUS XThread::Create() {
|
||||||
// 0x160: last error
|
// 0x160: last error
|
||||||
// So, at offset 0x100 we have a 4b pointer to offset 200, then have the
|
// So, at offset 0x100 we have a 4b pointer to offset 200, then have the
|
||||||
// structure.
|
// structure.
|
||||||
thread_state_address_ = memory()->SystemHeapAlloc(0xAB0);
|
pcr_address_ = memory()->SystemHeapAlloc(0x2D8 + 0xAB0);
|
||||||
|
thread_state_address_ = pcr_address_ + 0x2D8;
|
||||||
if (!thread_state_address_) {
|
if (!thread_state_address_) {
|
||||||
XELOGW("Unable to allocate thread state block");
|
XELOGW("Unable to allocate thread state block");
|
||||||
return X_STATUS_NO_MEMORY;
|
return X_STATUS_NO_MEMORY;
|
||||||
|
@ -167,6 +169,23 @@ X_STATUS XThread::Create() {
|
||||||
// TODO(benvanik): is this correct?
|
// TODO(benvanik): is this correct?
|
||||||
memory()->Copy(tls_address_, header->tls_info.raw_data_address, tls_size);
|
memory()->Copy(tls_address_, header->tls_info.raw_data_address, tls_size);
|
||||||
|
|
||||||
|
// Allocate processor thread state.
|
||||||
|
// This is thread safe.
|
||||||
|
thread_state_ = new ThreadState(kernel_state()->processor(), thread_id_, 0,
|
||||||
|
creation_params_.stack_size, pcr_address_);
|
||||||
|
XELOGI("XThread%04X (%X) Stack: %.8X-%.8X", handle(),
|
||||||
|
thread_state_->thread_id(), thread_state_->stack_address(),
|
||||||
|
thread_state_->stack_address() + thread_state_->stack_size());
|
||||||
|
|
||||||
|
uint8_t* pcr = memory()->TranslateVirtual(pcr_address_);
|
||||||
|
xe::store_and_swap<uint32_t>(pcr + 0x000, tls_address_);
|
||||||
|
xe::store_and_swap<uint32_t>(pcr + 0x030, pcr_address_);
|
||||||
|
xe::store_and_swap<uint32_t>(pcr + 0x070, thread_state_->stack_address() +
|
||||||
|
thread_state_->stack_size());
|
||||||
|
xe::store_and_swap<uint32_t>(pcr + 0x074, thread_state_->stack_address());
|
||||||
|
xe::store_and_swap<uint32_t>(pcr + 0x100, thread_state_address_);
|
||||||
|
xe::store_and_swap<uint32_t>(pcr + 0x150, 0); // DPC active bool?
|
||||||
|
|
||||||
// Setup the thread state block (last error/etc).
|
// Setup the thread state block (last error/etc).
|
||||||
uint8_t* p = memory()->TranslateVirtual(thread_state_address_);
|
uint8_t* p = memory()->TranslateVirtual(thread_state_address_);
|
||||||
xe::store_and_swap<uint32_t>(p + 0x000, 6);
|
xe::store_and_swap<uint32_t>(p + 0x000, 6);
|
||||||
|
@ -180,6 +199,9 @@ X_STATUS XThread::Create() {
|
||||||
xe::store_and_swap<uint32_t>(p + 0x04C, thread_state_address_ + 0x018);
|
xe::store_and_swap<uint32_t>(p + 0x04C, thread_state_address_ + 0x018);
|
||||||
xe::store_and_swap<uint16_t>(p + 0x054, 0x102);
|
xe::store_and_swap<uint16_t>(p + 0x054, 0x102);
|
||||||
xe::store_and_swap<uint16_t>(p + 0x056, 1);
|
xe::store_and_swap<uint16_t>(p + 0x056, 1);
|
||||||
|
xe::store_and_swap<uint32_t>(
|
||||||
|
p + 0x05C, thread_state_->stack_address() + thread_state_->stack_size());
|
||||||
|
xe::store_and_swap<uint32_t>(p + 0x060, thread_state_->stack_address());
|
||||||
xe::store_and_swap<uint32_t>(p + 0x068, tls_address_);
|
xe::store_and_swap<uint32_t>(p + 0x068, tls_address_);
|
||||||
xe::store_and_swap<uint8_t>(p + 0x06C, 0);
|
xe::store_and_swap<uint8_t>(p + 0x06C, 0);
|
||||||
xe::store_and_swap<uint32_t>(p + 0x074, thread_state_address_ + 0x074);
|
xe::store_and_swap<uint32_t>(p + 0x074, thread_state_address_ + 0x074);
|
||||||
|
@ -192,7 +214,8 @@ X_STATUS XThread::Create() {
|
||||||
// A88 = APC
|
// A88 = APC
|
||||||
// 18 = timer
|
// 18 = timer
|
||||||
xe::store_and_swap<uint32_t>(p + 0x09C, 0xFDFFD7FF);
|
xe::store_and_swap<uint32_t>(p + 0x09C, 0xFDFFD7FF);
|
||||||
xe::store_and_swap<uint32_t>(p + 0x100, thread_state_address_);
|
xe::store_and_swap<uint32_t>(
|
||||||
|
p + 0x0D0, thread_state_->stack_address() + thread_state_->stack_size());
|
||||||
FILETIME t;
|
FILETIME t;
|
||||||
GetSystemTimeAsFileTime(&t);
|
GetSystemTimeAsFileTime(&t);
|
||||||
xe::store_and_swap<uint64_t>(
|
xe::store_and_swap<uint64_t>(
|
||||||
|
@ -200,29 +223,13 @@ X_STATUS XThread::Create() {
|
||||||
xe::store_and_swap<uint32_t>(p + 0x144, thread_state_address_ + 0x144);
|
xe::store_and_swap<uint32_t>(p + 0x144, thread_state_address_ + 0x144);
|
||||||
xe::store_and_swap<uint32_t>(p + 0x148, thread_state_address_ + 0x144);
|
xe::store_and_swap<uint32_t>(p + 0x148, thread_state_address_ + 0x144);
|
||||||
xe::store_and_swap<uint32_t>(p + 0x14C, thread_id_);
|
xe::store_and_swap<uint32_t>(p + 0x14C, thread_id_);
|
||||||
// TODO(benvanik): figure out why RtlGetLastError changes on this:
|
xe::store_and_swap<uint32_t>(p + 0x150, creation_params_.start_address);
|
||||||
// xe::store_and_swap<uint32_t>(p + 0x150, creation_params_.start_address);
|
|
||||||
xe::store_and_swap<uint32_t>(p + 0x154, thread_state_address_ + 0x154);
|
xe::store_and_swap<uint32_t>(p + 0x154, thread_state_address_ + 0x154);
|
||||||
xe::store_and_swap<uint32_t>(p + 0x158, thread_state_address_ + 0x154);
|
xe::store_and_swap<uint32_t>(p + 0x158, thread_state_address_ + 0x154);
|
||||||
xe::store_and_swap<uint32_t>(p + 0x160, 0); // last error
|
xe::store_and_swap<uint32_t>(p + 0x160, 0); // last error
|
||||||
xe::store_and_swap<uint32_t>(p + 0x16C, creation_params_.creation_flags);
|
xe::store_and_swap<uint32_t>(p + 0x16C, creation_params_.creation_flags);
|
||||||
xe::store_and_swap<uint32_t>(p + 0x17C, 1);
|
xe::store_and_swap<uint32_t>(p + 0x17C, 1);
|
||||||
|
|
||||||
// Allocate processor thread state.
|
|
||||||
// This is thread safe.
|
|
||||||
thread_state_ =
|
|
||||||
new ThreadState(kernel_state()->processor(), thread_id_, 0,
|
|
||||||
creation_params_.stack_size, thread_state_address_);
|
|
||||||
XELOGI("XThread%04X (%X) Stack: %.8X-%.8X", handle(),
|
|
||||||
thread_state_->thread_id(), thread_state_->stack_address(),
|
|
||||||
thread_state_->stack_address() + thread_state_->stack_size());
|
|
||||||
|
|
||||||
xe::store_and_swap<uint32_t>(
|
|
||||||
p + 0x05C, thread_state_->stack_address() + thread_state_->stack_size());
|
|
||||||
xe::store_and_swap<uint32_t>(p + 0x060, thread_state_->stack_address());
|
|
||||||
xe::store_and_swap<uint32_t>(
|
|
||||||
p + 0x0D0, thread_state_->stack_address() + thread_state_->stack_size());
|
|
||||||
|
|
||||||
SetNativePointer(thread_state_address_);
|
SetNativePointer(thread_state_address_);
|
||||||
|
|
||||||
X_STATUS return_code = PlatformCreate();
|
X_STATUS return_code = PlatformCreate();
|
||||||
|
|
|
@ -35,6 +35,7 @@ class XThread : public XObject {
|
||||||
static uint32_t GetCurrentThreadHandle();
|
static uint32_t GetCurrentThreadHandle();
|
||||||
static uint32_t GetCurrentThreadId(const uint8_t* thread_state_block);
|
static uint32_t GetCurrentThreadId(const uint8_t* thread_state_block);
|
||||||
|
|
||||||
|
uint32_t pcr_ptr() const { return pcr_address_; }
|
||||||
uint32_t thread_state_ptr() const { return thread_state_address_; }
|
uint32_t thread_state_ptr() const { return thread_state_address_; }
|
||||||
cpu::ThreadState* thread_state() const { return thread_state_; }
|
cpu::ThreadState* thread_state() const { return thread_state_; }
|
||||||
uint32_t thread_id() const { return thread_id_; }
|
uint32_t thread_id() const { return thread_id_; }
|
||||||
|
@ -89,6 +90,7 @@ class XThread : public XObject {
|
||||||
uint32_t scratch_address_;
|
uint32_t scratch_address_;
|
||||||
uint32_t scratch_size_;
|
uint32_t scratch_size_;
|
||||||
uint32_t tls_address_;
|
uint32_t tls_address_;
|
||||||
|
uint32_t pcr_address_;
|
||||||
uint32_t thread_state_address_;
|
uint32_t thread_state_address_;
|
||||||
cpu::ThreadState* thread_state_;
|
cpu::ThreadState* thread_state_;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue