Merge pull request #275 from DrChat/thread_cleanup
Cleanup some XThread code
This commit is contained in:
commit
54b94ac22f
|
@ -155,25 +155,6 @@ X_STATUS XThread::Create() {
|
|||
return X_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
// Allocate thread state block from heap.
|
||||
// This is set as r13 for user code and some special inlined Win32 calls
|
||||
// (like GetLastError/etc) will poke it directly.
|
||||
// We try to use it as our primary store of data just to keep things all
|
||||
// consistent.
|
||||
// 0x000: pointer to tls data
|
||||
// 0x100: pointer to self?
|
||||
// 0x14C: thread id
|
||||
// 0x150: if >0 then error states don't get set
|
||||
// 0x160: last error
|
||||
// So, at offset 0x100 we have a 4b pointer to offset 200, then have the
|
||||
// structure.
|
||||
pcr_address_ = memory()->SystemHeapAlloc(0x2D8 + 0xAB0);
|
||||
thread_state_address_ = pcr_address_ + 0x2D8;
|
||||
if (!pcr_address_) {
|
||||
XELOGW("Unable to allocate thread state block");
|
||||
return X_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
auto module = kernel_state()->GetExecutableModule();
|
||||
|
||||
// Allocate thread scratch.
|
||||
|
@ -217,6 +198,31 @@ X_STATUS XThread::Create() {
|
|||
header->tls_info.raw_data_size);
|
||||
}
|
||||
|
||||
// Allocate thread state block from heap.
|
||||
// http://www.microsoft.com/msj/archive/s2ce.aspx
|
||||
// This is set as r13 for user code and some special inlined Win32 calls
|
||||
// (like GetLastError/etc) will poke it directly.
|
||||
// We try to use it as our primary store of data just to keep things all
|
||||
// consistent.
|
||||
// 0x000: pointer to tls data
|
||||
// 0x100: pointer to TEB(?)
|
||||
// 0x10C: Current CPU(?)
|
||||
// 0x150: if >0 then error states don't get set (DPC active bool?)
|
||||
// TEB:
|
||||
// 0x14C: thread id
|
||||
// 0x160: last error
|
||||
// So, at offset 0x100 we have a 4b pointer to offset 200, then have the
|
||||
// structure.
|
||||
pcr_address_ = memory()->SystemHeapAlloc(0x2D8 + 0xAB0);
|
||||
thread_state_address_ = pcr_address_ + 0x2D8;
|
||||
if (!pcr_address_) {
|
||||
XELOGW("Unable to allocate thread state block");
|
||||
return X_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
// Zero everything
|
||||
memory()->Zero(pcr_address_, 0x2D8 + 0xAB0);
|
||||
|
||||
// Allocate processor thread state.
|
||||
// This is thread safe.
|
||||
thread_state_ = new ThreadState(kernel_state()->processor(), thread_id_,
|
||||
|
@ -232,29 +238,56 @@ X_STATUS XThread::Create() {
|
|||
uint8_t proc_mask =
|
||||
static_cast<uint8_t>(creation_params_.creation_flags >> 24);
|
||||
|
||||
uint8_t* pcr = memory()->TranslateVirtual(pcr_address_);
|
||||
std::memset(pcr, 0x0, 0x2D8 + 0xAB0); // Zero the PCR
|
||||
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<uint8_t>(pcr + 0x10C,
|
||||
GetFakeCpuNumber(proc_mask)); // Current CPU(?)
|
||||
xe::store_and_swap<uint32_t>(pcr + 0x150, 0); // DPC active bool?
|
||||
// Processor Control Region
|
||||
struct XPCR {
|
||||
xe::be<uint32_t> tls_ptr; // 0x0
|
||||
char unk_04[0x2C]; // 0x4
|
||||
xe::be<uint32_t> pcr_ptr; // 0x30
|
||||
char unk_34[0x3C]; // 0x34
|
||||
xe::be<uint32_t> stack_base_ptr; // 0x70 Stack base address (high addr)
|
||||
xe::be<uint32_t> stack_end_ptr; // 0x74 Stack end (low addr)
|
||||
char unk_78[0x88]; // 0x78
|
||||
xe::be<uint32_t> teb_ptr; // 0x100
|
||||
char unk_104[0x8]; // 0x104
|
||||
xe::be<uint8_t> current_cpu; // 0x10C
|
||||
char unk_10D[0x43]; // 0x10D
|
||||
xe::be<uint32_t> dpc_active; // 0x150
|
||||
};
|
||||
|
||||
// Setup the thread state block (last error/etc).
|
||||
XPCR* pcr = memory()->TranslateVirtual<XPCR*>(pcr_address_);
|
||||
|
||||
pcr->tls_ptr = tls_address_;
|
||||
pcr->pcr_ptr = pcr_address_;
|
||||
pcr->teb_ptr = thread_state_address_;
|
||||
|
||||
pcr->stack_base_ptr =
|
||||
thread_state_->stack_address() + thread_state_->stack_size();
|
||||
pcr->stack_end_ptr = thread_state_->stack_address();
|
||||
|
||||
pcr->current_cpu = GetFakeCpuNumber(proc_mask); // Current CPU(?)
|
||||
pcr->dpc_active = 0; // DPC active bool?
|
||||
|
||||
// Thread state block
|
||||
struct XTEB {
|
||||
xe::be<uint32_t> unk_00; // 0x0
|
||||
xe::be<uint32_t> unk_04; // 0x4
|
||||
X_LIST_ENTRY unk_08; // 0x8
|
||||
X_LIST_ENTRY unk_10; // 0x10
|
||||
};
|
||||
|
||||
// Setup the thread state block (last error/etc)
|
||||
uint8_t* p = memory()->TranslateVirtual(thread_state_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>(
|
||||
|
@ -313,6 +346,8 @@ X_STATUS XThread::Exit(int exit_code) {
|
|||
// NOTE: unless PlatformExit fails, expect it to never return!
|
||||
current_thread_tls = nullptr;
|
||||
xe::Profiler::ThreadExit();
|
||||
kernel_state()->OnThreadExit(this);
|
||||
|
||||
Release();
|
||||
X_STATUS return_code = PlatformExit(exit_code);
|
||||
if (XFAILED(return_code)) {
|
||||
|
@ -443,6 +478,8 @@ void XThread::Execute() {
|
|||
// have time to initialize shared structures AFTER CreateThread (RR).
|
||||
xe::threading::Sleep(std::chrono::milliseconds::duration(100));
|
||||
|
||||
int exit_code = 0;
|
||||
|
||||
// If a XapiThreadStartup value is present, we use that as a trampoline.
|
||||
// Otherwise, we are a raw thread.
|
||||
if (creation_params_.xapi_thread_startup) {
|
||||
|
@ -454,16 +491,14 @@ void XThread::Execute() {
|
|||
} else {
|
||||
// Run user code.
|
||||
uint64_t args[] = {creation_params_.start_context};
|
||||
int exit_code = (int)kernel_state()->processor()->Execute(
|
||||
exit_code = (int)kernel_state()->processor()->Execute(
|
||||
thread_state_, creation_params_.start_address, args, xe::countof(args));
|
||||
// If we got here it means the execute completed without an exit being
|
||||
// called.
|
||||
// Treat the return code as an implicit exit code.
|
||||
Exit(exit_code);
|
||||
}
|
||||
|
||||
// Let the kernel know we are exiting.
|
||||
kernel_state()->OnThreadExit(this);
|
||||
Exit(exit_code);
|
||||
}
|
||||
|
||||
void XThread::EnterCriticalRegion() {
|
||||
|
@ -736,9 +771,6 @@ void XHostThread::Execute() {
|
|||
|
||||
int ret = host_fn_();
|
||||
|
||||
// Let the kernel know we are exiting.
|
||||
kernel_state()->OnThreadExit(this);
|
||||
|
||||
// Exit.
|
||||
Exit(ret);
|
||||
}
|
||||
|
|
|
@ -41,14 +41,14 @@ namespace kernel {
|
|||
|
||||
// RtlGetLastError:
|
||||
// lwz r11, 0x150(r13)
|
||||
// if (r11 != 0) {
|
||||
// if (r11 == 0) {
|
||||
// lwz r11, 0x100(r13)
|
||||
// stw r3, 0x160(r11)
|
||||
// }
|
||||
|
||||
// RtlSetLastError:
|
||||
// lwz r11, 0x150(r13)
|
||||
// if (r11 != 0) {
|
||||
// if (r11 == 0) {
|
||||
// lwz r11, 0x100(r13)
|
||||
// stw r3, 0x160(r11)
|
||||
// }
|
||||
|
@ -56,7 +56,7 @@ namespace kernel {
|
|||
// RtlSetLastNTError:
|
||||
// r3 = RtlNtStatusToDosError(r3)
|
||||
// lwz r11, 0x150(r13)
|
||||
// if (r11 != 0) {
|
||||
// if (r11 == 0) {
|
||||
// lwz r11, 0x100(r13)
|
||||
// stw r3, 0x160(r11)
|
||||
// }
|
||||
|
|
|
@ -292,7 +292,7 @@ class X_ANSI_STRING {
|
|||
};
|
||||
// static_assert_size(X_ANSI_STRING, 8);
|
||||
|
||||
// Values seem to be all over the place - GUIDs?
|
||||
// http://pastebin.com/SMypYikG
|
||||
typedef uint32_t XNotificationID;
|
||||
|
||||
// http://ffplay360.googlecode.com/svn/trunk/Common/XTLOnPC.h
|
||||
|
@ -374,6 +374,12 @@ struct X_INPUT_KEYSTROKE {
|
|||
};
|
||||
static_assert_size(X_INPUT_KEYSTROKE, 8);
|
||||
|
||||
struct X_LIST_ENTRY {
|
||||
be<uint32_t> flink_ptr; // next entry / head
|
||||
be<uint32_t> blink_ptr; // previous entry / head
|
||||
};
|
||||
static_assert_size(X_LIST_ENTRY, 8);
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
} // namespace xe
|
||||
|
|
Loading…
Reference in New Issue