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,
|
MutantObject = 2,
|
||||||
QueueObject = 4,
|
QueueObject = 4,
|
||||||
SemaphoreObject = 5,
|
SemaphoreObject = 5,
|
||||||
|
ThreadObject = 6,
|
||||||
TimerNotificationObject = 8,
|
TimerNotificationObject = 8,
|
||||||
TimerSynchronizationObject = 9,
|
TimerSynchronizationObject = 9,
|
||||||
ApcObject = 0x12,
|
ApcObject = 0x12,
|
||||||
|
@ -1961,7 +1962,7 @@ typedef struct _KTHREAD
|
||||||
/* 0x55/85 */ CHAR WaitMode;
|
/* 0x55/85 */ CHAR WaitMode;
|
||||||
/* 0x56/86 */ CHAR WaitNext;
|
/* 0x56/86 */ CHAR WaitNext;
|
||||||
/* 0x57/87 */ CHAR WaitReason;
|
/* 0x57/87 */ CHAR WaitReason;
|
||||||
/* 0x58/88 */ PVOID WaitBlockList;
|
/* 0x58/88 */ PKWAIT_BLOCK WaitBlockList;
|
||||||
/* 0x5C/92 */ LIST_ENTRY WaitListEntry;
|
/* 0x5C/92 */ LIST_ENTRY WaitListEntry;
|
||||||
/* 0x64/100 */ ULONG WaitTime;
|
/* 0x64/100 */ ULONG WaitTime;
|
||||||
/* 0x68/104 */ ULONG KernelApcDisable;
|
/* 0x68/104 */ ULONG KernelApcDisable;
|
||||||
|
|
|
@ -102,8 +102,13 @@ xboxkrnl::BOOLEAN RemoveEntryList(xboxkrnl::PLIST_ENTRY pEntry)
|
||||||
_EX_Flink->Blink = _EX_Blink;
|
_EX_Flink->Blink = _EX_Blink;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_EX_Blink != nullptr && _EX_Flink != nullptr) {
|
||||||
return (_EX_Flink == _EX_Blink);
|
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)
|
xboxkrnl::PLIST_ENTRY RemoveHeadList(xboxkrnl::PLIST_ENTRY pListHead)
|
||||||
{
|
{
|
||||||
|
|
|
@ -165,7 +165,8 @@ xboxkrnl::KPRCB *KeGetCurrentPrcb()
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
// * KeSetSystemTime()
|
// * KeSetSystemTime()
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
xboxkrnl::VOID NTAPI xboxkrnl::KeSetSystemTime(
|
xboxkrnl::VOID NTAPI xboxkrnl::KeSetSystemTime
|
||||||
|
(
|
||||||
IN xboxkrnl::PLARGE_INTEGER NewTime,
|
IN xboxkrnl::PLARGE_INTEGER NewTime,
|
||||||
OUT xboxkrnl::PLARGE_INTEGER OldTime
|
OUT xboxkrnl::PLARGE_INTEGER OldTime
|
||||||
)
|
)
|
||||||
|
@ -255,6 +256,19 @@ xboxkrnl::VOID NTAPI xboxkrnl::KeSetSystemTime(
|
||||||
KiTimerListExpire(&TempList2, OldIrql);
|
KiTimerListExpire(&TempList2, OldIrql);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ******************************************************************
|
||||||
|
// * KeInitializeTimer()
|
||||||
|
// ******************************************************************
|
||||||
|
xboxkrnl::VOID NTAPI xboxkrnl::KeInitializeTimer
|
||||||
|
(
|
||||||
|
IN PKTIMER Timer
|
||||||
|
)
|
||||||
|
{
|
||||||
|
LOG_FORWARD("KeInitializeTimerEx");
|
||||||
|
|
||||||
|
KeInitializeTimerEx(Timer, NotificationTimer);
|
||||||
|
}
|
||||||
|
|
||||||
// Forward KeLowerIrql() to KfLowerIrql()
|
// Forward KeLowerIrql() to KfLowerIrql()
|
||||||
#define KeLowerIrql(NewIrql) \
|
#define KeLowerIrql(NewIrql) \
|
||||||
KfLowerIrql(NewIrql)
|
KfLowerIrql(NewIrql)
|
||||||
|
@ -1923,6 +1937,8 @@ XBSYSAPI EXPORTNUM(158) xboxkrnl::NTSTATUS NTAPI xboxkrnl::KeWaitForMultipleObje
|
||||||
BOOLEAN WaitSatisfied;
|
BOOLEAN WaitSatisfied;
|
||||||
NTSTATUS WaitStatus;
|
NTSTATUS WaitStatus;
|
||||||
PKMUTANT ObjectMutant;
|
PKMUTANT ObjectMutant;
|
||||||
|
// Hack variable (remove this when the thread scheduler is here)
|
||||||
|
bool timeout_set = false;
|
||||||
do {
|
do {
|
||||||
// Check if we need to let an APC run. This should immediately trigger APC interrupt via a call to UnlockDispatcherDatabase
|
// 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)) {
|
if (Thread->ApcState.KernelApcPending && (Thread->WaitIrql < APC_LEVEL)) {
|
||||||
|
@ -1997,7 +2013,8 @@ XBSYSAPI EXPORTNUM(158) xboxkrnl::NTSTATUS NTAPI xboxkrnl::KeWaitForMultipleObje
|
||||||
goto NoWait;
|
goto NoWait;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup a timer for the thread
|
// Setup a timer for the thread but only once (for now)
|
||||||
|
if (!timeout_set) {
|
||||||
KiTimerLock();
|
KiTimerLock();
|
||||||
PKTIMER Timer = &Thread->Timer;
|
PKTIMER Timer = &Thread->Timer;
|
||||||
PKWAIT_BLOCK WaitTimer = &Thread->TimerWaitBlock;
|
PKWAIT_BLOCK WaitTimer = &Thread->TimerWaitBlock;
|
||||||
|
@ -2011,9 +2028,22 @@ XBSYSAPI EXPORTNUM(158) xboxkrnl::NTSTATUS NTAPI xboxkrnl::KeWaitForMultipleObje
|
||||||
goto NoWait;
|
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;
|
DueTime.QuadPart = Timer->DueTime.QuadPart;
|
||||||
KiTimerUnlock();
|
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 {
|
else {
|
||||||
WaitBlock->NextWaitBlock = WaitBlock;
|
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
|
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 schedular.
|
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 schedular in v1.0
|
This code can all be enabled once we have CPU emulation and our own scheduler in v1.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Insert the WaitBlock
|
// Insert the WaitBlock
|
||||||
|
@ -2061,7 +2091,7 @@ XBSYSAPI EXPORTNUM(158) xboxkrnl::NTSTATUS NTAPI xboxkrnl::KeWaitForMultipleObje
|
||||||
// return WaitStatus;
|
// 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);
|
Sleep(0);
|
||||||
|
|
||||||
// Reduce the timout if necessary
|
// Reduce the timout if necessary
|
||||||
|
@ -2076,6 +2106,10 @@ XBSYSAPI EXPORTNUM(158) xboxkrnl::NTSTATUS NTAPI xboxkrnl::KeWaitForMultipleObje
|
||||||
}
|
}
|
||||||
} while (TRUE);
|
} 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
|
// 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
|
// So unlock the dispatcher database, lower the IRQ and return the status
|
||||||
KiUnlockDispatcherDatabase(Thread->WaitIrql);
|
KiUnlockDispatcherDatabase(Thread->WaitIrql);
|
||||||
|
@ -2090,6 +2124,14 @@ NoWait:
|
||||||
// Unlock the database and return the status
|
// Unlock the database and return the status
|
||||||
//TODO: KiAdjustQuantumThread(Thread);
|
//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);
|
KiUnlockDispatcherDatabase(Thread->WaitIrql);
|
||||||
|
|
||||||
if (WaitStatus == STATUS_USER_APC) {
|
if (WaitStatus == STATUS_USER_APC) {
|
||||||
|
@ -2135,6 +2177,8 @@ XBSYSAPI EXPORTNUM(159) xboxkrnl::NTSTATUS NTAPI xboxkrnl::KeWaitForSingleObject
|
||||||
KWAIT_BLOCK StackWaitBlock;
|
KWAIT_BLOCK StackWaitBlock;
|
||||||
PKWAIT_BLOCK WaitBlock = &StackWaitBlock;
|
PKWAIT_BLOCK WaitBlock = &StackWaitBlock;
|
||||||
NTSTATUS WaitStatus;
|
NTSTATUS WaitStatus;
|
||||||
|
// Hack variable (remove this when the thread scheduler is here)
|
||||||
|
bool timeout_set = false;
|
||||||
do {
|
do {
|
||||||
// Check if we need to let an APC run. This should immediately trigger APC interrupt via a call to UnlockDispatcherDatabase
|
// 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)) {
|
if (Thread->ApcState.KernelApcPending && (Thread->WaitIrql < APC_LEVEL)) {
|
||||||
|
@ -2182,7 +2226,8 @@ XBSYSAPI EXPORTNUM(159) xboxkrnl::NTSTATUS NTAPI xboxkrnl::KeWaitForSingleObject
|
||||||
goto NoWait;
|
goto NoWait;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup a timer for the thread
|
// Setup a timer for the thread but only once (for now)
|
||||||
|
if (!timeout_set) {
|
||||||
KiTimerLock();
|
KiTimerLock();
|
||||||
PKTIMER Timer = &Thread->Timer;
|
PKTIMER Timer = &Thread->Timer;
|
||||||
PKWAIT_BLOCK WaitTimer = &Thread->TimerWaitBlock;
|
PKWAIT_BLOCK WaitTimer = &Thread->TimerWaitBlock;
|
||||||
|
@ -2191,22 +2236,36 @@ XBSYSAPI EXPORTNUM(159) xboxkrnl::NTSTATUS NTAPI xboxkrnl::KeWaitForSingleObject
|
||||||
Timer->Header.WaitListHead.Blink = &WaitTimer->WaitListEntry;
|
Timer->Header.WaitListHead.Blink = &WaitTimer->WaitListEntry;
|
||||||
WaitTimer->NextWaitBlock = WaitBlock;
|
WaitTimer->NextWaitBlock = WaitBlock;
|
||||||
if (KiInsertTreeTimer(Timer, *Timeout) == FALSE) {
|
if (KiInsertTreeTimer(Timer, *Timeout) == FALSE) {
|
||||||
|
DBG_PRINTF("%s: KiInsertTreeTimer(Timer, *Timeout) == FALSE\n", __func__);
|
||||||
WaitStatus = (NTSTATUS)STATUS_TIMEOUT;
|
WaitStatus = (NTSTATUS)STATUS_TIMEOUT;
|
||||||
KiTimerUnlock();
|
KiTimerUnlock();
|
||||||
goto NoWait;
|
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;
|
DueTime.QuadPart = Timer->DueTime.QuadPart;
|
||||||
KiTimerUnlock();
|
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 {
|
else {
|
||||||
WaitBlock->NextWaitBlock = WaitBlock;
|
WaitBlock->NextWaitBlock = WaitBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO: We can't implement this and the return values until we have our own thread schedular
|
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 schedular.
|
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 schedular in v1.0
|
This code can all be enabled once we have CPU emulation and our own scheduler in v1.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Insert the WaitBlock
|
// Insert the WaitBlock
|
||||||
|
@ -2238,7 +2297,7 @@ XBSYSAPI EXPORTNUM(159) xboxkrnl::NTSTATUS NTAPI xboxkrnl::KeWaitForSingleObject
|
||||||
return WaitStatus;
|
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);
|
Sleep(0);
|
||||||
|
|
||||||
// Reduce the timout if necessary
|
// Reduce the timout if necessary
|
||||||
|
@ -2253,6 +2312,10 @@ XBSYSAPI EXPORTNUM(159) xboxkrnl::NTSTATUS NTAPI xboxkrnl::KeWaitForSingleObject
|
||||||
}
|
}
|
||||||
} while (TRUE);
|
} 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
|
// 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
|
// So unlock the dispatcher database, lower the IRQ and return the status
|
||||||
KiUnlockDispatcherDatabase(Thread->WaitIrql);
|
KiUnlockDispatcherDatabase(Thread->WaitIrql);
|
||||||
|
@ -2267,6 +2330,14 @@ NoWait:
|
||||||
// Unlock the database and return the status
|
// Unlock the database and return the status
|
||||||
//TODO: KiAdjustQuantumThread(Thread);
|
//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);
|
KiUnlockDispatcherDatabase(Thread->WaitIrql);
|
||||||
|
|
||||||
if (WaitStatus == STATUS_USER_APC) {
|
if (WaitStatus == STATUS_USER_APC) {
|
||||||
|
|
|
@ -27,8 +27,14 @@
|
||||||
|
|
||||||
namespace xboxkrnl
|
namespace xboxkrnl
|
||||||
{
|
{
|
||||||
VOID NTAPI KeSetSystemTime(
|
VOID NTAPI KeSetSystemTime
|
||||||
|
(
|
||||||
IN PLARGE_INTEGER NewTime,
|
IN PLARGE_INTEGER NewTime,
|
||||||
OUT PLARGE_INTEGER OldTime
|
OUT PLARGE_INTEGER OldTime
|
||||||
);
|
);
|
||||||
|
|
||||||
|
VOID NTAPI KeInitializeTimer
|
||||||
|
(
|
||||||
|
IN PKTIMER Timer
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,7 +91,7 @@ namespace xboxkrnl
|
||||||
|
|
||||||
#define MAX_TIMER_DPCS 16
|
#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;
|
const xboxkrnl::ULONG CLOCK_TIME_INCREMENT = 0x2710;
|
||||||
xboxkrnl::KDPC KiTimerExpireDpc;
|
xboxkrnl::KDPC KiTimerExpireDpc;
|
||||||
|
@ -118,16 +118,17 @@ xboxkrnl::VOID xboxkrnl::KiInitSystem()
|
||||||
xboxkrnl::VOID xboxkrnl::KiTimerLock()
|
xboxkrnl::VOID xboxkrnl::KiTimerLock()
|
||||||
{
|
{
|
||||||
KiTimerMtx.Mtx.lock();
|
KiTimerMtx.Mtx.lock();
|
||||||
KiTimerMtx.Acquired = true;
|
KiTimerMtx.Acquired++;
|
||||||
}
|
}
|
||||||
|
|
||||||
xboxkrnl::VOID xboxkrnl::KiTimerUnlock()
|
xboxkrnl::VOID xboxkrnl::KiTimerUnlock()
|
||||||
{
|
{
|
||||||
KiTimerMtx.Acquired = false;
|
KiTimerMtx.Acquired--;
|
||||||
KiTimerMtx.Mtx.unlock();
|
KiTimerMtx.Mtx.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
xboxkrnl::VOID xboxkrnl::KiClockIsr(
|
xboxkrnl::VOID xboxkrnl::KiClockIsr
|
||||||
|
(
|
||||||
unsigned int ScalingFactor
|
unsigned int ScalingFactor
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
@ -165,10 +166,10 @@ xboxkrnl::VOID xboxkrnl::KiClockIsr(
|
||||||
if (KiTimerMtx.Mtx.try_lock()) {
|
if (KiTimerMtx.Mtx.try_lock()) {
|
||||||
KiTimerMtx.Acquired = true;
|
KiTimerMtx.Acquired = true;
|
||||||
// Check if a timer has expired
|
// 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 &&
|
if (KiTimerTableListHead[Hand].Entry.Flink != &KiTimerTableListHead[Hand].Entry &&
|
||||||
(ULONGLONG)InterruptTime.QuadPart >= KiTimerTableListHead[Hand].Time.QuadPart) {
|
(ULONGLONG)InterruptTime.QuadPart >= KiTimerTableListHead[Hand].Time.QuadPart) {
|
||||||
KeInsertQueueDpc(&KiTimerExpireDpc, (PVOID)OldKeTickCount, 0);
|
KeInsertQueueDpc(&KiTimerExpireDpc, (PVOID)Hand, 0);
|
||||||
}
|
}
|
||||||
KiTimerMtx.Acquired = false;
|
KiTimerMtx.Acquired = false;
|
||||||
KiTimerMtx.Mtx.unlock();
|
KiTimerMtx.Mtx.unlock();
|
||||||
|
@ -177,7 +178,8 @@ xboxkrnl::VOID xboxkrnl::KiClockIsr(
|
||||||
KfLowerIrql(OldIrql);
|
KfLowerIrql(OldIrql);
|
||||||
}
|
}
|
||||||
|
|
||||||
xboxkrnl::VOID NTAPI xboxkrnl::KiCheckTimerTable(
|
xboxkrnl::VOID NTAPI xboxkrnl::KiCheckTimerTable
|
||||||
|
(
|
||||||
IN xboxkrnl::ULARGE_INTEGER CurrentTime
|
IN xboxkrnl::ULARGE_INTEGER CurrentTime
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
@ -218,7 +220,8 @@ xboxkrnl::VOID NTAPI xboxkrnl::KiCheckTimerTable(
|
||||||
KfLowerIrql(OldIrql);
|
KfLowerIrql(OldIrql);
|
||||||
}
|
}
|
||||||
|
|
||||||
xboxkrnl::VOID xboxkrnl::KxInsertTimer(
|
xboxkrnl::VOID xboxkrnl::KxInsertTimer
|
||||||
|
(
|
||||||
IN xboxkrnl::PKTIMER Timer,
|
IN xboxkrnl::PKTIMER Timer,
|
||||||
IN xboxkrnl::ULONG Hand
|
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::PKTIMER Timer,
|
||||||
IN xboxkrnl::ULONG Hand
|
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::PKTIMER Timer,
|
||||||
IN xboxkrnl::ULONG Hand
|
IN xboxkrnl::ULONG Hand
|
||||||
)
|
)
|
||||||
|
@ -289,7 +294,8 @@ xboxkrnl::VOID xboxkrnl::KiRemoveEntryTimer(
|
||||||
Timer->TimerListEntry.Blink = NULL;
|
Timer->TimerListEntry.Blink = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
xboxkrnl::VOID xboxkrnl::KxRemoveTreeTimer(
|
xboxkrnl::VOID xboxkrnl::KxRemoveTreeTimer
|
||||||
|
(
|
||||||
IN xboxkrnl::PKTIMER Timer
|
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::PKTIMER Timer,
|
||||||
IN xboxkrnl::ULONG Hand
|
IN xboxkrnl::ULONG Hand
|
||||||
)
|
)
|
||||||
|
@ -370,7 +377,8 @@ xboxkrnl::BOOLEAN FASTCALL xboxkrnl::KiInsertTimerTable(
|
||||||
return Expired;
|
return Expired;
|
||||||
}
|
}
|
||||||
|
|
||||||
xboxkrnl::BOOLEAN FASTCALL xboxkrnl::KiInsertTreeTimer(
|
xboxkrnl::BOOLEAN FASTCALL xboxkrnl::KiInsertTreeTimer
|
||||||
|
(
|
||||||
IN xboxkrnl::PKTIMER Timer,
|
IN xboxkrnl::PKTIMER Timer,
|
||||||
IN xboxkrnl::LARGE_INTEGER Interval
|
IN xboxkrnl::LARGE_INTEGER Interval
|
||||||
)
|
)
|
||||||
|
@ -400,14 +408,16 @@ xboxkrnl::BOOLEAN FASTCALL xboxkrnl::KiInsertTreeTimer(
|
||||||
return Inserted;
|
return Inserted;
|
||||||
}
|
}
|
||||||
|
|
||||||
xboxkrnl::ULONG xboxkrnl::KiComputeTimerTableIndex(
|
xboxkrnl::ULONG xboxkrnl::KiComputeTimerTableIndex
|
||||||
|
(
|
||||||
IN xboxkrnl::ULONGLONG Interval
|
IN xboxkrnl::ULONGLONG Interval
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return (Interval / CLOCK_TIME_INCREMENT) & (TIMER_TABLE_SIZE - 1);
|
return (Interval / CLOCK_TIME_INCREMENT) & (TIMER_TABLE_SIZE - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
xboxkrnl::BOOLEAN xboxkrnl::KiComputeDueTime(
|
xboxkrnl::BOOLEAN xboxkrnl::KiComputeDueTime
|
||||||
|
(
|
||||||
IN xboxkrnl::PKTIMER Timer,
|
IN xboxkrnl::PKTIMER Timer,
|
||||||
IN xboxkrnl::LARGE_INTEGER DueTime,
|
IN xboxkrnl::LARGE_INTEGER DueTime,
|
||||||
OUT xboxkrnl::PULONG Hand)
|
OUT xboxkrnl::PULONG Hand)
|
||||||
|
@ -455,7 +465,8 @@ xboxkrnl::BOOLEAN xboxkrnl::KiComputeDueTime(
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
xboxkrnl::BOOLEAN FASTCALL xboxkrnl::KiSignalTimer(
|
xboxkrnl::BOOLEAN FASTCALL xboxkrnl::KiSignalTimer
|
||||||
|
(
|
||||||
IN xboxkrnl::PKTIMER Timer
|
IN xboxkrnl::PKTIMER Timer
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
@ -509,7 +520,8 @@ xboxkrnl::BOOLEAN FASTCALL xboxkrnl::KiSignalTimer(
|
||||||
return RequestInterrupt;
|
return RequestInterrupt;
|
||||||
}
|
}
|
||||||
|
|
||||||
xboxkrnl::VOID NTAPI xboxkrnl::KiTimerExpiration(
|
xboxkrnl::VOID NTAPI xboxkrnl::KiTimerExpiration
|
||||||
|
(
|
||||||
IN xboxkrnl::PKDPC Dpc,
|
IN xboxkrnl::PKDPC Dpc,
|
||||||
IN xboxkrnl::PVOID DeferredContext,
|
IN xboxkrnl::PVOID DeferredContext,
|
||||||
IN xboxkrnl::PVOID SystemArgument1,
|
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::PLIST_ENTRY ExpiredListHead,
|
||||||
IN xboxkrnl::KIRQL OldIrql
|
IN xboxkrnl::KIRQL OldIrql
|
||||||
)
|
)
|
||||||
|
@ -869,8 +882,6 @@ xboxkrnl::VOID FASTCALL xboxkrnl::KiWaitSatisfyAll
|
||||||
IN xboxkrnl::PKWAIT_BLOCK WaitBlock
|
IN xboxkrnl::PKWAIT_BLOCK WaitBlock
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
using namespace xboxkrnl;
|
|
||||||
|
|
||||||
PKMUTANT Object;
|
PKMUTANT Object;
|
||||||
PRKTHREAD Thread;
|
PRKTHREAD Thread;
|
||||||
PKWAIT_BLOCK WaitBlock1;
|
PKWAIT_BLOCK WaitBlock1;
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
|
// * 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
|
// * All rights reserved
|
||||||
// *
|
// *
|
||||||
|
@ -48,7 +49,7 @@ namespace xboxkrnl
|
||||||
typedef struct _KI_TIMER_LOCK
|
typedef struct _KI_TIMER_LOCK
|
||||||
{
|
{
|
||||||
std::recursive_mutex Mtx;
|
std::recursive_mutex Mtx;
|
||||||
bool Acquired;
|
int Acquired;
|
||||||
} KI_TIMER_LOCK;
|
} KI_TIMER_LOCK;
|
||||||
|
|
||||||
|
|
||||||
|
@ -58,70 +59,84 @@ namespace xboxkrnl
|
||||||
|
|
||||||
VOID KiTimerUnlock();
|
VOID KiTimerUnlock();
|
||||||
|
|
||||||
VOID KiClockIsr(
|
VOID KiClockIsr
|
||||||
|
(
|
||||||
IN unsigned int ScalingFactor
|
IN unsigned int ScalingFactor
|
||||||
);
|
);
|
||||||
|
|
||||||
VOID NTAPI KiCheckTimerTable(
|
VOID NTAPI KiCheckTimerTable
|
||||||
|
(
|
||||||
IN ULARGE_INTEGER CurrentTime
|
IN ULARGE_INTEGER CurrentTime
|
||||||
);
|
);
|
||||||
|
|
||||||
VOID KxInsertTimer(
|
VOID KxInsertTimer
|
||||||
|
(
|
||||||
IN PKTIMER Timer,
|
IN PKTIMER Timer,
|
||||||
IN ULONG Hand
|
IN ULONG Hand
|
||||||
);
|
);
|
||||||
|
|
||||||
VOID FASTCALL KiCompleteTimer(
|
VOID FASTCALL KiCompleteTimer
|
||||||
|
(
|
||||||
IN PKTIMER Timer,
|
IN PKTIMER Timer,
|
||||||
IN ULONG Hand
|
IN ULONG Hand
|
||||||
);
|
);
|
||||||
|
|
||||||
VOID KiRemoveEntryTimer(
|
VOID KiRemoveEntryTimer
|
||||||
|
(
|
||||||
IN PKTIMER Timer,
|
IN PKTIMER Timer,
|
||||||
IN ULONG Hand
|
IN ULONG Hand
|
||||||
);
|
);
|
||||||
|
|
||||||
VOID KxRemoveTreeTimer(
|
VOID KxRemoveTreeTimer
|
||||||
|
(
|
||||||
IN PKTIMER Timer
|
IN PKTIMER Timer
|
||||||
);
|
);
|
||||||
|
|
||||||
BOOLEAN FASTCALL KiInsertTimerTable(
|
BOOLEAN FASTCALL KiInsertTimerTable
|
||||||
|
(
|
||||||
IN PKTIMER Timer,
|
IN PKTIMER Timer,
|
||||||
IN ULONG Hand
|
IN ULONG Hand
|
||||||
);
|
);
|
||||||
|
|
||||||
BOOLEAN FASTCALL KiInsertTreeTimer(
|
BOOLEAN FASTCALL KiInsertTreeTimer
|
||||||
|
(
|
||||||
IN PKTIMER Timer,
|
IN PKTIMER Timer,
|
||||||
IN LARGE_INTEGER Interval
|
IN LARGE_INTEGER Interval
|
||||||
);
|
);
|
||||||
|
|
||||||
ULONG KiComputeTimerTableIndex(
|
ULONG KiComputeTimerTableIndex
|
||||||
|
(
|
||||||
IN ULONGLONG Interval
|
IN ULONGLONG Interval
|
||||||
);
|
);
|
||||||
|
|
||||||
BOOLEAN KiComputeDueTime(
|
BOOLEAN KiComputeDueTime
|
||||||
|
(
|
||||||
IN PKTIMER Timer,
|
IN PKTIMER Timer,
|
||||||
IN LARGE_INTEGER DueTime,
|
IN LARGE_INTEGER DueTime,
|
||||||
OUT PULONG Hand
|
OUT PULONG Hand
|
||||||
);
|
);
|
||||||
|
|
||||||
BOOLEAN FASTCALL KiSignalTimer(
|
BOOLEAN FASTCALL KiSignalTimer
|
||||||
|
(
|
||||||
IN PKTIMER Timer
|
IN PKTIMER Timer
|
||||||
);
|
);
|
||||||
|
|
||||||
VOID NTAPI KiTimerExpiration(
|
VOID NTAPI KiTimerExpiration
|
||||||
|
(
|
||||||
IN PKDPC Dpc,
|
IN PKDPC Dpc,
|
||||||
IN PVOID DeferredContext,
|
IN PVOID DeferredContext,
|
||||||
IN PVOID SystemArgument1,
|
IN PVOID SystemArgument1,
|
||||||
IN PVOID SystemArgument2
|
IN PVOID SystemArgument2
|
||||||
);
|
);
|
||||||
|
|
||||||
VOID FASTCALL KiTimerListExpire(
|
VOID FASTCALL KiTimerListExpire
|
||||||
|
(
|
||||||
IN PLIST_ENTRY ExpiredListHead,
|
IN PLIST_ENTRY ExpiredListHead,
|
||||||
IN KIRQL OldIrql
|
IN KIRQL OldIrql
|
||||||
);
|
);
|
||||||
|
|
||||||
VOID FASTCALL KiWaitSatisfyAll(
|
VOID FASTCALL KiWaitSatisfyAll
|
||||||
|
(
|
||||||
IN PKWAIT_BLOCK WaitBlock
|
IN PKWAIT_BLOCK WaitBlock
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -35,6 +35,7 @@ namespace xboxkrnl
|
||||||
};
|
};
|
||||||
|
|
||||||
#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 "EmuFS.h"
|
||||||
#include "core\kernel\init\CxbxKrnl.h"
|
#include "core\kernel\init\CxbxKrnl.h"
|
||||||
#include "core\kernel\memory-manager\VMManager.h"
|
#include "core\kernel\memory-manager\VMManager.h"
|
||||||
|
@ -652,6 +653,19 @@ void EmuGenerateFS(Xbe::TLS *pTLS, void *pTLSData)
|
||||||
EThread->UniqueThread = GetCurrentThreadId();
|
EThread->UniqueThread = GetCurrentThreadId();
|
||||||
// Set PrcbData.CurrentThread
|
// 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()
|
// Make the KPCR struct available to KeGetPcr()
|
||||||
|
|
Loading…
Reference in New Issue