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;
|
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();
|
auto module = kernel_state()->GetExecutableModule();
|
||||||
|
|
||||||
// Allocate thread scratch.
|
// Allocate thread scratch.
|
||||||
|
@ -217,6 +198,31 @@ X_STATUS XThread::Create() {
|
||||||
header->tls_info.raw_data_size);
|
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.
|
// Allocate processor thread state.
|
||||||
// This is thread safe.
|
// This is thread safe.
|
||||||
thread_state_ = new ThreadState(kernel_state()->processor(), thread_id_,
|
thread_state_ = new ThreadState(kernel_state()->processor(), thread_id_,
|
||||||
|
@ -232,29 +238,56 @@ X_STATUS XThread::Create() {
|
||||||
uint8_t proc_mask =
|
uint8_t proc_mask =
|
||||||
static_cast<uint8_t>(creation_params_.creation_flags >> 24);
|
static_cast<uint8_t>(creation_params_.creation_flags >> 24);
|
||||||
|
|
||||||
uint8_t* pcr = memory()->TranslateVirtual(pcr_address_);
|
// Processor Control Region
|
||||||
std::memset(pcr, 0x0, 0x2D8 + 0xAB0); // Zero the PCR
|
struct XPCR {
|
||||||
xe::store_and_swap<uint32_t>(pcr + 0x000, tls_address_);
|
xe::be<uint32_t> tls_ptr; // 0x0
|
||||||
xe::store_and_swap<uint32_t>(pcr + 0x030, pcr_address_);
|
char unk_04[0x2C]; // 0x4
|
||||||
xe::store_and_swap<uint32_t>(pcr + 0x070, thread_state_->stack_address() +
|
xe::be<uint32_t> pcr_ptr; // 0x30
|
||||||
thread_state_->stack_size());
|
char unk_34[0x3C]; // 0x34
|
||||||
xe::store_and_swap<uint32_t>(pcr + 0x074, thread_state_->stack_address());
|
xe::be<uint32_t> stack_base_ptr; // 0x70 Stack base address (high addr)
|
||||||
xe::store_and_swap<uint32_t>(pcr + 0x100, thread_state_address_);
|
xe::be<uint32_t> stack_end_ptr; // 0x74 Stack end (low addr)
|
||||||
xe::store_and_swap<uint8_t>(pcr + 0x10C,
|
char unk_78[0x88]; // 0x78
|
||||||
GetFakeCpuNumber(proc_mask)); // Current CPU(?)
|
xe::be<uint32_t> teb_ptr; // 0x100
|
||||||
xe::store_and_swap<uint32_t>(pcr + 0x150, 0); // DPC active bool?
|
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_);
|
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);
|
||||||
xe::store_and_swap<uint32_t>(p + 0x008, thread_state_address_ + 0x008);
|
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 + 0x00C, thread_state_address_ + 0x008);
|
||||||
xe::store_and_swap<uint32_t>(p + 0x010, thread_state_address_ + 0x010);
|
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 + 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 + 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 + 0x044, thread_state_address_ + 0x018 + 8);
|
||||||
xe::store_and_swap<uint32_t>(p + 0x048, thread_state_address_);
|
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<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>(
|
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!
|
// NOTE: unless PlatformExit fails, expect it to never return!
|
||||||
current_thread_tls = nullptr;
|
current_thread_tls = nullptr;
|
||||||
xe::Profiler::ThreadExit();
|
xe::Profiler::ThreadExit();
|
||||||
|
kernel_state()->OnThreadExit(this);
|
||||||
|
|
||||||
Release();
|
Release();
|
||||||
X_STATUS return_code = PlatformExit(exit_code);
|
X_STATUS return_code = PlatformExit(exit_code);
|
||||||
if (XFAILED(return_code)) {
|
if (XFAILED(return_code)) {
|
||||||
|
@ -443,6 +478,8 @@ void XThread::Execute() {
|
||||||
// have time to initialize shared structures AFTER CreateThread (RR).
|
// have time to initialize shared structures AFTER CreateThread (RR).
|
||||||
xe::threading::Sleep(std::chrono::milliseconds::duration(100));
|
xe::threading::Sleep(std::chrono::milliseconds::duration(100));
|
||||||
|
|
||||||
|
int exit_code = 0;
|
||||||
|
|
||||||
// If a XapiThreadStartup value is present, we use that as a trampoline.
|
// If a XapiThreadStartup value is present, we use that as a trampoline.
|
||||||
// Otherwise, we are a raw thread.
|
// Otherwise, we are a raw thread.
|
||||||
if (creation_params_.xapi_thread_startup) {
|
if (creation_params_.xapi_thread_startup) {
|
||||||
|
@ -454,16 +491,14 @@ void XThread::Execute() {
|
||||||
} else {
|
} else {
|
||||||
// Run user code.
|
// Run user code.
|
||||||
uint64_t args[] = {creation_params_.start_context};
|
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));
|
thread_state_, creation_params_.start_address, args, xe::countof(args));
|
||||||
// If we got here it means the execute completed without an exit being
|
// If we got here it means the execute completed without an exit being
|
||||||
// called.
|
// called.
|
||||||
// Treat the return code as an implicit exit code.
|
// Treat the return code as an implicit exit code.
|
||||||
Exit(exit_code);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let the kernel know we are exiting.
|
Exit(exit_code);
|
||||||
kernel_state()->OnThreadExit(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void XThread::EnterCriticalRegion() {
|
void XThread::EnterCriticalRegion() {
|
||||||
|
@ -736,9 +771,6 @@ void XHostThread::Execute() {
|
||||||
|
|
||||||
int ret = host_fn_();
|
int ret = host_fn_();
|
||||||
|
|
||||||
// Let the kernel know we are exiting.
|
|
||||||
kernel_state()->OnThreadExit(this);
|
|
||||||
|
|
||||||
// Exit.
|
// Exit.
|
||||||
Exit(ret);
|
Exit(ret);
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,14 +41,14 @@ namespace kernel {
|
||||||
|
|
||||||
// RtlGetLastError:
|
// RtlGetLastError:
|
||||||
// lwz r11, 0x150(r13)
|
// lwz r11, 0x150(r13)
|
||||||
// if (r11 != 0) {
|
// if (r11 == 0) {
|
||||||
// lwz r11, 0x100(r13)
|
// lwz r11, 0x100(r13)
|
||||||
// stw r3, 0x160(r11)
|
// stw r3, 0x160(r11)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// RtlSetLastError:
|
// RtlSetLastError:
|
||||||
// lwz r11, 0x150(r13)
|
// lwz r11, 0x150(r13)
|
||||||
// if (r11 != 0) {
|
// if (r11 == 0) {
|
||||||
// lwz r11, 0x100(r13)
|
// lwz r11, 0x100(r13)
|
||||||
// stw r3, 0x160(r11)
|
// stw r3, 0x160(r11)
|
||||||
// }
|
// }
|
||||||
|
@ -56,7 +56,7 @@ namespace kernel {
|
||||||
// RtlSetLastNTError:
|
// RtlSetLastNTError:
|
||||||
// r3 = RtlNtStatusToDosError(r3)
|
// r3 = RtlNtStatusToDosError(r3)
|
||||||
// lwz r11, 0x150(r13)
|
// lwz r11, 0x150(r13)
|
||||||
// if (r11 != 0) {
|
// if (r11 == 0) {
|
||||||
// lwz r11, 0x100(r13)
|
// lwz r11, 0x100(r13)
|
||||||
// stw r3, 0x160(r11)
|
// stw r3, 0x160(r11)
|
||||||
// }
|
// }
|
||||||
|
|
|
@ -292,7 +292,7 @@ class X_ANSI_STRING {
|
||||||
};
|
};
|
||||||
// static_assert_size(X_ANSI_STRING, 8);
|
// static_assert_size(X_ANSI_STRING, 8);
|
||||||
|
|
||||||
// Values seem to be all over the place - GUIDs?
|
// http://pastebin.com/SMypYikG
|
||||||
typedef uint32_t XNotificationID;
|
typedef uint32_t XNotificationID;
|
||||||
|
|
||||||
// http://ffplay360.googlecode.com/svn/trunk/Common/XTLOnPC.h
|
// http://ffplay360.googlecode.com/svn/trunk/Common/XTLOnPC.h
|
||||||
|
@ -374,6 +374,12 @@ struct X_INPUT_KEYSTROKE {
|
||||||
};
|
};
|
||||||
static_assert_size(X_INPUT_KEYSTROKE, 8);
|
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)
|
#pragma pack(pop)
|
||||||
|
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
Loading…
Reference in New Issue