Fix a deadlock in KiTimerExpiration caused by KeWaitForSingleObject

This also fixes LLE USB not working for homebrews
This commit is contained in:
ergo720 2019-03-30 18:06:11 +01:00
parent f58d3ce6cf
commit 9270091d99
7 changed files with 201 additions and 78 deletions

View File

@ -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;

View File

@ -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)

View File

@ -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) {

View File

@ -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
);
}

View File

@ -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;

View File

@ -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 <pvanlogchem@gmail.com>
// * (c) 2018 Patrick van Logchem <pvanlogchem@gmail.com>
// * (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
);
};

View File

@ -34,7 +34,8 @@ namespace xboxkrnl
#include <xboxkrnl/xboxkrnl.h>
};
#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()