From 43018060611ee751477f9b337e0d0e969b6b0055 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Sat, 25 Jul 2015 11:43:25 -0500 Subject: [PATCH] Cleanup some Ke* threading APIs (and update the dispatch header when possible) --- src/xenia/kernel/objects/xevent.h | 5 + src/xenia/kernel/objects/xsemaphore.cc | 7 +- src/xenia/kernel/objects/xsemaphore.h | 4 +- src/xenia/kernel/xboxkrnl_threading.cc | 246 +++++++++++-------------- 4 files changed, 118 insertions(+), 144 deletions(-) diff --git a/src/xenia/kernel/objects/xevent.h b/src/xenia/kernel/objects/xevent.h index 31cbb9df6..696a0b27f 100644 --- a/src/xenia/kernel/objects/xevent.h +++ b/src/xenia/kernel/objects/xevent.h @@ -17,6 +17,11 @@ namespace xe { namespace kernel { +// http://www.nirsoft.net/kernel_struct/vista/KEVENT.html +struct X_KEVENT { + X_DISPATCH_HEADER header; +}; + class XEvent : public XObject { public: XEvent(KernelState* kernel_state); diff --git a/src/xenia/kernel/objects/xsemaphore.cc b/src/xenia/kernel/objects/xsemaphore.cc index 6331a3480..00a94888b 100644 --- a/src/xenia/kernel/objects/xsemaphore.cc +++ b/src/xenia/kernel/objects/xsemaphore.cc @@ -20,7 +20,7 @@ XSemaphore::~XSemaphore() = default; void XSemaphore::Initialize(int32_t initial_count, int32_t maximum_count) { assert_false(semaphore_); - CreateNative(sizeof(X_SEMAPHORE)); + CreateNative(sizeof(X_KSEMAPHORE)); semaphore_ = xe::threading::Semaphore::Create(initial_count, maximum_count); } @@ -28,8 +28,9 @@ void XSemaphore::Initialize(int32_t initial_count, int32_t maximum_count) { void XSemaphore::InitializeNative(void* native_ptr, X_DISPATCH_HEADER& header) { assert_false(semaphore_); - // NOT IMPLEMENTED - // We expect Initialize to be called shortly. + auto semaphore = reinterpret_cast(native_ptr); + semaphore_ = xe::threading::Semaphore::Create(semaphore->header.signal_state, + semaphore->limit); } int32_t XSemaphore::ReleaseSemaphore(int32_t release_count) { diff --git a/src/xenia/kernel/objects/xsemaphore.h b/src/xenia/kernel/objects/xsemaphore.h index 73019b4c5..cdccb1993 100644 --- a/src/xenia/kernel/objects/xsemaphore.h +++ b/src/xenia/kernel/objects/xsemaphore.h @@ -17,9 +17,9 @@ namespace xe { namespace kernel { -struct X_SEMAPHORE { +struct X_KSEMAPHORE { X_DISPATCH_HEADER header; - // TODO: Make this not empty! + xe::be limit; }; class XSemaphore : public XObject { diff --git a/src/xenia/kernel/xboxkrnl_threading.cc b/src/xenia/kernel/xboxkrnl_threading.cc index cf2698778..ea0c0a966 100644 --- a/src/xenia/kernel/xboxkrnl_threading.cc +++ b/src/xenia/kernel/xboxkrnl_threading.cc @@ -423,6 +423,65 @@ SHIM_CALL KeTlsSetValue_shim(PPCContext* ppc_context, SHIM_SET_RETURN_32(result); } +dword_result_t KeInitializeEvent(pointer_t event_ptr, + dword_t event_type, dword_t initial_state) { + event_ptr.Zero(); + event_ptr->header.type = event_type; + event_ptr->header.signal_state = (uint32_t)initial_state; + auto ev = + XObject::GetNativeObject(kernel_state(), event_ptr, event_type); + if (!ev) { + return X_STATUS_INSUFFICIENT_RESOURCES; + } + + return X_STATUS_SUCCESS; +} +DECLARE_XBOXKRNL_EXPORT(KeInitializeEvent, + ExportTag::kImplemented | ExportTag::kThreading); + +dword_result_t KeSetEvent(pointer_t event_ptr, dword_t increment, + dword_t wait) { + // Update dispatch header + xe::atomic_exchange(xe::byte_swap(1), + (uint32_t*)&event_ptr->header.signal_state); + + auto ev = XObject::GetNativeObject(kernel_state(), event_ptr); + if (!ev) { + assert_always(); + return 0; + } + + return ev->Set(increment, !!wait); +} +DECLARE_XBOXKRNL_EXPORT(KeSetEvent, + ExportTag::kImplemented | ExportTag::kThreading); + +dword_result_t KePulseEvent(pointer_t event_ptr, dword_t increment, + dword_t wait) { + auto ev = XObject::GetNativeObject(kernel_state(), event_ptr); + if (!ev) { + assert_always(); + return 0; + } + + return ev->Pulse(increment, !!wait); +} +DECLARE_XBOXKRNL_EXPORT(KePulseEvent, ExportTag::kImplemented); + +dword_result_t KeResetEvent(pointer_t event_ptr) { + // Update dispatch header + xe::atomic_exchange(0, (uint32_t*)&event_ptr->header.signal_state); + + auto ev = XObject::GetNativeObject(kernel_state(), event_ptr); + if (!ev) { + return 0; + } + + return ev->Reset(); +} +DECLARE_XBOXKRNL_EXPORT(KeResetEvent, + ExportTag::kImplemented | ExportTag::kThreading); + SHIM_CALL NtCreateEvent_shim(PPCContext* ppc_context, KernelState* kernel_state) { uint32_t handle_ptr = SHIM_GET_ARG_32(0); @@ -451,43 +510,6 @@ SHIM_CALL NtCreateEvent_shim(PPCContext* ppc_context, SHIM_SET_RETURN_32(X_STATUS_SUCCESS); } -SHIM_CALL KeInitializeEvent_shim(PPCContext* ppc_context, - KernelState* kernel_state) { - uint32_t handle_ptr = SHIM_GET_ARG_32(0); - uint32_t event_type = SHIM_GET_ARG_32(1); - uint32_t initial_state = SHIM_GET_ARG_32(2); - - XELOGD("KeInitializeEvent(%.8X, %.8X, %.8X)", handle_ptr, event_type, - initial_state); - - XEvent* ev = new XEvent(kernel_state); - ev->Initialize(!event_type, !!initial_state); - - if (handle_ptr) { - SHIM_SET_MEM_32(handle_ptr, ev->handle()); - } - SHIM_SET_RETURN_32(X_STATUS_SUCCESS); -} - -SHIM_CALL KeSetEvent_shim(PPCContext* ppc_context, KernelState* kernel_state) { - uint32_t event_ref = SHIM_GET_ARG_32(0); - uint32_t increment = SHIM_GET_ARG_32(1); - uint32_t wait = SHIM_GET_ARG_32(2); - - XELOGD("KeSetEvent(%.8X, %.8X, %.8X)", event_ref, increment, wait); - - void* event_ptr = SHIM_MEM_ADDR(event_ref); - - auto ev = XObject::GetNativeObject(kernel_state, event_ptr); - if (!ev) { - SHIM_SET_RETURN_32(0); - return; - } - - auto result = ev->Set(increment, !!wait); - SHIM_SET_RETURN_32(result); -} - SHIM_CALL NtSetEvent_shim(PPCContext* ppc_context, KernelState* kernel_state) { uint32_t event_handle = SHIM_GET_ARG_32(0); uint32_t previous_state_ptr = SHIM_GET_ARG_32(1); @@ -509,25 +531,6 @@ SHIM_CALL NtSetEvent_shim(PPCContext* ppc_context, KernelState* kernel_state) { SHIM_SET_RETURN_32(result); } -SHIM_CALL KePulseEvent_shim(PPCContext* ppc_context, - KernelState* kernel_state) { - uint32_t event_ref = SHIM_GET_ARG_32(0); - uint32_t increment = SHIM_GET_ARG_32(1); - uint32_t wait = SHIM_GET_ARG_32(2); - - XELOGD("KePulseEvent(%.8X, %.8X, %.8X)", event_ref, increment, wait); - - int32_t result = 0; - - void* event_ptr = SHIM_MEM_ADDR(event_ref); - auto ev = XObject::GetNativeObject(kernel_state, event_ptr); - if (ev) { - result = ev->Pulse(increment, !!wait); - } - - SHIM_SET_RETURN_32(result); -} - SHIM_CALL NtPulseEvent_shim(PPCContext* ppc_context, KernelState* kernel_state) { uint32_t event_handle = SHIM_GET_ARG_32(0); @@ -550,23 +553,6 @@ SHIM_CALL NtPulseEvent_shim(PPCContext* ppc_context, SHIM_SET_RETURN_32(result); } -SHIM_CALL KeResetEvent_shim(PPCContext* ppc_context, - KernelState* kernel_state) { - uint32_t event_ref = SHIM_GET_ARG_32(0); - - XELOGD("KeResetEvent(%.8X)", event_ref); - - void* event_ptr = SHIM_MEM_ADDR(event_ref); - auto ev = XObject::GetNativeObject(kernel_state, event_ptr); - if (!ev) { - SHIM_SET_RETURN_32(0); - return; - } - - auto result = ev->Reset(); - SHIM_SET_RETURN_32(result); -} - dword_result_t NtClearEvent(dword_t handle) { X_STATUS result = X_STATUS_SUCCESS; @@ -582,6 +568,41 @@ dword_result_t NtClearEvent(dword_t handle) { DECLARE_XBOXKRNL_EXPORT(NtClearEvent, ExportTag::kImplemented | ExportTag::kThreading); +// https://msdn.microsoft.com/en-us/library/windows/hardware/ff552150(v=vs.85).aspx +void KeInitializeSemaphore(pointer_t semaphore_ptr, dword_t count, + dword_t limit) { + semaphore_ptr->header.type = 5; // SemaphoreObject + semaphore_ptr->header.signal_state = (uint32_t)count; + semaphore_ptr->limit = (uint32_t)limit; + + auto sem = XObject::GetNativeObject(kernel_state(), semaphore_ptr, + 5 /* SemaphoreObject */); + if (!sem) { + assert_always(); + return; + } +} +DECLARE_XBOXKRNL_EXPORT(KeInitializeSemaphore, + ExportTag::kImplemented | ExportTag::kThreading); + +dword_result_t KeReleaseSemaphore(pointer_t semaphore_ptr, + dword_t increment, dword_t adjustment, + dword_t wait) { + auto sem = + XObject::GetNativeObject(kernel_state(), semaphore_ptr); + if (!sem) { + assert_always(); + return 0; + } + + // TODO(benvanik): increment thread priority? + // TODO(benvanik): wait? + + return sem->ReleaseSemaphore(adjustment); +} +DECLARE_XBOXKRNL_EXPORT(KeReleaseSemaphore, + ExportTag::kImplemented | ExportTag::kThreading); + SHIM_CALL NtCreateSemaphore_shim(PPCContext* ppc_context, KernelState* kernel_state) { uint32_t handle_ptr = SHIM_GET_ARG_32(0); @@ -613,48 +634,6 @@ SHIM_CALL NtCreateSemaphore_shim(PPCContext* ppc_context, SHIM_SET_RETURN_32(X_STATUS_SUCCESS); } -SHIM_CALL KeInitializeSemaphore_shim(PPCContext* ppc_context, - KernelState* kernel_state) { - uint32_t semaphore_ref = SHIM_GET_ARG_32(0); - int32_t count = SHIM_GET_ARG_32(1); - int32_t limit = SHIM_GET_ARG_32(2); - - XELOGD("KeInitializeSemaphore(%.8X, %d, %d)", semaphore_ref, count, limit); - - void* semaphore_ptr = SHIM_MEM_ADDR(semaphore_ref); - auto sem = XObject::GetNativeObject(kernel_state, semaphore_ptr, - 5 /* SemaphoreObject */); - if (!sem) { - return; - } - - sem->Initialize(count, limit); -} - -SHIM_CALL KeReleaseSemaphore_shim(PPCContext* ppc_context, - KernelState* kernel_state) { - uint32_t semaphore_ref = SHIM_GET_ARG_32(0); - int32_t increment = SHIM_GET_ARG_32(1); - int32_t adjustment = SHIM_GET_ARG_32(2); - int32_t wait = SHIM_GET_ARG_32(3); - - XELOGD("KeReleaseSemaphore(%.8X, %d, %d, %d)", semaphore_ref, increment, - adjustment, wait); - - void* semaphore_ptr = SHIM_MEM_ADDR(semaphore_ref); - auto sem = XObject::GetNativeObject(kernel_state, semaphore_ptr); - if (!sem) { - SHIM_SET_RETURN_32(0); - return; - } - - // TODO(benvanik): increment thread priority? - // TODO(benvanik): wait? - - int32_t result = sem->ReleaseSemaphore(adjustment); - SHIM_SET_RETURN_32(result); -} - SHIM_CALL NtReleaseSemaphore_shim(PPCContext* ppc_context, KernelState* kernel_state) { uint32_t sem_handle = SHIM_GET_ARG_32(0); @@ -680,35 +659,30 @@ SHIM_CALL NtReleaseSemaphore_shim(PPCContext* ppc_context, SHIM_SET_RETURN_32(result); } -SHIM_CALL NtCreateMutant_shim(PPCContext* ppc_context, - KernelState* kernel_state) { - uint32_t handle_ptr = SHIM_GET_ARG_32(0); - uint32_t obj_attributes_ptr = SHIM_GET_ARG_32(1); - uint32_t initial_owner = SHIM_GET_ARG_32(2); - - XELOGD("NtCreateMutant(%.8X, %.8X, %.1X)", handle_ptr, obj_attributes_ptr, - initial_owner); - +dword_result_t NtCreateMutant(lpdword_t handle_out, + pointer_t obj_attributes, + dword_t initial_owner) { // TODO(benvanik): check for name collision. May return existing object if // type matches. - if (obj_attributes_ptr) { - AssertNoNameCollision(kernel_state, obj_attributes_ptr); + if (obj_attributes) { + AssertNoNameCollision(kernel_state(), obj_attributes); } - XMutant* mutant = new XMutant(kernel_state); + XMutant* mutant = new XMutant(kernel_state()); mutant->Initialize(initial_owner ? true : false); // obj_attributes may have a name inside of it, if != NULL. - if (obj_attributes_ptr) { - mutant->SetAttributes(obj_attributes_ptr); + if (obj_attributes) { + mutant->SetAttributes(obj_attributes); } - if (handle_ptr) { - SHIM_SET_MEM_32(handle_ptr, mutant->handle()); + if (handle_out) { + *handle_out = mutant->handle(); } - SHIM_SET_RETURN_32(X_STATUS_SUCCESS); + return X_STATUS_SUCCESS; } +DECLARE_XBOXKRNL_EXPORT(NtCreateMutant, ExportTag::kImplemented); SHIM_CALL NtReleaseMutant_shim(PPCContext* ppc_context, KernelState* kernel_state) { @@ -1331,6 +1305,7 @@ pointer_result_t InterlockedFlushSList(pointer_t plist_ptr) { uint32_t next = plist_ptr->next.next; plist_ptr->next.next = 0; + plist_ptr->depth = 0; return next; } @@ -1365,19 +1340,12 @@ void xe::kernel::xboxkrnl::RegisterThreadingExports( SHIM_SET_MAPPING("xboxkrnl.exe", KeTlsSetValue, state); SHIM_SET_MAPPING("xboxkrnl.exe", NtCreateEvent, state); - SHIM_SET_MAPPING("xboxkrnl.exe", KeInitializeEvent, state); - SHIM_SET_MAPPING("xboxkrnl.exe", KeSetEvent, state); SHIM_SET_MAPPING("xboxkrnl.exe", NtSetEvent, state); - SHIM_SET_MAPPING("xboxkrnl.exe", KePulseEvent, state); SHIM_SET_MAPPING("xboxkrnl.exe", NtPulseEvent, state); - SHIM_SET_MAPPING("xboxkrnl.exe", KeResetEvent, state); SHIM_SET_MAPPING("xboxkrnl.exe", NtCreateSemaphore, state); - SHIM_SET_MAPPING("xboxkrnl.exe", KeInitializeSemaphore, state); - SHIM_SET_MAPPING("xboxkrnl.exe", KeReleaseSemaphore, state); SHIM_SET_MAPPING("xboxkrnl.exe", NtReleaseSemaphore, state); - SHIM_SET_MAPPING("xboxkrnl.exe", NtCreateMutant, state); SHIM_SET_MAPPING("xboxkrnl.exe", NtReleaseMutant, state); SHIM_SET_MAPPING("xboxkrnl.exe", NtCreateTimer, state);