diff --git a/import/OpenXDK/include/xboxkrnl/xboxkrnl.h b/import/OpenXDK/include/xboxkrnl/xboxkrnl.h index dd08860a1..facde0367 100644 --- a/import/OpenXDK/include/xboxkrnl/xboxkrnl.h +++ b/import/OpenXDK/include/xboxkrnl/xboxkrnl.h @@ -1580,6 +1580,7 @@ typedef enum _KOBJECTS MutantObject = 2, QueueObject = 4, SemaphoreObject = 5, + ThreadObject = 6, TimerNotificationObject = 8, TimerSynchronizationObject = 9, ApcObject = 0x12, @@ -1961,7 +1962,7 @@ typedef struct _KTHREAD /* 0x55/85 */ CHAR WaitMode; /* 0x56/86 */ CHAR WaitNext; /* 0x57/87 */ CHAR WaitReason; - /* 0x58/88 */ PVOID WaitBlockList; + /* 0x58/88 */ PKWAIT_BLOCK WaitBlockList; /* 0x5C/92 */ LIST_ENTRY WaitListEntry; /* 0x64/100 */ ULONG WaitTime; /* 0x68/104 */ ULONG KernelApcDisable; diff --git a/src/core/kernel/exports/EmuKrnl.cpp b/src/core/kernel/exports/EmuKrnl.cpp index fb932432e..6f2bc0f0f 100644 --- a/src/core/kernel/exports/EmuKrnl.cpp +++ b/src/core/kernel/exports/EmuKrnl.cpp @@ -102,7 +102,12 @@ xboxkrnl::BOOLEAN RemoveEntryList(xboxkrnl::PLIST_ENTRY pEntry) _EX_Flink->Blink = _EX_Blink; } - return (_EX_Flink == _EX_Blink); + if (_EX_Blink != nullptr && _EX_Flink != nullptr) { + return (_EX_Flink == _EX_Blink); + } + // If we reach here then it means we have erroneously been called on a detached element. In this case, + // always report FALSE to avoid possible side effects + return FALSE; } xboxkrnl::PLIST_ENTRY RemoveHeadList(xboxkrnl::PLIST_ENTRY pListHead) diff --git a/src/core/kernel/exports/EmuKrnlKe.cpp b/src/core/kernel/exports/EmuKrnlKe.cpp index 57313f9d7..edd30f9a9 100644 --- a/src/core/kernel/exports/EmuKrnlKe.cpp +++ b/src/core/kernel/exports/EmuKrnlKe.cpp @@ -165,7 +165,8 @@ xboxkrnl::KPRCB *KeGetCurrentPrcb() // ****************************************************************** // * KeSetSystemTime() // ****************************************************************** -xboxkrnl::VOID NTAPI xboxkrnl::KeSetSystemTime( +xboxkrnl::VOID NTAPI xboxkrnl::KeSetSystemTime +( IN xboxkrnl::PLARGE_INTEGER NewTime, OUT xboxkrnl::PLARGE_INTEGER OldTime ) @@ -255,6 +256,19 @@ xboxkrnl::VOID NTAPI xboxkrnl::KeSetSystemTime( KiTimerListExpire(&TempList2, OldIrql); } +// ****************************************************************** +// * KeInitializeTimer() +// ****************************************************************** +xboxkrnl::VOID NTAPI xboxkrnl::KeInitializeTimer +( + IN PKTIMER Timer +) +{ + LOG_FORWARD("KeInitializeTimerEx"); + + KeInitializeTimerEx(Timer, NotificationTimer); +} + // Forward KeLowerIrql() to KfLowerIrql() #define KeLowerIrql(NewIrql) \ KfLowerIrql(NewIrql) @@ -1923,6 +1937,8 @@ XBSYSAPI EXPORTNUM(158) xboxkrnl::NTSTATUS NTAPI xboxkrnl::KeWaitForMultipleObje BOOLEAN WaitSatisfied; NTSTATUS WaitStatus; PKMUTANT ObjectMutant; + // Hack variable (remove this when the thread scheduler is here) + bool timeout_set = false; do { // Check if we need to let an APC run. This should immediately trigger APC interrupt via a call to UnlockDispatcherDatabase if (Thread->ApcState.KernelApcPending && (Thread->WaitIrql < APC_LEVEL)) { @@ -1958,7 +1974,7 @@ XBSYSAPI EXPORTNUM(158) xboxkrnl::NTSTATUS NTAPI xboxkrnl::KeWaitForMultipleObje } } else { if (ObjectMutant->Header.Type == MutantObject) { - if ((Thread == ObjectMutant->OwnerThread) && (ObjectMutant->Header.SignalState == MINLONG)) { + if ((Thread == ObjectMutant->OwnerThread) && (ObjectMutant->Header.SignalState == MINLONG)) { KiUnlockDispatcherDatabase(Thread->WaitIrql); ExRaiseStatus(STATUS_MUTANT_LIMIT_EXCEEDED); } else if ((ObjectMutant->Header.SignalState <= 0) && (Thread != ObjectMutant->OwnerThread)) { @@ -1997,22 +2013,36 @@ XBSYSAPI EXPORTNUM(158) xboxkrnl::NTSTATUS NTAPI xboxkrnl::KeWaitForMultipleObje goto NoWait; } - // Setup a timer for the thread - KiTimerLock(); - PKTIMER Timer = &Thread->Timer; - PKWAIT_BLOCK WaitTimer = &Thread->TimerWaitBlock; - WaitBlock->NextWaitBlock = WaitTimer; - Timer->Header.WaitListHead.Flink = &WaitTimer->WaitListEntry; - Timer->Header.WaitListHead.Blink = &WaitTimer->WaitListEntry; - WaitTimer->NextWaitBlock = WaitBlock; - if (KiInsertTreeTimer(Timer, *Timeout) == FALSE) { - WaitStatus = (NTSTATUS)STATUS_TIMEOUT; + // Setup a timer for the thread but only once (for now) + if (!timeout_set) { + KiTimerLock(); + PKTIMER Timer = &Thread->Timer; + PKWAIT_BLOCK WaitTimer = &Thread->TimerWaitBlock; + WaitBlock->NextWaitBlock = WaitTimer; + Timer->Header.WaitListHead.Flink = &WaitTimer->WaitListEntry; + Timer->Header.WaitListHead.Blink = &WaitTimer->WaitListEntry; + WaitTimer->NextWaitBlock = WaitBlock; + if (KiInsertTreeTimer(Timer, *Timeout) == FALSE) { + WaitStatus = (NTSTATUS)STATUS_TIMEOUT; + KiTimerUnlock(); + goto NoWait; + } + + // Boring, ensure that we only set the thread timer once. Otherwise, this will cause to insert the same + // thread timer over and over in the timer list, which will prevent KiTimerExpiration from removing these + // duplicated timers and thus it will attempt to endlessly remove the same unremoved timers, causing a deadlock. + // This can be removed once KiSwapThread and the kernel/user APCs are implemented + timeout_set = true; + DueTime.QuadPart = Timer->DueTime.QuadPart; KiTimerUnlock(); - goto NoWait; } - DueTime.QuadPart = Timer->DueTime.QuadPart; - KiTimerUnlock(); + // KiTimerExpiration has removed the timer but the objects were not signaled, so we have a timeout + // (remove this when the thread scheduler is here) + if (Thread->Timer.Header.Inserted == FALSE) { + WaitStatus = (NTSTATUS)(STATUS_TIMEOUT); + goto NoWait; + } } else { WaitBlock->NextWaitBlock = WaitBlock; @@ -2028,9 +2058,9 @@ XBSYSAPI EXPORTNUM(158) xboxkrnl::NTSTATUS NTAPI xboxkrnl::KeWaitForMultipleObje /* - TODO: We can't implement this and the return values until we have our own thread schedular - For now, we'll have to implement waiting here instead of the schedular. - This code can all be enabled once we have CPU emulation and our own schedular in v1.0 + TODO: We can't implement this and the return values until we have our own thread scheduler + For now, we'll have to implement waiting here instead of the scheduler. + This code can all be enabled once we have CPU emulation and our own scheduler in v1.0 */ // Insert the WaitBlock @@ -2061,7 +2091,7 @@ XBSYSAPI EXPORTNUM(158) xboxkrnl::NTSTATUS NTAPI xboxkrnl::KeWaitForMultipleObje // return WaitStatus; //} - // TODO: Remove this after we have our own schedular and the above is implemented + // TODO: Remove this after we have our own scheduler and the above is implemented Sleep(0); // Reduce the timout if necessary @@ -2076,6 +2106,10 @@ XBSYSAPI EXPORTNUM(158) xboxkrnl::NTSTATUS NTAPI xboxkrnl::KeWaitForMultipleObje } } while (TRUE); + // NOTE: we don't need to remove the wait blocks for the object and/or the timer because InsertTailList is disabled at + // the moment, which means they are never attached to the object wait list. TimerWaitBlock can also stay attached to the timer wait + // list since KiTimerExpiration disregards it for now. + // The waiting thead has been alerted, or an APC needs to be delivered // So unlock the dispatcher database, lower the IRQ and return the status KiUnlockDispatcherDatabase(Thread->WaitIrql); @@ -2090,6 +2124,14 @@ NoWait: // Unlock the database and return the status //TODO: KiAdjustQuantumThread(Thread); + // Don't forget to remove the thread timer if the objects were signaled before the timer expired + // (remove this when the thread scheduler is here) + if (timeout_set && Thread->Timer.Header.Inserted == TRUE) { + KiTimerLock(); + KxRemoveTreeTimer(&Thread->Timer); + KiTimerUnlock(); + } + KiUnlockDispatcherDatabase(Thread->WaitIrql); if (WaitStatus == STATUS_USER_APC) { @@ -2135,6 +2177,8 @@ XBSYSAPI EXPORTNUM(159) xboxkrnl::NTSTATUS NTAPI xboxkrnl::KeWaitForSingleObject KWAIT_BLOCK StackWaitBlock; PKWAIT_BLOCK WaitBlock = &StackWaitBlock; NTSTATUS WaitStatus; + // Hack variable (remove this when the thread scheduler is here) + bool timeout_set = false; do { // Check if we need to let an APC run. This should immediately trigger APC interrupt via a call to UnlockDispatcherDatabase if (Thread->ApcState.KernelApcPending && (Thread->WaitIrql < APC_LEVEL)) { @@ -2182,31 +2226,46 @@ XBSYSAPI EXPORTNUM(159) xboxkrnl::NTSTATUS NTAPI xboxkrnl::KeWaitForSingleObject goto NoWait; } - // Setup a timer for the thread - KiTimerLock(); - PKTIMER Timer = &Thread->Timer; - PKWAIT_BLOCK WaitTimer = &Thread->TimerWaitBlock; - WaitBlock->NextWaitBlock = WaitTimer; - Timer->Header.WaitListHead.Flink = &WaitTimer->WaitListEntry; - Timer->Header.WaitListHead.Blink = &WaitTimer->WaitListEntry; - WaitTimer->NextWaitBlock = WaitBlock; - if (KiInsertTreeTimer(Timer, *Timeout) == FALSE) { - WaitStatus = (NTSTATUS)STATUS_TIMEOUT; + // Setup a timer for the thread but only once (for now) + if (!timeout_set) { + KiTimerLock(); + PKTIMER Timer = &Thread->Timer; + PKWAIT_BLOCK WaitTimer = &Thread->TimerWaitBlock; + WaitBlock->NextWaitBlock = WaitTimer; + Timer->Header.WaitListHead.Flink = &WaitTimer->WaitListEntry; + Timer->Header.WaitListHead.Blink = &WaitTimer->WaitListEntry; + WaitTimer->NextWaitBlock = WaitBlock; + if (KiInsertTreeTimer(Timer, *Timeout) == FALSE) { + DBG_PRINTF("%s: KiInsertTreeTimer(Timer, *Timeout) == FALSE\n", __func__); + WaitStatus = (NTSTATUS)STATUS_TIMEOUT; + KiTimerUnlock(); + goto NoWait; + } + + // Boring, ensure that we only set the thread timer once. Otherwise, this will cause to insert the same + // thread timer over and over in the timer list, which will prevent KiTimerExpiration from removing these + // duplicated timers and thus it will attempt to endlessly remove the same unremoved timers, causing a deadlock. + // This can be removed once KiSwapThread and the kernel/user APCs are implemented + timeout_set = true; + DueTime.QuadPart = Timer->DueTime.QuadPart; KiTimerUnlock(); - goto NoWait; } - DueTime.QuadPart = Timer->DueTime.QuadPart; - KiTimerUnlock(); + // KiTimerExpiration has removed the timer but the object was not signaled, so we have a timeout + // (remove this when the thread scheduler is here) + if (Thread->Timer.Header.Inserted == FALSE) { + WaitStatus = (NTSTATUS)(STATUS_TIMEOUT); + goto NoWait; + } } else { WaitBlock->NextWaitBlock = WaitBlock; } /* - TODO: We can't implement this and the return values until we have our own thread schedular - For now, we'll have to implement waiting here instead of the schedular. - This code can all be enabled once we have CPU emulation and our own schedular in v1.0 + TODO: We can't implement this and the return values until we have our own thread scheduler + For now, we'll have to implement waiting here instead of the scheduler. + This code can all be enabled once we have CPU emulation and our own scheduler in v1.0 */ // Insert the WaitBlock @@ -2238,7 +2297,7 @@ XBSYSAPI EXPORTNUM(159) xboxkrnl::NTSTATUS NTAPI xboxkrnl::KeWaitForSingleObject return WaitStatus; } */ - // TODO: Remove this after we have our own schedular and the above is implemented + // TODO: Remove this after we have our own scheduler and the above is implemented Sleep(0); // Reduce the timout if necessary @@ -2253,6 +2312,10 @@ XBSYSAPI EXPORTNUM(159) xboxkrnl::NTSTATUS NTAPI xboxkrnl::KeWaitForSingleObject } } while (TRUE); + // NOTE: we don't need to remove the wait blocks for the object and/or the timer because InsertTailList is disabled at + // the moment, which means they are never attached to the object wait list. TimerWaitBlock can also stay attached to the timer wait + // list since KiTimerExpiration disregards it for now. + // The waiting thead has been alerted, or an APC needs to be delivered // So unlock the dispatcher database, lower the IRQ and return the status KiUnlockDispatcherDatabase(Thread->WaitIrql); @@ -2267,6 +2330,14 @@ NoWait: // Unlock the database and return the status //TODO: KiAdjustQuantumThread(Thread); + // Don't forget to remove the thread timer if the object was signaled before the timer expired + // (remove this when the thread scheduler is here) + if (timeout_set && Thread->Timer.Header.Inserted == TRUE) { + KiTimerLock(); + KxRemoveTreeTimer(&Thread->Timer); + KiTimerUnlock(); + } + KiUnlockDispatcherDatabase(Thread->WaitIrql); if (WaitStatus == STATUS_USER_APC) { diff --git a/src/core/kernel/exports/EmuKrnlKe.h b/src/core/kernel/exports/EmuKrnlKe.h index 42d3c2457..148104c0f 100644 --- a/src/core/kernel/exports/EmuKrnlKe.h +++ b/src/core/kernel/exports/EmuKrnlKe.h @@ -27,8 +27,14 @@ namespace xboxkrnl { - VOID NTAPI KeSetSystemTime( + VOID NTAPI KeSetSystemTime + ( IN PLARGE_INTEGER NewTime, OUT PLARGE_INTEGER OldTime ); + + VOID NTAPI KeInitializeTimer + ( + IN PKTIMER Timer + ); } diff --git a/src/core/kernel/exports/EmuKrnlKi.cpp b/src/core/kernel/exports/EmuKrnlKi.cpp index 1cb489da4..ac7280b4f 100644 --- a/src/core/kernel/exports/EmuKrnlKi.cpp +++ b/src/core/kernel/exports/EmuKrnlKi.cpp @@ -91,7 +91,7 @@ namespace xboxkrnl #define MAX_TIMER_DPCS 16 -#define ASSERT_TIMER_LOCKED assert(KiTimerMtx.Acquired == true) +#define ASSERT_TIMER_LOCKED assert(KiTimerMtx.Acquired > 0) const xboxkrnl::ULONG CLOCK_TIME_INCREMENT = 0x2710; xboxkrnl::KDPC KiTimerExpireDpc; @@ -118,16 +118,17 @@ xboxkrnl::VOID xboxkrnl::KiInitSystem() xboxkrnl::VOID xboxkrnl::KiTimerLock() { KiTimerMtx.Mtx.lock(); - KiTimerMtx.Acquired = true; + KiTimerMtx.Acquired++; } xboxkrnl::VOID xboxkrnl::KiTimerUnlock() { - KiTimerMtx.Acquired = false; + KiTimerMtx.Acquired--; KiTimerMtx.Mtx.unlock(); } -xboxkrnl::VOID xboxkrnl::KiClockIsr( +xboxkrnl::VOID xboxkrnl::KiClockIsr +( unsigned int ScalingFactor ) { @@ -165,10 +166,10 @@ xboxkrnl::VOID xboxkrnl::KiClockIsr( if (KiTimerMtx.Mtx.try_lock()) { KiTimerMtx.Acquired = true; // Check if a timer has expired - Hand = KeTickCount & (TIMER_TABLE_SIZE - 1); + Hand = OldKeTickCount & (TIMER_TABLE_SIZE - 1); if (KiTimerTableListHead[Hand].Entry.Flink != &KiTimerTableListHead[Hand].Entry && (ULONGLONG)InterruptTime.QuadPart >= KiTimerTableListHead[Hand].Time.QuadPart) { - KeInsertQueueDpc(&KiTimerExpireDpc, (PVOID)OldKeTickCount, 0); + KeInsertQueueDpc(&KiTimerExpireDpc, (PVOID)Hand, 0); } KiTimerMtx.Acquired = false; KiTimerMtx.Mtx.unlock(); @@ -177,7 +178,8 @@ xboxkrnl::VOID xboxkrnl::KiClockIsr( KfLowerIrql(OldIrql); } -xboxkrnl::VOID NTAPI xboxkrnl::KiCheckTimerTable( +xboxkrnl::VOID NTAPI xboxkrnl::KiCheckTimerTable +( IN xboxkrnl::ULARGE_INTEGER CurrentTime ) { @@ -218,7 +220,8 @@ xboxkrnl::VOID NTAPI xboxkrnl::KiCheckTimerTable( KfLowerIrql(OldIrql); } -xboxkrnl::VOID xboxkrnl::KxInsertTimer( +xboxkrnl::VOID xboxkrnl::KxInsertTimer +( IN xboxkrnl::PKTIMER Timer, IN xboxkrnl::ULONG Hand ) @@ -233,7 +236,8 @@ xboxkrnl::VOID xboxkrnl::KxInsertTimer( } } -xboxkrnl::VOID FASTCALL xboxkrnl::KiCompleteTimer( +xboxkrnl::VOID FASTCALL xboxkrnl::KiCompleteTimer +( IN xboxkrnl::PKTIMER Timer, IN xboxkrnl::ULONG Hand ) @@ -263,7 +267,8 @@ xboxkrnl::VOID FASTCALL xboxkrnl::KiCompleteTimer( } } -xboxkrnl::VOID xboxkrnl::KiRemoveEntryTimer( +xboxkrnl::VOID xboxkrnl::KiRemoveEntryTimer +( IN xboxkrnl::PKTIMER Timer, IN xboxkrnl::ULONG Hand ) @@ -289,7 +294,8 @@ xboxkrnl::VOID xboxkrnl::KiRemoveEntryTimer( Timer->TimerListEntry.Blink = NULL; } -xboxkrnl::VOID xboxkrnl::KxRemoveTreeTimer( +xboxkrnl::VOID xboxkrnl::KxRemoveTreeTimer +( IN xboxkrnl::PKTIMER Timer ) { @@ -314,7 +320,8 @@ xboxkrnl::VOID xboxkrnl::KxRemoveTreeTimer( } } -xboxkrnl::BOOLEAN FASTCALL xboxkrnl::KiInsertTimerTable( +xboxkrnl::BOOLEAN FASTCALL xboxkrnl::KiInsertTimerTable +( IN xboxkrnl::PKTIMER Timer, IN xboxkrnl::ULONG Hand ) @@ -370,7 +377,8 @@ xboxkrnl::BOOLEAN FASTCALL xboxkrnl::KiInsertTimerTable( return Expired; } -xboxkrnl::BOOLEAN FASTCALL xboxkrnl::KiInsertTreeTimer( +xboxkrnl::BOOLEAN FASTCALL xboxkrnl::KiInsertTreeTimer +( IN xboxkrnl::PKTIMER Timer, IN xboxkrnl::LARGE_INTEGER Interval ) @@ -400,14 +408,16 @@ xboxkrnl::BOOLEAN FASTCALL xboxkrnl::KiInsertTreeTimer( return Inserted; } -xboxkrnl::ULONG xboxkrnl::KiComputeTimerTableIndex( +xboxkrnl::ULONG xboxkrnl::KiComputeTimerTableIndex +( IN xboxkrnl::ULONGLONG Interval ) { return (Interval / CLOCK_TIME_INCREMENT) & (TIMER_TABLE_SIZE - 1); } -xboxkrnl::BOOLEAN xboxkrnl::KiComputeDueTime( +xboxkrnl::BOOLEAN xboxkrnl::KiComputeDueTime +( IN xboxkrnl::PKTIMER Timer, IN xboxkrnl::LARGE_INTEGER DueTime, OUT xboxkrnl::PULONG Hand) @@ -455,7 +465,8 @@ xboxkrnl::BOOLEAN xboxkrnl::KiComputeDueTime( return TRUE; } -xboxkrnl::BOOLEAN FASTCALL xboxkrnl::KiSignalTimer( +xboxkrnl::BOOLEAN FASTCALL xboxkrnl::KiSignalTimer +( IN xboxkrnl::PKTIMER Timer ) { @@ -509,7 +520,8 @@ xboxkrnl::BOOLEAN FASTCALL xboxkrnl::KiSignalTimer( return RequestInterrupt; } -xboxkrnl::VOID NTAPI xboxkrnl::KiTimerExpiration( +xboxkrnl::VOID NTAPI xboxkrnl::KiTimerExpiration +( IN xboxkrnl::PKDPC Dpc, IN xboxkrnl::PVOID DeferredContext, IN xboxkrnl::PVOID SystemArgument1, @@ -752,7 +764,8 @@ xboxkrnl::VOID NTAPI xboxkrnl::KiTimerExpiration( } } -xboxkrnl::VOID FASTCALL xboxkrnl::KiTimerListExpire( +xboxkrnl::VOID FASTCALL xboxkrnl::KiTimerListExpire +( IN xboxkrnl::PLIST_ENTRY ExpiredListHead, IN xboxkrnl::KIRQL OldIrql ) @@ -869,8 +882,6 @@ xboxkrnl::VOID FASTCALL xboxkrnl::KiWaitSatisfyAll IN xboxkrnl::PKWAIT_BLOCK WaitBlock ) { - using namespace xboxkrnl; - PKMUTANT Object; PRKTHREAD Thread; PKWAIT_BLOCK WaitBlock1; diff --git a/src/core/kernel/exports/EmuKrnlKi.h b/src/core/kernel/exports/EmuKrnlKi.h index 473c82dc5..f6e25e869 100644 --- a/src/core/kernel/exports/EmuKrnlKi.h +++ b/src/core/kernel/exports/EmuKrnlKi.h @@ -17,7 +17,8 @@ // * If not, write to the Free Software Foundation, Inc., // * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA. // * -// * (c) 2018 Patrick van Logchem +// * (c) 2018 Patrick van Logchem +// * (c) 2019 ergo720 // * // * All rights reserved // * @@ -48,7 +49,7 @@ namespace xboxkrnl typedef struct _KI_TIMER_LOCK { std::recursive_mutex Mtx; - bool Acquired; + int Acquired; } KI_TIMER_LOCK; @@ -58,70 +59,84 @@ namespace xboxkrnl VOID KiTimerUnlock(); - VOID KiClockIsr( + VOID KiClockIsr + ( IN unsigned int ScalingFactor ); - VOID NTAPI KiCheckTimerTable( + VOID NTAPI KiCheckTimerTable + ( IN ULARGE_INTEGER CurrentTime ); - VOID KxInsertTimer( + VOID KxInsertTimer + ( IN PKTIMER Timer, IN ULONG Hand ); - VOID FASTCALL KiCompleteTimer( + VOID FASTCALL KiCompleteTimer + ( IN PKTIMER Timer, IN ULONG Hand - ); + ); - VOID KiRemoveEntryTimer( + VOID KiRemoveEntryTimer + ( IN PKTIMER Timer, IN ULONG Hand ); - VOID KxRemoveTreeTimer( + VOID KxRemoveTreeTimer + ( IN PKTIMER Timer ); - BOOLEAN FASTCALL KiInsertTimerTable( + BOOLEAN FASTCALL KiInsertTimerTable + ( IN PKTIMER Timer, IN ULONG Hand ); - BOOLEAN FASTCALL KiInsertTreeTimer( + BOOLEAN FASTCALL KiInsertTreeTimer + ( IN PKTIMER Timer, IN LARGE_INTEGER Interval ); - ULONG KiComputeTimerTableIndex( + ULONG KiComputeTimerTableIndex + ( IN ULONGLONG Interval ); - BOOLEAN KiComputeDueTime( + BOOLEAN KiComputeDueTime + ( IN PKTIMER Timer, IN LARGE_INTEGER DueTime, OUT PULONG Hand ); - BOOLEAN FASTCALL KiSignalTimer( + BOOLEAN FASTCALL KiSignalTimer + ( IN PKTIMER Timer ); - VOID NTAPI KiTimerExpiration( + VOID NTAPI KiTimerExpiration + ( IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2 ); - VOID FASTCALL KiTimerListExpire( + VOID FASTCALL KiTimerListExpire + ( IN PLIST_ENTRY ExpiredListHead, IN KIRQL OldIrql ); - VOID FASTCALL KiWaitSatisfyAll( + VOID FASTCALL KiWaitSatisfyAll + ( IN PKWAIT_BLOCK WaitBlock ); }; diff --git a/src/core/kernel/support/EmuFS.cpp b/src/core/kernel/support/EmuFS.cpp index 19cf2e1c4..887019ff4 100644 --- a/src/core/kernel/support/EmuFS.cpp +++ b/src/core/kernel/support/EmuFS.cpp @@ -34,7 +34,8 @@ namespace xboxkrnl #include }; -#include "core\kernel\exports\EmuKrnl.h" // For InitializeListHead(), etc. +#include "core\kernel\exports\EmuKrnl.h" // For InitializeListHead(), etc. +#include "core\kernel\exports\EmuKrnlKe.h" #include "EmuFS.h" #include "core\kernel\init\CxbxKrnl.h" #include "core\kernel\memory-manager\VMManager.h" @@ -651,7 +652,20 @@ void EmuGenerateFS(Xbe::TLS *pTLS, void *pTLSData) EThread->Tcb.TlsData = pNewTLS; EThread->UniqueThread = GetCurrentThreadId(); // Set PrcbData.CurrentThread - Prcb->CurrentThread = (xboxkrnl::KTHREAD*)EThread; + Prcb->CurrentThread = (xboxkrnl::KTHREAD*)EThread; + // Initialize the thread header and its wait list + Prcb->CurrentThread->Header.Type = xboxkrnl::ThreadObject; + Prcb->CurrentThread->Header.Size = sizeof(xboxkrnl::KTHREAD) / sizeof(xboxkrnl::LONG); + InitializeListHead(&Prcb->CurrentThread->Header.WaitListHead); + // Also initialize the timer associated with the thread + xboxkrnl::KeInitializeTimer(&Prcb->CurrentThread->Timer); + xboxkrnl::PKWAIT_BLOCK WaitBlock = &Prcb->CurrentThread->TimerWaitBlock; + WaitBlock->Object = &Prcb->CurrentThread->Timer; + WaitBlock->WaitKey = (xboxkrnl::CSHORT)STATUS_TIMEOUT; + WaitBlock->WaitType = xboxkrnl::WaitAny; + WaitBlock->Thread = Prcb->CurrentThread; + WaitBlock->WaitListEntry.Flink = &Prcb->CurrentThread->Timer.Header.WaitListHead; + WaitBlock->WaitListEntry.Blink = &Prcb->CurrentThread->Timer.Header.WaitListHead; } // Make the KPCR struct available to KeGetPcr()