Fixed dpc recursion bug
This commit is contained in:
parent
58041c95b4
commit
99ab34ac82
|
@ -158,7 +158,10 @@ void CallSoftwareInterrupt(const xbox::KIRQL SoftwareIrql)
|
|||
xbox::KiExecuteKernelApc();
|
||||
break;
|
||||
case DISPATCH_LEVEL: // = 2
|
||||
ExecuteDpcQueue();
|
||||
// This can be recursively called by KiUnlockDispatcherDatabase and KfLowerIrql, so avoid calling DPCs again if the current one has queued yet another one
|
||||
if (!IsDpcActive()) { // Avoid KeIsExecutingDpc(), as that logs
|
||||
ExecuteDpcQueue();
|
||||
}
|
||||
break;
|
||||
case APC_LEVEL | DISPATCH_LEVEL: // = 3
|
||||
KiUnexpectedInterrupt();
|
||||
|
@ -450,7 +453,8 @@ XBSYSAPI EXPORTNUM(163) xbox::void_xt FASTCALL xbox::KiUnlockDispatcherDatabase
|
|||
LOG_FUNC_ONE_ARG_TYPE(KIRQL_TYPE, OldIrql);
|
||||
|
||||
// Wrong, this should only happen when OldIrql >= DISPATCH_LEVEL
|
||||
if (!(KeGetCurrentPrcb()->DpcRoutineActive)) { // Avoid KeIsExecutingDpc(), as that logs
|
||||
// Checking DpcRoutineActive doesn't work because our Prcb is per-thread instead of being per-processor
|
||||
if (!IsDpcActive()) { // Avoid KeIsExecutingDpc(), as that logs
|
||||
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
||||
}
|
||||
|
||||
|
|
|
@ -96,6 +96,7 @@ namespace NtDll
|
|||
// TODO : Move towards thread-simulation based Dpc emulation
|
||||
typedef struct _DpcData {
|
||||
CRITICAL_SECTION Lock;
|
||||
std::atomic_flag IsDpcActive;
|
||||
xbox::LIST_ENTRY DpcQueue; // TODO : Use KeGetCurrentPrcb()->DpcListHead instead
|
||||
} DpcData;
|
||||
|
||||
|
@ -459,8 +460,10 @@ void ExecuteDpcQueue()
|
|||
// Mark it as no longer linked into the DpcQueue
|
||||
pkdpc->Inserted = FALSE;
|
||||
// Set DpcRoutineActive to support KeIsExecutingDpc:
|
||||
g_DpcData.IsDpcActive.test_and_set();
|
||||
KeGetCurrentPrcb()->DpcRoutineActive = TRUE; // Experimental
|
||||
EmuLog(LOG_LEVEL::DEBUG, "Global DpcQueue, calling DPC at 0x%.8X", pkdpc->DeferredRoutine);
|
||||
LeaveCriticalSection(&(g_DpcData.Lock));
|
||||
EmuLog(LOG_LEVEL::DEBUG, "Global DpcQueue, calling DPC object 0x%.8X at 0x%.8X", pkdpc, pkdpc->DeferredRoutine);
|
||||
|
||||
// Call the Deferred Procedure :
|
||||
pkdpc->DeferredRoutine(
|
||||
|
@ -469,7 +472,9 @@ void ExecuteDpcQueue()
|
|||
pkdpc->SystemArgument1,
|
||||
pkdpc->SystemArgument2);
|
||||
|
||||
EnterCriticalSection(&(g_DpcData.Lock));
|
||||
KeGetCurrentPrcb()->DpcRoutineActive = FALSE; // Experimental
|
||||
g_DpcData.IsDpcActive.clear();
|
||||
}
|
||||
|
||||
// Assert(g_DpcData._dwThreadId == GetCurrentThreadId());
|
||||
|
@ -486,6 +491,11 @@ void InitDpcData()
|
|||
InitializeListHead(&(g_DpcData.DpcQueue));
|
||||
}
|
||||
|
||||
bool IsDpcActive()
|
||||
{
|
||||
return g_DpcData.IsDpcActive.test();
|
||||
}
|
||||
|
||||
static constexpr uint32_t XBOX_TSC_FREQUENCY = 733333333; // Xbox Time Stamp Counter Frequency = 733333333 (CPU Clock)
|
||||
static constexpr uint32_t XBOX_ACPI_FREQUENCY = 3375000; // Xbox ACPI frequency (3.375 mhz)
|
||||
|
||||
|
@ -1258,7 +1268,9 @@ XBSYSAPI EXPORTNUM(119) xbox::boolean_xt NTAPI xbox::KeInsertQueueDpc
|
|||
InsertTailList(&(g_DpcData.DpcQueue), &(Dpc->DpcListEntry));
|
||||
// TODO : Instead of DpcQueue, add the DPC to KeGetCurrentPrcb()->DpcListHead
|
||||
// Signal the Dpc handling code there's work to do
|
||||
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
||||
if (g_DpcData.IsDpcActive.test() == false) {
|
||||
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
||||
}
|
||||
// OpenXbox has this instead:
|
||||
// if (!pKPRCB->DpcRoutineActive && !pKPRCB->DpcInterruptRequested) {
|
||||
// pKPRCB->DpcInterruptRequested = TRUE;
|
||||
|
@ -1279,7 +1291,11 @@ XBSYSAPI EXPORTNUM(121) xbox::boolean_xt NTAPI xbox::KeIsExecutingDpc
|
|||
{
|
||||
LOG_FUNC();
|
||||
|
||||
// This is the correct implementation, but it doesn't work because our Prcb is per-thread instead of being per-processor
|
||||
#if 0
|
||||
BOOLEAN ret = (BOOLEAN)KeGetCurrentPrcb()->DpcRoutineActive;
|
||||
#endif
|
||||
BOOLEAN ret = (BOOLEAN)IsDpcActive();
|
||||
|
||||
RETURN(ret);
|
||||
}
|
||||
|
|
|
@ -156,6 +156,7 @@ void CxbxKrnlPanic();
|
|||
void CxbxKrnlNoFunc();
|
||||
|
||||
void InitDpcData(); // Implemented in EmuKrnlKe.cpp
|
||||
bool IsDpcActive();
|
||||
|
||||
/*! kernel thunk table */
|
||||
extern uint32_t CxbxKrnl_KernelThunkTable[379];
|
||||
|
|
Loading…
Reference in New Issue