Thread ID lookup and naming.
This commit is contained in:
parent
20b76b0e59
commit
5fd0b211ce
|
@ -82,3 +82,31 @@ void KernelState::SetExecutableModule(XModule* module) {
|
||||||
executable_module_->Retain();
|
executable_module_->Retain();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KernelState::RegisterThread(XThread* thread) {
|
||||||
|
xe_mutex_lock(object_mutex_);
|
||||||
|
threads_by_id_[thread->thread_id()] = thread;
|
||||||
|
xe_mutex_unlock(object_mutex_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KernelState::UnregisterThread(XThread* thread) {
|
||||||
|
xe_mutex_lock(object_mutex_);
|
||||||
|
auto it = threads_by_id_.find(thread->thread_id());
|
||||||
|
if (it != threads_by_id_.end()) {
|
||||||
|
threads_by_id_.erase(it);
|
||||||
|
}
|
||||||
|
xe_mutex_unlock(object_mutex_);
|
||||||
|
}
|
||||||
|
|
||||||
|
XThread* KernelState::GetThreadByID(uint32_t thread_id) {
|
||||||
|
XThread* thread = NULL;
|
||||||
|
xe_mutex_lock(object_mutex_);
|
||||||
|
auto it = threads_by_id_.find(thread_id);
|
||||||
|
if (it != threads_by_id_.end()) {
|
||||||
|
thread = it->second;
|
||||||
|
// Caller must release.
|
||||||
|
thread->Retain();
|
||||||
|
}
|
||||||
|
xe_mutex_unlock(object_mutex_);
|
||||||
|
return thread;
|
||||||
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
XEDECLARECLASS2(xe, cpu, Processor);
|
XEDECLARECLASS2(xe, cpu, Processor);
|
||||||
XEDECLARECLASS2(xe, kernel, XModule);
|
XEDECLARECLASS2(xe, kernel, XModule);
|
||||||
|
XEDECLARECLASS2(xe, kernel, XThread);
|
||||||
XEDECLARECLASS3(xe, kernel, fs, FileSystem);
|
XEDECLARECLASS3(xe, kernel, fs, FileSystem);
|
||||||
|
|
||||||
|
|
||||||
|
@ -47,6 +48,10 @@ public:
|
||||||
XModule* GetExecutableModule();
|
XModule* GetExecutableModule();
|
||||||
void SetExecutableModule(XModule* module);
|
void SetExecutableModule(XModule* module);
|
||||||
|
|
||||||
|
void RegisterThread(XThread* thread);
|
||||||
|
void UnregisterThread(XThread* thread);
|
||||||
|
XThread* GetThreadByID(uint32_t thread_id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Emulator* emulator_;
|
Emulator* emulator_;
|
||||||
Memory* memory_;
|
Memory* memory_;
|
||||||
|
@ -55,6 +60,7 @@ private:
|
||||||
|
|
||||||
ObjectTable* object_table_;
|
ObjectTable* object_table_;
|
||||||
xe_mutex_t* object_mutex_;
|
xe_mutex_t* object_mutex_;
|
||||||
|
std::unordered_map<uint32_t, XThread*> threads_by_id_;
|
||||||
|
|
||||||
XModule* executable_module_;
|
XModule* executable_module_;
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@ XThread::XThread(KernelState* kernel_state,
|
||||||
thread_state_address_(0),
|
thread_state_address_(0),
|
||||||
thread_state_(0),
|
thread_state_(0),
|
||||||
event_(NULL),
|
event_(NULL),
|
||||||
|
name_(0),
|
||||||
irql_(0) {
|
irql_(0) {
|
||||||
creation_params_.stack_size = stack_size;
|
creation_params_.stack_size = stack_size;
|
||||||
creation_params_.xapi_thread_startup = xapi_thread_startup;
|
creation_params_.xapi_thread_startup = xapi_thread_startup;
|
||||||
|
@ -54,9 +55,15 @@ XThread::XThread(KernelState* kernel_state,
|
||||||
|
|
||||||
event_ = new XEvent(kernel_state);
|
event_ = new XEvent(kernel_state);
|
||||||
event_->Initialize(true, false);
|
event_->Initialize(true, false);
|
||||||
|
|
||||||
|
// The kernel does not take a reference. We must unregister in the dtor.
|
||||||
|
kernel_state_->RegisterThread(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
XThread::~XThread() {
|
XThread::~XThread() {
|
||||||
|
// Unregister first to prevent lookups while deleting.
|
||||||
|
kernel_state_->UnregisterThread(this);
|
||||||
|
|
||||||
event_->Release();
|
event_->Release();
|
||||||
|
|
||||||
PlatformDestroy();
|
PlatformDestroy();
|
||||||
|
@ -70,6 +77,9 @@ XThread::~XThread() {
|
||||||
if (thread_state_address_) {
|
if (thread_state_address_) {
|
||||||
kernel_state()->memory()->HeapFree(thread_state_address_, 0);
|
kernel_state()->memory()->HeapFree(thread_state_address_, 0);
|
||||||
}
|
}
|
||||||
|
if (name_) {
|
||||||
|
xe_free(name_);
|
||||||
|
}
|
||||||
|
|
||||||
if (thread_handle_) {
|
if (thread_handle_) {
|
||||||
// TODO(benvanik): platform kill
|
// TODO(benvanik): platform kill
|
||||||
|
@ -121,6 +131,37 @@ void XThread::set_last_error(uint32_t error_code) {
|
||||||
XESETUINT32BE(p + 0x160, error_code);
|
XESETUINT32BE(p + 0x160, error_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void XThread::set_name(const char* name) {
|
||||||
|
if (name == name_) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (name_) {
|
||||||
|
xe_free(name_);
|
||||||
|
}
|
||||||
|
name_ = xestrdupa(name);
|
||||||
|
|
||||||
|
#if XE_PLATFORM(WIN32)
|
||||||
|
// Do the nasty set for us.
|
||||||
|
#pragma pack(push, 8)
|
||||||
|
typedef struct tagTHREADNAME_INFO {
|
||||||
|
DWORD dwType; // must be 0x1000
|
||||||
|
LPCSTR szName; // pointer to name (in user addr space)
|
||||||
|
DWORD dwThreadID; // thread ID (-1=caller thread)
|
||||||
|
DWORD dwFlags; // reserved for future use, must be zero
|
||||||
|
} THREADNAME_INFO;
|
||||||
|
#pragma pack(pop)
|
||||||
|
THREADNAME_INFO info;
|
||||||
|
info.dwType = 0x1000;
|
||||||
|
info.szName = name_;
|
||||||
|
info.dwThreadID = ::GetThreadId(thread_handle_);
|
||||||
|
info.dwFlags = 0;
|
||||||
|
__try {
|
||||||
|
RaiseException(0x406D1388, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);
|
||||||
|
} __except(EXCEPTION_CONTINUE_EXECUTION) {
|
||||||
|
}
|
||||||
|
#endif // WIN32
|
||||||
|
}
|
||||||
|
|
||||||
X_STATUS XThread::Create() {
|
X_STATUS XThread::Create() {
|
||||||
// Allocate thread state block from heap.
|
// Allocate thread state block from heap.
|
||||||
// This is set as r13 for user code and some special inlined Win32 calls
|
// This is set as r13 for user code and some special inlined Win32 calls
|
||||||
|
|
|
@ -46,6 +46,8 @@ public:
|
||||||
uint32_t thread_id();
|
uint32_t 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 char* name() const { return name_; }
|
||||||
|
void set_name(const char* name);
|
||||||
|
|
||||||
X_STATUS Create();
|
X_STATUS Create();
|
||||||
X_STATUS Exit(int exit_code);
|
X_STATUS Exit(int exit_code);
|
||||||
|
@ -83,6 +85,8 @@ private:
|
||||||
uint32_t thread_state_address_;
|
uint32_t thread_state_address_;
|
||||||
cpu::XenonThreadState* thread_state_;
|
cpu::XenonThreadState* thread_state_;
|
||||||
|
|
||||||
|
char* name_;
|
||||||
|
|
||||||
uint32_t irql_;
|
uint32_t irql_;
|
||||||
|
|
||||||
XEvent* event_;
|
XEvent* event_;
|
||||||
|
|
|
@ -241,6 +241,20 @@ SHIM_CALL DbgBreakPoint_shim(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SHIM_CALL RtlRaiseException_shim(
|
||||||
|
PPCContext* ppc_state, KernelState* state) {
|
||||||
|
uint32_t record_ptr = SHIM_GET_ARG_32(0);
|
||||||
|
|
||||||
|
uint32_t code = SHIM_MEM_32(record_ptr + 0);
|
||||||
|
|
||||||
|
XELOGD(
|
||||||
|
"RtlRaiseException(%.8X(%.8X))",
|
||||||
|
record_ptr, code);
|
||||||
|
|
||||||
|
XEASSERTALWAYS();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace kernel
|
} // namespace kernel
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
|
@ -249,4 +263,5 @@ void xe::kernel::xboxkrnl::RegisterDebugExports(
|
||||||
ExportResolver* export_resolver, KernelState* state) {
|
ExportResolver* export_resolver, KernelState* state) {
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", DbgPrint, state);
|
SHIM_SET_MAPPING("xboxkrnl.exe", DbgPrint, state);
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", DbgBreakPoint, state);
|
SHIM_SET_MAPPING("xboxkrnl.exe", DbgBreakPoint, state);
|
||||||
|
SHIM_SET_MAPPING("xboxkrnl.exe", RtlRaiseException, state);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue