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() {
if (executable_module_) {
executable_module_->Release();
executable_module_ = NULL;
}
SetExecutableModule(NULL);
// Delete all objects.
xe_mutex_free(object_mutex_);

View File

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

View File

@ -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;

View File

@ -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();

View File

@ -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();

View File

@ -9,6 +9,7 @@
#include <xenia/kernel/modules/xboxkrnl/objects/xthread.h>
#include <xenia/kernel/modules/xboxkrnl/objects/xevent.h>
#include <xenia/kernel/modules/xboxkrnl/objects/xmodule.h>
@ -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);
}

View File

@ -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_;
};

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();
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;
}

View File

@ -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;