diff --git a/src/xenia/cpu/export_resolver.h b/src/xenia/cpu/export_resolver.h index feb4f560b..ad79c2b89 100644 --- a/src/xenia/cpu/export_resolver.h +++ b/src/xenia/cpu/export_resolver.h @@ -32,6 +32,8 @@ struct ExportTag { static const type kHighFrequency = 1u << 3; // Export is important and should always be logged. static const type kImportant = 1u << 4; + // Export blocks the calling thread + static const type kBlocking = 1u << 5; static const type kThreading = 1u << 10; static const type kInput = 1u << 11; diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc index e385ca8fb..09c164145 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc @@ -345,22 +345,16 @@ SHIM_CALL KeQueryPerformanceFrequency_shim(PPCContext* ppc_context, SHIM_SET_RETURN_32(result); } -SHIM_CALL KeDelayExecutionThread_shim(PPCContext* ppc_context, - KernelState* kernel_state) { - uint32_t processor_mode = SHIM_GET_ARG_32(0); - uint32_t alertable = SHIM_GET_ARG_32(1); - uint32_t interval_ptr = SHIM_GET_ARG_32(2); - uint64_t interval = SHIM_MEM_64(interval_ptr); - - // XELOGD( - // "KeDelayExecutionThread(%.8X, %d, %.8X(%.16llX)", - // processor_mode, alertable, interval_ptr, interval); - +dword_result_t KeDelayExecutionThread(dword_t processor_mode, dword_t alertable, + lpqword_t interval_ptr) { XThread* thread = XThread::GetCurrentThread(); - X_STATUS result = thread->Delay(processor_mode, alertable, interval); + X_STATUS result = thread->Delay(processor_mode, alertable, *interval_ptr); - SHIM_SET_RETURN_32(result); + return result; } +DECLARE_XBOXKRNL_EXPORT(KeDelayExecutionThread, + ExportTag::kImplemented | ExportTag::kThreading | + ExportTag::kHighFrequency | ExportTag::kBlocking); SHIM_CALL NtYieldExecution_shim(PPCContext* ppc_context, KernelState* kernel_state) { @@ -853,104 +847,87 @@ SHIM_CALL NtCancelTimer_shim(PPCContext* ppc_context, SHIM_SET_RETURN_32(result); } -SHIM_CALL KeWaitForSingleObject_shim(PPCContext* ppc_context, - KernelState* kernel_state) { - uint32_t object_ptr = SHIM_GET_ARG_32(0); - uint32_t wait_reason = SHIM_GET_ARG_32(1); - uint32_t processor_mode = SHIM_GET_ARG_32(2); - uint32_t alertable = SHIM_GET_ARG_32(3); - uint32_t timeout_ptr = SHIM_GET_ARG_32(4); - - XELOGD("KeWaitForSingleObject(%.8X, %.8X, %.8X, %.1X, %.8X)", object_ptr, - wait_reason, processor_mode, alertable, timeout_ptr); - - auto object = XObject::GetNativeObject(kernel_state, - SHIM_MEM_ADDR(object_ptr)); +dword_result_t KeWaitForSingleObject(lpvoid_t object_ptr, dword_t wait_reason, + dword_t processor_mode, dword_t alertable, + lpqword_t timeout_ptr) { + auto object = XObject::GetNativeObject(kernel_state(), object_ptr); if (!object) { - // The only kind-of failure code. - SHIM_SET_RETURN_32(X_STATUS_ABANDONED_WAIT_0); - return; + // The only kind-of failure code (though this should never happen) + assert_always(); + return X_STATUS_ABANDONED_WAIT_0; } - uint64_t timeout = timeout_ptr ? SHIM_MEM_64(timeout_ptr) : 0; + uint64_t timeout = timeout_ptr ? *timeout_ptr : 0; X_STATUS result = object->Wait(wait_reason, processor_mode, alertable, timeout_ptr ? &timeout : nullptr); - SHIM_SET_RETURN_32(result); + return result; } +DECLARE_XBOXKRNL_EXPORT(KeWaitForSingleObject, ExportTag::kImplemented | + ExportTag::kThreading | + ExportTag::kBlocking); -SHIM_CALL NtWaitForSingleObjectEx_shim(PPCContext* ppc_context, - KernelState* kernel_state) { - uint32_t object_handle = SHIM_GET_ARG_32(0); - uint8_t wait_mode = SHIM_GET_ARG_8(1); - uint32_t alertable = SHIM_GET_ARG_32(2); - uint32_t timeout_ptr = SHIM_GET_ARG_32(3); - - XELOGD("NtWaitForSingleObjectEx(%.8X, %u, %.1X, %.8X)", object_handle, - (uint32_t)wait_mode, alertable, timeout_ptr); - +dword_result_t NtWaitForSingleObjectEx(dword_t object_handle, dword_t wait_mode, + dword_t alertable, + lpqword_t timeout_ptr) { X_STATUS result = X_STATUS_SUCCESS; auto object = - kernel_state->object_table()->LookupObject(object_handle); + kernel_state()->object_table()->LookupObject(object_handle); if (object) { - uint64_t timeout = timeout_ptr ? SHIM_MEM_64(timeout_ptr) : 0; + uint64_t timeout = timeout_ptr ? *timeout_ptr : 0; result = object->Wait(3, wait_mode, alertable, timeout_ptr ? &timeout : nullptr); } else { result = X_STATUS_INVALID_HANDLE; } - SHIM_SET_RETURN_32(result); + return result; } +DECLARE_XBOXKRNL_EXPORT(NtWaitForSingleObjectEx, ExportTag::kImplemented | + ExportTag::kThreading | + ExportTag::kBlocking); -SHIM_CALL KeWaitForMultipleObjects_shim(PPCContext* ppc_context, - KernelState* kernel_state) { - uint32_t count = SHIM_GET_ARG_32(0); - uint32_t objects_ptr = SHIM_GET_ARG_32(1); - uint32_t wait_type = SHIM_GET_ARG_32(2); - uint32_t wait_reason = SHIM_GET_ARG_32(3); - uint32_t processor_mode = SHIM_GET_ARG_32(4); - uint32_t alertable = SHIM_GET_ARG_32(5); - uint32_t timeout_ptr = SHIM_GET_ARG_32(6); - uint32_t wait_block_array_ptr = SHIM_GET_ARG_32(7); - - XELOGD( - "KeWaitForMultipleObjects(%d, %.8X, %.8X, %.8X, %.8X, %.1X, %.8X, %.8X)", - count, objects_ptr, wait_type, wait_reason, processor_mode, alertable, - timeout_ptr, wait_block_array_ptr); - +dword_result_t KeWaitForMultipleObjects(dword_t count, lpdword_t objects_ptr, + dword_t wait_type, dword_t wait_reason, + dword_t processor_mode, + dword_t alertable, + lpqword_t timeout_ptr, + lpvoid_t wait_block_array_ptr) { assert_true(wait_type <= 1); X_STATUS result = X_STATUS_SUCCESS; std::vector> objects; for (uint32_t n = 0; n < count; n++) { - uint32_t object_ptr_ptr = SHIM_MEM_32(objects_ptr + n * 4); - void* object_ptr = SHIM_MEM_ADDR(object_ptr_ptr); + auto object_ptr = kernel_memory()->TranslateVirtual(objects_ptr[n]); auto object_ref = - XObject::GetNativeObject(kernel_state, object_ptr); + XObject::GetNativeObject(kernel_state(), object_ptr); if (!object_ref) { - SHIM_SET_RETURN_32(X_STATUS_INVALID_PARAMETER); - return; + return X_STATUS_INVALID_PARAMETER; } + objects.push_back(std::move(object_ref)); } - uint64_t timeout = timeout_ptr ? SHIM_MEM_64(timeout_ptr) : 0; + uint64_t timeout = timeout_ptr ? *timeout_ptr : 0; result = XObject::WaitMultiple(uint32_t(objects.size()), reinterpret_cast(objects.data()), wait_type, wait_reason, processor_mode, alertable, timeout_ptr ? &timeout : nullptr); - SHIM_SET_RETURN_32(result); + return result; } +DECLARE_XBOXKRNL_EXPORT(KeWaitForMultipleObjects, ExportTag::kImplemented | + ExportTag::kThreading | + ExportTag::kBlocking); -dword_result_t NtWaitForMultipleObjectsEx( - dword_t count, pointer_t> handles, dword_t wait_type, - dword_t wait_mode, dword_t alertable, - pointer_t> timeout_ptr) { +dword_result_t NtWaitForMultipleObjectsEx(dword_t count, + pointer_t> handles, + dword_t wait_type, dword_t wait_mode, + dword_t alertable, + lpqword_t timeout_ptr) { assert_true(wait_type <= 1); X_STATUS result = X_STATUS_SUCCESS; @@ -972,28 +949,22 @@ dword_result_t NtWaitForMultipleObjectsEx( return result; } -DECLARE_XBOXKRNL_EXPORT(NtWaitForMultipleObjectsEx, - ExportTag::kImplemented | ExportTag::kThreading); - -SHIM_CALL NtSignalAndWaitForSingleObjectEx_shim(PPCContext* ppc_context, - KernelState* kernel_state) { - uint32_t signal_handle = SHIM_GET_ARG_32(0); - uint32_t wait_handle = SHIM_GET_ARG_32(1); - uint32_t alertable = SHIM_GET_ARG_32(2); - uint32_t unk_3 = SHIM_GET_ARG_32(3); - uint32_t timeout_ptr = SHIM_GET_ARG_32(4); - - XELOGD("NtSignalAndWaitForSingleObjectEx(%.8X, %.8X, %.1X, %.8X, %.8X)", - signal_handle, wait_handle, alertable, unk_3, timeout_ptr); +DECLARE_XBOXKRNL_EXPORT(NtWaitForMultipleObjectsEx, ExportTag::kImplemented | + ExportTag::kThreading | + ExportTag::kBlocking); +dword_result_t NtSignalAndWaitForSingleObjectEx(dword_t signal_handle, + dword_t wait_handle, + dword_t alertable, dword_t r6, + lpqword_t timeout_ptr) { X_STATUS result = X_STATUS_SUCCESS; auto signal_object = - kernel_state->object_table()->LookupObject(signal_handle); + kernel_state()->object_table()->LookupObject(signal_handle); auto wait_object = - kernel_state->object_table()->LookupObject(wait_handle); + kernel_state()->object_table()->LookupObject(wait_handle); if (signal_object && wait_object) { - uint64_t timeout = timeout_ptr ? SHIM_MEM_64(timeout_ptr) : 0; + uint64_t timeout = timeout_ptr ? *timeout_ptr : 0; result = XObject::SignalAndWait(signal_object.get(), wait_object.get(), 3, 1, alertable, timeout_ptr ? &timeout : nullptr); @@ -1001,19 +972,19 @@ SHIM_CALL NtSignalAndWaitForSingleObjectEx_shim(PPCContext* ppc_context, result = X_STATUS_INVALID_HANDLE; } - SHIM_SET_RETURN_32(result); + return result; } +DECLARE_XBOXKRNL_EXPORT(NtSignalAndWaitForSingleObjectEx, + ExportTag::kImplemented | ExportTag::kThreading | + ExportTag::kBlocking); -SHIM_CALL KfAcquireSpinLock_shim(PPCContext* ppc_context, - KernelState* kernel_state) { - uint32_t lock_ptr = SHIM_GET_ARG_32(0); - +dword_result_t KfAcquireSpinLock(lpdword_t lock_ptr) { // XELOGD( // "KfAcquireSpinLock(%.8X)", // lock_ptr); // Lock. - auto lock = reinterpret_cast(SHIM_MEM_ADDR(lock_ptr)); + auto lock = reinterpret_cast(lock_ptr.host_address()); while (!xe::atomic_cas(0, 1, lock)) { // Spin! // TODO(benvanik): error on deadlock? @@ -1024,56 +995,45 @@ SHIM_CALL KfAcquireSpinLock_shim(PPCContext* ppc_context, XThread* thread = XThread::GetCurrentThread(); auto old_irql = thread->RaiseIrql(2); - SHIM_SET_RETURN_32(old_irql); + return old_irql; } +DECLARE_XBOXKRNL_EXPORT(KfAcquireSpinLock, + ExportTag::kImplemented | ExportTag::kThreading | + ExportTag::kHighFrequency | ExportTag::kBlocking); -SHIM_CALL KfReleaseSpinLock_shim(PPCContext* ppc_context, - KernelState* kernel_state) { - uint32_t lock_ptr = SHIM_GET_ARG_32(0); - uint32_t old_irql = SHIM_GET_ARG_32(1); - - // XELOGD( - // "KfReleaseSpinLock(%.8X, %d)", - // lock_ptr, - // old_irql); - +void KfReleaseSpinLock(lpdword_t lock_ptr, dword_t old_irql) { // Restore IRQL. XThread* thread = XThread::GetCurrentThread(); thread->LowerIrql(old_irql); // Unlock. - auto lock = reinterpret_cast(SHIM_MEM_ADDR(lock_ptr)); + auto lock = reinterpret_cast(lock_ptr.host_address()); xe::atomic_dec(lock); } +DECLARE_XBOXKRNL_EXPORT(KfReleaseSpinLock, ExportTag::kImplemented | + ExportTag::kThreading | + ExportTag::kHighFrequency); -SHIM_CALL KeAcquireSpinLockAtRaisedIrql_shim(PPCContext* ppc_context, - KernelState* kernel_state) { - uint32_t lock_ptr = SHIM_GET_ARG_32(0); - - // XELOGD( - // "KeAcquireSpinLockAtRaisedIrql(%.8X)", - // lock_ptr); - +void KeAcquireSpinLockAtRaisedIrql(lpdword_t lock_ptr) { // Lock. - auto lock = reinterpret_cast(SHIM_MEM_ADDR(lock_ptr)); + auto lock = reinterpret_cast(lock_ptr.host_address()); while (!xe::atomic_cas(0, 1, lock)) { // Spin! // TODO(benvanik): error on deadlock? } } +DECLARE_XBOXKRNL_EXPORT(KeAcquireSpinLockAtRaisedIrql, + ExportTag::kImplemented | ExportTag::kThreading | + ExportTag::kHighFrequency | ExportTag::kBlocking); -SHIM_CALL KeReleaseSpinLockFromRaisedIrql_shim(PPCContext* ppc_context, - KernelState* kernel_state) { - uint32_t lock_ptr = SHIM_GET_ARG_32(0); - - // XELOGD( - // "KeReleaseSpinLockFromRaisedIrql(%.8X)", - // lock_ptr); - +void KeReleaseSpinLockFromRaisedIrql(lpdword_t lock_ptr) { // Unlock. - auto lock = reinterpret_cast(SHIM_MEM_ADDR(lock_ptr)); + auto lock = reinterpret_cast(lock_ptr.host_address()); xe::atomic_dec(lock); } +DECLARE_XBOXKRNL_EXPORT(KeReleaseSpinLockFromRaisedIrql, + ExportTag::kImplemented | ExportTag::kThreading | + ExportTag::kHighFrequency); SHIM_CALL KeEnterCriticalRegion_shim(PPCContext* ppc_context, KernelState* kernel_state) { @@ -1409,7 +1369,6 @@ void RegisterThreadingExports(xe::cpu::ExportResolver* export_resolver, SHIM_SET_MAPPING("xboxkrnl.exe", KeSetCurrentProcessType, state); SHIM_SET_MAPPING("xboxkrnl.exe", KeQueryPerformanceFrequency, state); - SHIM_SET_MAPPING("xboxkrnl.exe", KeDelayExecutionThread, state); SHIM_SET_MAPPING("xboxkrnl.exe", NtYieldExecution, state); SHIM_SET_MAPPING("xboxkrnl.exe", KeQuerySystemTime, state); @@ -1427,17 +1386,6 @@ void RegisterThreadingExports(xe::cpu::ExportResolver* export_resolver, SHIM_SET_MAPPING("xboxkrnl.exe", NtSetTimerEx, state); SHIM_SET_MAPPING("xboxkrnl.exe", NtCancelTimer, state); - SHIM_SET_MAPPING("xboxkrnl.exe", KeWaitForSingleObject, state); - SHIM_SET_MAPPING("xboxkrnl.exe", NtWaitForSingleObjectEx, state); - SHIM_SET_MAPPING("xboxkrnl.exe", KeWaitForMultipleObjects, state); - SHIM_SET_MAPPING("xboxkrnl.exe", NtSignalAndWaitForSingleObjectEx, state); - - SHIM_SET_MAPPING("xboxkrnl.exe", KfAcquireSpinLock, state); - SHIM_SET_MAPPING("xboxkrnl.exe", KfReleaseSpinLock, state); - - SHIM_SET_MAPPING("xboxkrnl.exe", KeAcquireSpinLockAtRaisedIrql, state); - SHIM_SET_MAPPING("xboxkrnl.exe", KeReleaseSpinLockFromRaisedIrql, state); - SHIM_SET_MAPPING("xboxkrnl.exe", KeEnterCriticalRegion, state); SHIM_SET_MAPPING("xboxkrnl.exe", KeLeaveCriticalRegion, state);