Fix a deadlock in KiTimerExpiration caused by KeWaitForSingleObject
This also fixes LLE USB not working for homebrews
This commit is contained in:
parent
f58d3ce6cf
commit
9270091d99
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue