Revert to using the host to do thread suspension

This commit is contained in:
ergo720 2023-03-14 23:57:40 +01:00 committed by RadWolfie
parent 4fca5c7007
commit 08ab4b9164
3 changed files with 56 additions and 6 deletions

View File

@ -132,6 +132,28 @@ xbox::ulonglong_xt LARGE_INTEGER2ULONGLONG(xbox::LARGE_INTEGER value)
}
xbox::void_xt xbox::KeResumeThreadEx
(
IN PKTHREAD Thread
)
{
// This is only to be used to synchronize new thread creation with the thread that spawned it
Thread->SuspendSemaphore.Header.SignalState = 1;
KiWaitTest(&Thread->SuspendSemaphore, 0);
}
xbox::void_xt xbox::KeSuspendThreadEx
(
IN PKTHREAD Thread
)
{
// This is only to be used to synchronize new thread creation with the thread that spawned it
Thread->SuspendSemaphore.Header.SignalState = 0;
KiInsertQueueApc(&Thread->SuspendApc, 0);
}
// ******************************************************************
// * EmuKeGetPcr()
// * NOTE: This is a macro on the Xbox, however we implement it
@ -1729,8 +1751,13 @@ XBSYSAPI EXPORTNUM(140) xbox::ulong_xt NTAPI xbox::KeResumeThread
if (OldCount != 0) {
--Thread->SuspendCount;
if (Thread->SuspendCount == 0) {
#if 0
++Thread->SuspendSemaphore.Header.SignalState;
KiWaitTest(&Thread->SuspendSemaphore, 0);
#else
const auto &nativeHandle = GetNativeHandle<true>(reinterpret_cast<PETHREAD>(Thread)->UniqueThread);
ResumeThread(*nativeHandle);
#endif
}
}
@ -2089,10 +2116,20 @@ XBSYSAPI EXPORTNUM(152) xbox::ulong_xt NTAPI xbox::KeSuspendThread
if (Thread->ApcState.ApcQueueable == TRUE) {
++Thread->SuspendCount;
if (OldCount == 0) {
#if 0
if (KiInsertQueueApc(&Thread->SuspendApc, 0) == FALSE) {
--Thread->SuspendSemaphore.Header.SignalState;
}
#else
// JSRF creates a thread at 0x0013BC30 and then it attempts to continuously suspend/resume it. Unfortunately, this thread performs a never ending loop (and
// terminates if it ever exit the loop), and never calls any kernel functions in the middle. This means that our suspend APC will never be executed and so
// we cannot suspend such thread. Thus, we will always have to rely on the host to do the suspension, as long as we do direct execution. Note that this is
// a general issue for all kernel APCs too.
const auto &nativeHandle = GetNativeHandle<true>(reinterpret_cast<PETHREAD>(Thread)->UniqueThread);
SuspendThread(*nativeHandle);
#endif
}
}
KiUnlockDispatcherDatabase(OldIrql);

View File

@ -52,5 +52,15 @@ namespace xbox
IN PKPROCESS Process
);
xbox::void_xt KeResumeThreadEx
(
IN PKTHREAD Thread
);
xbox::void_xt KeSuspendThreadEx
(
IN PKTHREAD Thread
);
void_xt KeEmptyQueueApc();
}

View File

@ -122,7 +122,6 @@ static unsigned int WINAPI PCSTProxy
params.TlsDataSize);
xbox::KiExecuteKernelApc();
eThread->Tcb.State = xbox::Running;
auto routine = (xbox::PKSYSTEM_ROUTINE)StartFrame->SystemRoutine;
// Debugging notice : When the below line shows up with an Exception dialog and a
@ -411,20 +410,24 @@ XBSYSAPI EXPORTNUM(255) xbox::ntstatus_xt NTAPI xbox::PsCreateSystemThreadEx
g_AffinityPolicy->SetAffinityXbox(handle);
// Wait for the initialization of the remaining thread state
KeSuspendThreadEx(&eThread->Tcb);
ResumeThread(handle);
while (eThread->Tcb.State == Initialized) {
std::this_thread::yield();
}
// Now that ThreadId is populated and affinity is changed, resume the thread (unless the guest passed CREATE_SUSPENDED), then wait until the new thread has
// finished initialization
if (CreateSuspended) {
KeSuspendThread(&eThread->Tcb);
}
KeResumeThreadEx(&eThread->Tcb);
// Log ThreadID identical to how GetCurrentThreadID() is rendered :
EmuLog(LOG_LEVEL::DEBUG, "Created Xbox proxy thread. Handle : 0x%X, ThreadId : [0x%.4X], Native Handle : 0x%X, Native ThreadId : [0x%.4X]",
*ThreadHandle, eThread->UniqueThread, handle, ThreadId);
ResumeThread(handle);
while (eThread->Tcb.State == Initialized) {
std::this_thread::yield();
}
}
RETURN(X_STATUS_SUCCESS);