Thread state updates.
This commit is contained in:
parent
88596611d1
commit
8d4f54e240
|
@ -32,7 +32,7 @@ class ThreadState {
|
||||||
void set_name(const std::string& value) { name_ = value; }
|
void set_name(const std::string& value) { name_ = value; }
|
||||||
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_; }
|
||||||
size_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 thread_state_address() const { return thread_state_address_; }
|
||||||
xe::cpu::frontend::PPCContext* context() const { return context_; }
|
xe::cpu::frontend::PPCContext* context() const { return context_; }
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ void XEvent::InitializeNative(void* native_ptr, DISPATCH_HEADER& header) {
|
||||||
assert_null(handle_);
|
assert_null(handle_);
|
||||||
|
|
||||||
bool manual_reset;
|
bool manual_reset;
|
||||||
switch (header.type_flags >> 24) {
|
switch ((header.type_flags >> 24) & 0xFF) {
|
||||||
case 0x00: // EventNotificationObject (manual reset)
|
case 0x00: // EventNotificationObject (manual reset)
|
||||||
manual_reset = true;
|
manual_reset = true;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -91,7 +91,7 @@ XThread* XThread::GetCurrentThread() {
|
||||||
XThread::EnterCriticalRegion();
|
XThread::EnterCriticalRegion();
|
||||||
thread = shared_kernel_thread_;
|
thread = shared_kernel_thread_;
|
||||||
if (!thread) {
|
if (!thread) {
|
||||||
thread = new XThread(KernelState::shared(), 32 * 1024, 0, 0, 0, 0);
|
thread = new XThread(KernelState::shared(), 256 * 1024, 0, 0, 0, 0);
|
||||||
shared_kernel_thread_ = thread;
|
shared_kernel_thread_ = thread;
|
||||||
current_thread_tls = thread;
|
current_thread_tls = thread;
|
||||||
}
|
}
|
||||||
|
@ -137,7 +137,7 @@ 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(2048);
|
thread_state_address_ = memory()->SystemHeapAlloc(0xAB0);
|
||||||
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;
|
||||||
|
@ -169,21 +169,43 @@ X_STATUS XThread::Create() {
|
||||||
|
|
||||||
// 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, tls_address_);
|
xe::store_and_swap<uint32_t>(p + 0x000, 6);
|
||||||
|
xe::store_and_swap<uint32_t>(p + 0x008, thread_state_address_ + 0x008);
|
||||||
|
xe::store_and_swap<uint32_t>(p + 0x00C, thread_state_address_ + 0x008);
|
||||||
|
xe::store_and_swap<uint32_t>(p + 0x010, thread_state_address_ + 0x010);
|
||||||
|
xe::store_and_swap<uint32_t>(p + 0x014, thread_state_address_ + 0x010);
|
||||||
|
xe::store_and_swap<uint32_t>(p + 0x040, thread_state_address_ + 0x018 + 8);
|
||||||
|
xe::store_and_swap<uint32_t>(p + 0x044, thread_state_address_ + 0x018 + 8);
|
||||||
|
xe::store_and_swap<uint32_t>(p + 0x048, thread_state_address_);
|
||||||
|
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 + 0x056, 1);
|
||||||
|
xe::store_and_swap<uint32_t>(p + 0x068, tls_address_);
|
||||||
|
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 + 0x078, thread_state_address_ + 0x074);
|
||||||
|
xe::store_and_swap<uint32_t>(p + 0x07C, thread_state_address_ + 0x07C);
|
||||||
|
xe::store_and_swap<uint32_t>(p + 0x080, thread_state_address_ + 0x07C);
|
||||||
|
xe::store_and_swap<uint8_t>(p + 0x08B, 1);
|
||||||
|
// D4 = APC
|
||||||
|
// FC = semaphore (ptr, 0, 2)
|
||||||
|
// A88 = APC
|
||||||
|
// 18 = timer
|
||||||
|
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 + 0x100, thread_state_address_);
|
||||||
|
|
||||||
FILETIME t;
|
FILETIME t;
|
||||||
GetSystemTimeAsFileTime(&t);
|
GetSystemTimeAsFileTime(&t);
|
||||||
xe::store_and_swap<uint64_t>(
|
xe::store_and_swap<uint64_t>(
|
||||||
p + 0x130, ((uint64_t)t.dwHighDateTime << 32) | t.dwLowDateTime);
|
p + 0x130, ((uint64_t)t.dwHighDateTime << 32) | t.dwLowDateTime);
|
||||||
|
|
||||||
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_);
|
||||||
xe::store_and_swap<uint32_t>(p + 0x150, 0); // ?
|
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 + 0x17C, 1);
|
||||||
|
|
||||||
// Allocate processor thread state.
|
// Allocate processor thread state.
|
||||||
// This is thread safe.
|
// This is thread safe.
|
||||||
|
@ -191,6 +213,14 @@ X_STATUS XThread::Create() {
|
||||||
new ThreadState(kernel_state()->processor(), thread_id_, 0,
|
new ThreadState(kernel_state()->processor(), thread_id_, 0,
|
||||||
creation_params_.stack_size, thread_state_address_);
|
creation_params_.stack_size, thread_state_address_);
|
||||||
|
|
||||||
|
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_);
|
||||||
|
|
||||||
X_STATUS return_code = PlatformCreate();
|
X_STATUS return_code = PlatformCreate();
|
||||||
if (XFAILED(return_code)) {
|
if (XFAILED(return_code)) {
|
||||||
XELOGW("Unable to create platform thread (%.8X)", return_code);
|
XELOGW("Unable to create platform thread (%.8X)", return_code);
|
||||||
|
@ -242,9 +272,8 @@ static uint32_t __stdcall XThreadStartCallbackWin32(void* param) {
|
||||||
X_STATUS XThread::PlatformCreate() {
|
X_STATUS XThread::PlatformCreate() {
|
||||||
bool suspended = creation_params_.creation_flags & 0x1;
|
bool suspended = creation_params_.creation_flags & 0x1;
|
||||||
thread_handle_ =
|
thread_handle_ =
|
||||||
CreateThread(NULL, 0,
|
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)XThreadStartCallbackWin32,
|
||||||
(LPTHREAD_START_ROUTINE)XThreadStartCallbackWin32, this,
|
this, suspended ? CREATE_SUSPENDED : 0, NULL);
|
||||||
suspended ? CREATE_SUSPENDED : 0, NULL);
|
|
||||||
if (!thread_handle_) {
|
if (!thread_handle_) {
|
||||||
uint32_t last_error = GetLastError();
|
uint32_t last_error = GetLastError();
|
||||||
// TODO(benvanik): translate?
|
// TODO(benvanik): translate?
|
||||||
|
@ -289,7 +318,7 @@ X_STATUS XThread::PlatformCreate() {
|
||||||
|
|
||||||
pthread_attr_init(&attr);
|
pthread_attr_init(&attr);
|
||||||
// TODO(benvanik): this shouldn't be necessary
|
// TODO(benvanik): this shouldn't be necessary
|
||||||
//pthread_attr_setstacksize(&attr, creation_params_.stack_size);
|
// pthread_attr_setstacksize(&attr, creation_params_.stack_size);
|
||||||
|
|
||||||
int result_code;
|
int result_code;
|
||||||
if (creation_params_.creation_flags & 0x1) {
|
if (creation_params_.creation_flags & 0x1) {
|
||||||
|
@ -428,9 +457,8 @@ void XThread::DeliverAPCs(void* data) {
|
||||||
// kernel_routine(apc_address, &normal_routine, &normal_context,
|
// kernel_routine(apc_address, &normal_routine, &normal_context,
|
||||||
// &system_arg1, &system_arg2)
|
// &system_arg1, &system_arg2)
|
||||||
uint64_t kernel_args[] = {
|
uint64_t kernel_args[] = {
|
||||||
apc_address, thread->scratch_address_ + 0,
|
apc_address, thread->scratch_address_ + 0, thread->scratch_address_ + 4,
|
||||||
thread->scratch_address_ + 4, thread->scratch_address_ + 8,
|
thread->scratch_address_ + 8, thread->scratch_address_ + 12,
|
||||||
thread->scratch_address_ + 12,
|
|
||||||
};
|
};
|
||||||
processor->ExecuteInterrupt(0, kernel_routine, kernel_args,
|
processor->ExecuteInterrupt(0, kernel_routine, kernel_args,
|
||||||
xe::countof(kernel_args));
|
xe::countof(kernel_args));
|
||||||
|
|
|
@ -154,22 +154,16 @@ X_STATUS XObject::WaitMultiple(uint32_t count, XObject** objects,
|
||||||
void XObject::SetNativePointer(uint32_t native_ptr) {
|
void XObject::SetNativePointer(uint32_t native_ptr) {
|
||||||
std::lock_guard<std::mutex> lock(kernel_state_->object_mutex());
|
std::lock_guard<std::mutex> lock(kernel_state_->object_mutex());
|
||||||
|
|
||||||
auto header_be =
|
auto header =
|
||||||
kernel_state_->memory()->TranslateVirtual<DISPATCH_HEADER*>(native_ptr);
|
kernel_state_->memory()->TranslateVirtual<DISPATCH_HEADER*>(native_ptr);
|
||||||
DISPATCH_HEADER header;
|
|
||||||
header.type_flags = xe::byte_swap(header_be->type_flags);
|
|
||||||
header.signal_state = xe::byte_swap(header_be->signal_state);
|
|
||||||
header.wait_list_flink = xe::byte_swap(header_be->wait_list_flink);
|
|
||||||
header.wait_list_blink = xe::byte_swap(header_be->wait_list_blink);
|
|
||||||
|
|
||||||
assert_true(!(header.wait_list_blink & 0x1));
|
assert_true(!(header->wait_list_blink & 0x1));
|
||||||
|
|
||||||
// Stash pointer in struct.
|
// Stash pointer in struct.
|
||||||
uint64_t object_ptr = reinterpret_cast<uint64_t>(this);
|
uint64_t object_ptr = reinterpret_cast<uint64_t>(this);
|
||||||
object_ptr |= 0x1;
|
object_ptr |= 0x1;
|
||||||
header_be->wait_list_flink = xe::byte_swap((uint32_t)(object_ptr >> 32));
|
header->wait_list_flink = (uint32_t)(object_ptr >> 32);
|
||||||
header_be->wait_list_blink =
|
header->wait_list_blink = (uint32_t)(object_ptr & 0xFFFFFFFF);
|
||||||
xe::byte_swap((uint32_t)(object_ptr & 0xFFFFFFFF));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
XObject* XObject::GetObject(KernelState* kernel_state, void* native_ptr,
|
XObject* XObject::GetObject(KernelState* kernel_state, void* native_ptr,
|
||||||
|
@ -185,21 +179,16 @@ XObject* XObject::GetObject(KernelState* kernel_state, void* native_ptr,
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(kernel_state->object_mutex());
|
std::lock_guard<std::mutex> lock(kernel_state->object_mutex());
|
||||||
|
|
||||||
DISPATCH_HEADER* header_be = (DISPATCH_HEADER*)native_ptr;
|
auto header = reinterpret_cast<DISPATCH_HEADER*>(native_ptr);
|
||||||
DISPATCH_HEADER header;
|
|
||||||
header.type_flags = xe::byte_swap(header_be->type_flags);
|
|
||||||
header.signal_state = xe::byte_swap(header_be->signal_state);
|
|
||||||
header.wait_list_flink = xe::byte_swap(header_be->wait_list_flink);
|
|
||||||
header.wait_list_blink = xe::byte_swap(header_be->wait_list_blink);
|
|
||||||
|
|
||||||
if (as_type == -1) {
|
if (as_type == -1) {
|
||||||
as_type = (header.type_flags >> 24) & 0xFF;
|
as_type = (header->type_flags >> 24) & 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (header.wait_list_blink & 0x1) {
|
if (header->wait_list_blink & 0x1) {
|
||||||
// Already initialized.
|
// Already initialized.
|
||||||
uint64_t object_ptr = ((uint64_t)header.wait_list_flink << 32) |
|
uint64_t object_ptr = ((uint64_t)header->wait_list_flink << 32) |
|
||||||
((header.wait_list_blink) & ~0x1);
|
((header->wait_list_blink) & ~0x1);
|
||||||
XObject* object = reinterpret_cast<XObject*>(object_ptr);
|
XObject* object = reinterpret_cast<XObject*>(object_ptr);
|
||||||
// TODO(benvanik): assert nothing has been changed in the struct.
|
// TODO(benvanik): assert nothing has been changed in the struct.
|
||||||
return object;
|
return object;
|
||||||
|
@ -212,19 +201,19 @@ XObject* XObject::GetObject(KernelState* kernel_state, void* native_ptr,
|
||||||
case 1: // EventSynchronizationObject
|
case 1: // EventSynchronizationObject
|
||||||
{
|
{
|
||||||
XEvent* ev = new XEvent(kernel_state);
|
XEvent* ev = new XEvent(kernel_state);
|
||||||
ev->InitializeNative(native_ptr, header);
|
ev->InitializeNative(native_ptr, *header);
|
||||||
object = ev;
|
object = ev;
|
||||||
} break;
|
} break;
|
||||||
case 2: // MutantObject
|
case 2: // MutantObject
|
||||||
{
|
{
|
||||||
XMutant* mutant = new XMutant(kernel_state);
|
XMutant* mutant = new XMutant(kernel_state);
|
||||||
mutant->InitializeNative(native_ptr, header);
|
mutant->InitializeNative(native_ptr, *header);
|
||||||
object = mutant;
|
object = mutant;
|
||||||
} break;
|
} break;
|
||||||
case 5: // SemaphoreObject
|
case 5: // SemaphoreObject
|
||||||
{
|
{
|
||||||
XSemaphore* sem = new XSemaphore(kernel_state);
|
XSemaphore* sem = new XSemaphore(kernel_state);
|
||||||
sem->InitializeNative(native_ptr, header);
|
sem->InitializeNative(native_ptr, *header);
|
||||||
object = sem;
|
object = sem;
|
||||||
} break;
|
} break;
|
||||||
case 3: // ProcessObject
|
case 3: // ProcessObject
|
||||||
|
@ -248,9 +237,8 @@ XObject* XObject::GetObject(KernelState* kernel_state, void* native_ptr,
|
||||||
// Stash pointer in struct.
|
// Stash pointer in struct.
|
||||||
uint64_t object_ptr = reinterpret_cast<uint64_t>(object);
|
uint64_t object_ptr = reinterpret_cast<uint64_t>(object);
|
||||||
object_ptr |= 0x1;
|
object_ptr |= 0x1;
|
||||||
header_be->wait_list_flink = xe::byte_swap((uint32_t)(object_ptr >> 32));
|
header->wait_list_flink = (uint32_t)(object_ptr >> 32);
|
||||||
header_be->wait_list_blink =
|
header->wait_list_blink = (uint32_t)(object_ptr & 0xFFFFFFFF);
|
||||||
xe::byte_swap((uint32_t)(object_ptr & 0xFFFFFFFF));
|
|
||||||
|
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,10 +20,10 @@ namespace kernel {
|
||||||
|
|
||||||
// http://www.nirsoft.net/kernel_struct/vista/DISPATCHER_HEADER.html
|
// http://www.nirsoft.net/kernel_struct/vista/DISPATCHER_HEADER.html
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t type_flags;
|
xe::be<uint32_t> type_flags;
|
||||||
uint32_t signal_state;
|
xe::be<uint32_t> signal_state;
|
||||||
uint32_t wait_list_flink;
|
xe::be<uint32_t> wait_list_flink;
|
||||||
uint32_t wait_list_blink;
|
xe::be<uint32_t> wait_list_blink;
|
||||||
} DISPATCH_HEADER;
|
} DISPATCH_HEADER;
|
||||||
|
|
||||||
class XObject {
|
class XObject {
|
||||||
|
|
Loading…
Reference in New Issue