From b0481472f270cbc42c7bd5274c780499ee2c30f0 Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Wed, 25 Sep 2013 20:55:22 -0700 Subject: [PATCH] Finally adding thread wait so we kill the spin loop. --- .../kernel/modules/xboxkrnl/kernel_state.cc | 5 +--- .../kernel/modules/xboxkrnl/object_table.cc | 1 + .../kernel/modules/xboxkrnl/objects/xevent.cc | 8 ++++++- .../kernel/modules/xboxkrnl/objects/xevent.h | 3 ++- .../modules/xboxkrnl/objects/xmodule.cc | 11 +-------- .../modules/xboxkrnl/objects/xthread.cc | 23 +++++++++++++++++-- .../kernel/modules/xboxkrnl/objects/xthread.h | 8 +++++++ .../kernel/modules/xboxkrnl/xboxkrnl_rtl.cc | 2 ++ src/xenia/kernel/modules/xboxkrnl/xobject.cc | 4 ++-- 9 files changed, 45 insertions(+), 20 deletions(-) diff --git a/src/xenia/kernel/modules/xboxkrnl/kernel_state.cc b/src/xenia/kernel/modules/xboxkrnl/kernel_state.cc index d63608d95..467906ef7 100644 --- a/src/xenia/kernel/modules/xboxkrnl/kernel_state.cc +++ b/src/xenia/kernel/modules/xboxkrnl/kernel_state.cc @@ -36,10 +36,7 @@ KernelState::KernelState(Runtime* runtime) : } KernelState::~KernelState() { - if (executable_module_) { - executable_module_->Release(); - executable_module_ = NULL; - } + SetExecutableModule(NULL); // Delete all objects. xe_mutex_free(object_mutex_); diff --git a/src/xenia/kernel/modules/xboxkrnl/object_table.cc b/src/xenia/kernel/modules/xboxkrnl/object_table.cc index 0f3eaa13e..c781c2434 100644 --- a/src/xenia/kernel/modules/xboxkrnl/object_table.cc +++ b/src/xenia/kernel/modules/xboxkrnl/object_table.cc @@ -33,6 +33,7 @@ ObjectTable::~ObjectTable() { ObjectTableEntry& entry = table_[n]; if (entry.object) { entry.object->ReleaseHandle(); + entry.object->Release(); } } diff --git a/src/xenia/kernel/modules/xboxkrnl/objects/xevent.cc b/src/xenia/kernel/modules/xboxkrnl/objects/xevent.cc index 6e41fec23..17ba5cfd0 100644 --- a/src/xenia/kernel/modules/xboxkrnl/objects/xevent.cc +++ b/src/xenia/kernel/modules/xboxkrnl/objects/xevent.cc @@ -23,7 +23,13 @@ XEvent::XEvent(KernelState* kernel_state) : XEvent::~XEvent() { } -void XEvent::Initialize(void* native_ptr, DISPATCH_HEADER& header) { +void XEvent::Initialize(bool manual_reset, bool initial_state) { + XEASSERTNULL(handle_); + + handle_ = CreateEvent(NULL, manual_reset, initial_state, NULL); +} + +void XEvent::InitializeNative(void* native_ptr, DISPATCH_HEADER& header) { XEASSERTNULL(handle_); bool manual_reset; diff --git a/src/xenia/kernel/modules/xboxkrnl/objects/xevent.h b/src/xenia/kernel/modules/xboxkrnl/objects/xevent.h index f51a28b9d..1e2e112d8 100644 --- a/src/xenia/kernel/modules/xboxkrnl/objects/xevent.h +++ b/src/xenia/kernel/modules/xboxkrnl/objects/xevent.h @@ -25,7 +25,8 @@ public: XEvent(KernelState* kernel_state); virtual ~XEvent(); - void Initialize(void* native_ptr, DISPATCH_HEADER& header); + void Initialize(bool manual_reset, bool initial_state); + void InitializeNative(void* native_ptr, DISPATCH_HEADER& header); int32_t Set(uint32_t priority_increment, bool wait); int32_t Reset(); diff --git a/src/xenia/kernel/modules/xboxkrnl/objects/xmodule.cc b/src/xenia/kernel/modules/xboxkrnl/objects/xmodule.cc index 506927c59..8becd31c1 100644 --- a/src/xenia/kernel/modules/xboxkrnl/objects/xmodule.cc +++ b/src/xenia/kernel/modules/xboxkrnl/objects/xmodule.cc @@ -142,16 +142,7 @@ X_STATUS XModule::Launch(uint32_t flags) { } // Wait until thread completes. - // XLARGE_INTEGER timeout = XINFINITE; - // xekNtWaitForSingleObjectEx(thread_handle, TRUE, &timeout); - - while (true) { -#if XE_PLATFORM(WIN32) - Sleep(1000); -#else - sleep(1); -#endif // WIN32 - } + thread->Wait(0, 0, 0, NULL); kernel_state()->SetExecutableModule(NULL); thread->Release(); diff --git a/src/xenia/kernel/modules/xboxkrnl/objects/xthread.cc b/src/xenia/kernel/modules/xboxkrnl/objects/xthread.cc index e64dc72bc..e2d04f5e1 100644 --- a/src/xenia/kernel/modules/xboxkrnl/objects/xthread.cc +++ b/src/xenia/kernel/modules/xboxkrnl/objects/xthread.cc @@ -9,6 +9,7 @@ #include +#include #include @@ -31,7 +32,8 @@ XThread::XThread(KernelState* kernel_state, thread_id_(++next_xthread_id), thread_handle_(0), thread_state_address_(0), - thread_state_(0) { + thread_state_(0), + event_(NULL) { creation_params_.stack_size = stack_size; creation_params_.xapi_thread_startup = xapi_thread_startup; creation_params_.start_address = start_address; @@ -42,9 +44,14 @@ XThread::XThread(KernelState* kernel_state, if (creation_params_.stack_size < 16 * 1024 * 1024) { creation_params_.stack_size = 16 * 1024 * 1024; } + + event_ = new XEvent(kernel_state); + event_->Initialize(true, false); } XThread::~XThread() { + event_->Release(); + PlatformDestroy(); if (thread_state_) { @@ -100,13 +107,15 @@ X_STATUS XThread::Create() { return X_STATUS_NO_MEMORY; } - // Allocate TLS block. XModule* module = kernel_state()->GetExecutableModule(); + + // Allocate TLS block. const xe_xex2_header_t* header = module->xex_header(); uint32_t tls_size = header->tls_info.slot_count * header->tls_info.data_size; tls_address_ = xe_memory_heap_alloc(memory(), 0, tls_size, 0); if (!tls_address_) { XELOGW("Unable to allocate thread local storage block"); + module->Release(); return X_STATUS_NO_MEMORY; } @@ -129,21 +138,26 @@ X_STATUS XThread::Create() { creation_params_.stack_size, thread_state_address_, thread_id_); if (!thread_state_) { XELOGW("Unable to allocate processor thread state"); + module->Release(); return X_STATUS_NO_MEMORY; } X_STATUS return_code = PlatformCreate(); if (XFAILED(return_code)) { XELOGW("Unable to create platform thread (%.8X)", return_code); + module->Release(); return return_code; } + module->Release(); return X_STATUS_SUCCESS; } X_STATUS XThread::Exit(int exit_code) { // TODO(benvanik): set exit code in thread state block + // TODO(benvanik); dispatch events? waiters? etc? + event_->Set(0, false); // NOTE: unless PlatformExit fails, expect it to never return! X_STATUS return_code = PlatformExit(exit_code); @@ -271,3 +285,8 @@ void XThread::Execute() { Exit(exit_code); } } + +X_STATUS XThread::Wait(uint32_t wait_reason, uint32_t processor_mode, + uint32_t alertable, uint64_t* opt_timeout) { + return event_->Wait(wait_reason, processor_mode, alertable, opt_timeout); +} diff --git a/src/xenia/kernel/modules/xboxkrnl/objects/xthread.h b/src/xenia/kernel/modules/xboxkrnl/objects/xthread.h index 90355c578..46a481c29 100644 --- a/src/xenia/kernel/modules/xboxkrnl/objects/xthread.h +++ b/src/xenia/kernel/modules/xboxkrnl/objects/xthread.h @@ -20,6 +20,9 @@ namespace kernel { namespace xboxkrnl { +class XEvent; + + class XThread : public XObject { public: XThread(KernelState* kernel_state, @@ -40,6 +43,9 @@ public: void Execute(); + virtual X_STATUS Wait(uint32_t wait_reason, uint32_t processor_mode, + uint32_t alertable, uint64_t* opt_timeout); + private: X_STATUS PlatformCreate(); void PlatformDestroy(); @@ -58,6 +64,8 @@ private: uint32_t tls_address_; uint32_t thread_state_address_; cpu::ThreadState* thread_state_; + + XEvent* event_; }; diff --git a/src/xenia/kernel/modules/xboxkrnl/xboxkrnl_rtl.cc b/src/xenia/kernel/modules/xboxkrnl/xboxkrnl_rtl.cc index 6f1d80327..b07843247 100644 --- a/src/xenia/kernel/modules/xboxkrnl/xboxkrnl_rtl.cc +++ b/src/xenia/kernel/modules/xboxkrnl/xboxkrnl_rtl.cc @@ -590,10 +590,12 @@ uint32_t xeRtlImageXexHeaderField(uint32_t xex_header_base_ptr, const xe_xex2_header_t* xex_header = module->xex_header(); for (size_t n = 0; n < xex_header->header_count; n++) { if (xex_header->headers[n].key == image_field) { + module->Release(); return xex_header->headers[n].value; } } + module->Release(); return 0; } diff --git a/src/xenia/kernel/modules/xboxkrnl/xobject.cc b/src/xenia/kernel/modules/xboxkrnl/xobject.cc index a2f55b26a..cce202433 100644 --- a/src/xenia/kernel/modules/xboxkrnl/xobject.cc +++ b/src/xenia/kernel/modules/xboxkrnl/xobject.cc @@ -21,7 +21,7 @@ using namespace xe::kernel::xboxkrnl; XObject::XObject(KernelState* kernel_state, Type type) : kernel_state_(kernel_state), handle_ref_count_(0), - pointer_ref_count_(0), + pointer_ref_count_(1), type_(type), handle_(X_INVALID_HANDLE_VALUE) { kernel_state->object_table()->AddHandle(this, &handle_); } @@ -123,7 +123,7 @@ XObject* XObject::GetObject(KernelState* kernel_state, void* native_ptr) { case 1: // EventSynchronizationObject { XEvent* ev = new XEvent(kernel_state); - ev->Initialize(native_ptr, header); + ev->InitializeNative(native_ptr, header); object = ev; } break;