Finally adding thread wait so we kill the spin loop.

This commit is contained in:
Ben Vanik 2013-09-25 20:55:22 -07:00
parent d16ab71252
commit b0481472f2
9 changed files with 45 additions and 20 deletions

View File

@ -36,10 +36,7 @@ KernelState::KernelState(Runtime* runtime) :
} }
KernelState::~KernelState() { KernelState::~KernelState() {
if (executable_module_) { SetExecutableModule(NULL);
executable_module_->Release();
executable_module_ = NULL;
}
// Delete all objects. // Delete all objects.
xe_mutex_free(object_mutex_); xe_mutex_free(object_mutex_);

View File

@ -33,6 +33,7 @@ ObjectTable::~ObjectTable() {
ObjectTableEntry& entry = table_[n]; ObjectTableEntry& entry = table_[n];
if (entry.object) { if (entry.object) {
entry.object->ReleaseHandle(); entry.object->ReleaseHandle();
entry.object->Release();
} }
} }

View File

@ -23,7 +23,13 @@ XEvent::XEvent(KernelState* kernel_state) :
XEvent::~XEvent() { 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_); XEASSERTNULL(handle_);
bool manual_reset; bool manual_reset;

View File

@ -25,7 +25,8 @@ public:
XEvent(KernelState* kernel_state); XEvent(KernelState* kernel_state);
virtual ~XEvent(); 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 Set(uint32_t priority_increment, bool wait);
int32_t Reset(); int32_t Reset();

View File

@ -142,16 +142,7 @@ X_STATUS XModule::Launch(uint32_t flags) {
} }
// Wait until thread completes. // Wait until thread completes.
// XLARGE_INTEGER timeout = XINFINITE; thread->Wait(0, 0, 0, NULL);
// xekNtWaitForSingleObjectEx(thread_handle, TRUE, &timeout);
while (true) {
#if XE_PLATFORM(WIN32)
Sleep(1000);
#else
sleep(1);
#endif // WIN32
}
kernel_state()->SetExecutableModule(NULL); kernel_state()->SetExecutableModule(NULL);
thread->Release(); thread->Release();

View File

@ -9,6 +9,7 @@
#include <xenia/kernel/modules/xboxkrnl/objects/xthread.h> #include <xenia/kernel/modules/xboxkrnl/objects/xthread.h>
#include <xenia/kernel/modules/xboxkrnl/objects/xevent.h>
#include <xenia/kernel/modules/xboxkrnl/objects/xmodule.h> #include <xenia/kernel/modules/xboxkrnl/objects/xmodule.h>
@ -31,7 +32,8 @@ XThread::XThread(KernelState* kernel_state,
thread_id_(++next_xthread_id), thread_id_(++next_xthread_id),
thread_handle_(0), thread_handle_(0),
thread_state_address_(0), thread_state_address_(0),
thread_state_(0) { thread_state_(0),
event_(NULL) {
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;
creation_params_.start_address = start_address; creation_params_.start_address = start_address;
@ -42,9 +44,14 @@ XThread::XThread(KernelState* kernel_state,
if (creation_params_.stack_size < 16 * 1024 * 1024) { if (creation_params_.stack_size < 16 * 1024 * 1024) {
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() { XThread::~XThread() {
event_->Release();
PlatformDestroy(); PlatformDestroy();
if (thread_state_) { if (thread_state_) {
@ -100,13 +107,15 @@ X_STATUS XThread::Create() {
return X_STATUS_NO_MEMORY; return X_STATUS_NO_MEMORY;
} }
// Allocate TLS block.
XModule* module = kernel_state()->GetExecutableModule(); XModule* module = kernel_state()->GetExecutableModule();
// Allocate TLS block.
const xe_xex2_header_t* header = module->xex_header(); const xe_xex2_header_t* header = module->xex_header();
uint32_t tls_size = header->tls_info.slot_count * header->tls_info.data_size; 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); tls_address_ = xe_memory_heap_alloc(memory(), 0, tls_size, 0);
if (!tls_address_) { if (!tls_address_) {
XELOGW("Unable to allocate thread local storage block"); XELOGW("Unable to allocate thread local storage block");
module->Release();
return X_STATUS_NO_MEMORY; return X_STATUS_NO_MEMORY;
} }
@ -129,21 +138,26 @@ X_STATUS XThread::Create() {
creation_params_.stack_size, thread_state_address_, thread_id_); creation_params_.stack_size, thread_state_address_, thread_id_);
if (!thread_state_) { if (!thread_state_) {
XELOGW("Unable to allocate processor thread state"); XELOGW("Unable to allocate processor thread state");
module->Release();
return X_STATUS_NO_MEMORY; return X_STATUS_NO_MEMORY;
} }
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);
module->Release();
return return_code; return return_code;
} }
module->Release();
return X_STATUS_SUCCESS; return X_STATUS_SUCCESS;
} }
X_STATUS XThread::Exit(int exit_code) { X_STATUS XThread::Exit(int exit_code) {
// TODO(benvanik): set exit code in thread state block // TODO(benvanik): set exit code in thread state block
// TODO(benvanik); dispatch events? waiters? etc? // TODO(benvanik); dispatch events? waiters? etc?
event_->Set(0, false);
// NOTE: unless PlatformExit fails, expect it to never return! // NOTE: unless PlatformExit fails, expect it to never return!
X_STATUS return_code = PlatformExit(exit_code); X_STATUS return_code = PlatformExit(exit_code);
@ -271,3 +285,8 @@ void XThread::Execute() {
Exit(exit_code); 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);
}

View File

@ -20,6 +20,9 @@ namespace kernel {
namespace xboxkrnl { namespace xboxkrnl {
class XEvent;
class XThread : public XObject { class XThread : public XObject {
public: public:
XThread(KernelState* kernel_state, XThread(KernelState* kernel_state,
@ -40,6 +43,9 @@ public:
void Execute(); void Execute();
virtual X_STATUS Wait(uint32_t wait_reason, uint32_t processor_mode,
uint32_t alertable, uint64_t* opt_timeout);
private: private:
X_STATUS PlatformCreate(); X_STATUS PlatformCreate();
void PlatformDestroy(); void PlatformDestroy();
@ -58,6 +64,8 @@ private:
uint32_t tls_address_; uint32_t tls_address_;
uint32_t thread_state_address_; uint32_t thread_state_address_;
cpu::ThreadState* thread_state_; cpu::ThreadState* thread_state_;
XEvent* event_;
}; };

View File

@ -590,10 +590,12 @@ uint32_t xeRtlImageXexHeaderField(uint32_t xex_header_base_ptr,
const xe_xex2_header_t* xex_header = module->xex_header(); const xe_xex2_header_t* xex_header = module->xex_header();
for (size_t n = 0; n < xex_header->header_count; n++) { for (size_t n = 0; n < xex_header->header_count; n++) {
if (xex_header->headers[n].key == image_field) { if (xex_header->headers[n].key == image_field) {
module->Release();
return xex_header->headers[n].value; return xex_header->headers[n].value;
} }
} }
module->Release();
return 0; return 0;
} }

View File

@ -21,7 +21,7 @@ using namespace xe::kernel::xboxkrnl;
XObject::XObject(KernelState* kernel_state, Type type) : XObject::XObject(KernelState* kernel_state, Type type) :
kernel_state_(kernel_state), kernel_state_(kernel_state),
handle_ref_count_(0), handle_ref_count_(0),
pointer_ref_count_(0), pointer_ref_count_(1),
type_(type), handle_(X_INVALID_HANDLE_VALUE) { type_(type), handle_(X_INVALID_HANDLE_VALUE) {
kernel_state->object_table()->AddHandle(this, &handle_); kernel_state->object_table()->AddHandle(this, &handle_);
} }
@ -123,7 +123,7 @@ 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->Initialize(native_ptr, header); ev->InitializeNative(native_ptr, header);
object = ev; object = ev;
} }
break; break;