diff --git a/src/core/kernel/exports/EmuKrnlKi.cpp b/src/core/kernel/exports/EmuKrnlKi.cpp index f06976f2d..1e7c10f97 100644 --- a/src/core/kernel/exports/EmuKrnlKi.cpp +++ b/src/core/kernel/exports/EmuKrnlKi.cpp @@ -102,6 +102,7 @@ xbox::void_xt xbox::KiInitSystem() { KiUniqueProcess.StackCount = 0; KiUniqueProcess.ThreadQuantum = X_THREAD_QUANTUM; + InitializeListHead(&KiUniqueProcess.ThreadListHead); InitializeListHead(&KiWaitInListHead); diff --git a/src/core/kernel/exports/EmuKrnlPs.cpp b/src/core/kernel/exports/EmuKrnlPs.cpp index 913614f0c..84a96bcbf 100644 --- a/src/core/kernel/exports/EmuKrnlPs.cpp +++ b/src/core/kernel/exports/EmuKrnlPs.cpp @@ -294,6 +294,7 @@ XBSYSAPI EXPORTNUM(255) xbox::ntstatus_xt NTAPI xbox::PsCreateSystemThreadEx ObfReferenceObject(eThread); KeQuerySystemTime(&eThread->CreateTime); + InsertTailList(&KiUniqueProcess.ThreadListHead, &eThread->Tcb.ThreadListEntry); KiUniqueProcess.StackCount++; RegisterXboxHandle(*ThreadHandle, handle); HANDLE dupHandle = OpenThread(THREAD_ALL_ACCESS, FALSE, ThreadId); diff --git a/src/core/kernel/init/CxbxKrnl.cpp b/src/core/kernel/init/CxbxKrnl.cpp index 4098ae7d0..c6a74603d 100644 --- a/src/core/kernel/init/CxbxKrnl.cpp +++ b/src/core/kernel/init/CxbxKrnl.cpp @@ -72,6 +72,8 @@ #include "common\crypto\EmuSha.h" // For the SHA1 functions #include "Timer.h" // For Timer_Init #include "common\input\InputManager.h" // For the InputDeviceManager +#include "core/kernel/support/NativeHandle.h" +#include "common/win32/Util.h" // for WinError2Str #include "common/FilePaths.hpp" @@ -1573,6 +1575,51 @@ static void CxbxrKrnlInitHacks() CxbxKrnlShutDown(); } +void CxbxrKrnlSuspendThreads() +{ + xbox::PLIST_ENTRY ThreadListEntry = KiUniqueProcess.ThreadListHead.Flink; + std::vector threads; + threads.reserve(KiUniqueProcess.StackCount); + + xbox::KPCR* Pcr = EmuKeGetPcr(); + + // If there's nothing in list entry, skip this step. + if (!ThreadListEntry) { + return; + } + + while (ThreadListEntry != &KiUniqueProcess.ThreadListHead) { + xbox::HANDLE UniqueThread = CONTAINING_RECORD(ThreadListEntry, xbox::ETHREAD, Tcb.ThreadListEntry)->UniqueThread; + if (UniqueThread) { + // Current thread is an xbox thread + if (Pcr) { + const auto& nHandle = GetNativeHandle(UniqueThread); + if (nHandle) { + // We do not want to suspend current thread, so we let it skip this one. + if (*nHandle != NtCurrentThread()) { + threads.push_back(*nHandle); + } + } + } + // Otherwise, convert all UniqueThread to host thead handles. + else { + const auto& nHandle = GetNativeHandle(UniqueThread); + if (nHandle) { + threads.push_back(*nHandle); + } + } + } + ThreadListEntry = ThreadListEntry->Flink; + } + + for (const auto& thread : threads) { + DWORD PrevCount = SuspendThread(thread); + if (PrevCount == -1) { + EmuLog(LOG_LEVEL::ERROR2, "Unable to suspend thread 0x%X for: %s", thread, WinError2Str().c_str()); + } + } +} + void CxbxKrnlShutDown(bool is_reboot) { if (!is_reboot) { @@ -1581,6 +1628,9 @@ void CxbxKrnlShutDown(bool is_reboot) g_EmuShared->SetBootFlags(&BootFlags); } + // This is very important process to prevent false positive report and allow IDEs to continue debug multiple reboots. + CxbxrKrnlSuspendThreads(); + // NOTE: This causes a hang when exiting while NV2A is processing // This is okay for now: It won't leak memory or resources since TerminateProcess will free everything // delete g_NV2A; // TODO : g_pXbox diff --git a/src/core/kernel/support/EmuFS.cpp b/src/core/kernel/support/EmuFS.cpp index 68a45c40d..b46b9b9e7 100644 --- a/src/core/kernel/support/EmuFS.cpp +++ b/src/core/kernel/support/EmuFS.cpp @@ -228,6 +228,8 @@ void EmuKeFreeThread(xbox::ntstatus_xt ExitStatus) xbox::KeQuerySystemTime(&eThread->ExitTime); eThread->Tcb.HasTerminated = 1; + RemoveEntryList(&eThread->Tcb.ThreadListEntry); + // Emulate our exit strategy for GetExitCodeThread eThread->ExitStatus = ExitStatus; eThread->Tcb.Header.SignalState = 1; diff --git a/src/core/kernel/support/NativeHandle.cpp b/src/core/kernel/support/NativeHandle.cpp index 123483374..6edd55e83 100644 --- a/src/core/kernel/support/NativeHandle.cpp +++ b/src/core/kernel/support/NativeHandle.cpp @@ -32,6 +32,7 @@ #include "assert.h" #include "NativeHandle.h" #include "core\kernel\init\CxbxKrnl.h" +#include "core/kernel/support/EmuFS.h" std::unordered_map g_RegisteredHandles;