Add lock to kernel timer functions
This commit is contained in:
parent
bd0eced253
commit
4f86a5a26f
|
@ -105,11 +105,16 @@ VOID xboxkrnl::KiClockIsr(unsigned int ScalingFactor)
|
|||
// Update the tick counter
|
||||
KeTickCount += ScalingFactor;
|
||||
|
||||
// Check if a timer has expired
|
||||
Hand = KeTickCount & (TIMER_TABLE_SIZE - 1);
|
||||
if (KiTimerTableListHead[Hand].Entry.Flink != &KiTimerTableListHead[Hand].Entry &&
|
||||
InterruptTime.QuadPart >= KiTimerTableListHead[Hand].Time.QuadPart) {
|
||||
KeInsertQueueDpc(&KiTimerExpireDpc, (PVOID)&KeTickCount, 0);
|
||||
// Because this function must be fast to continuously update the kernel clocks, if somebody else is currently
|
||||
// holding the lock, we won't wait and instead skip the check of the timers for this cycle
|
||||
if (TimerMtx.try_lock()) {
|
||||
// Check if a timer has expired
|
||||
Hand = KeTickCount & (TIMER_TABLE_SIZE - 1);
|
||||
if (KiTimerTableListHead[Hand].Entry.Flink != &KiTimerTableListHead[Hand].Entry &&
|
||||
InterruptTime.QuadPart >= KiTimerTableListHead[Hand].Time.QuadPart) {
|
||||
KeInsertQueueDpc(&KiTimerExpireDpc, (PVOID)&KeTickCount, 0);
|
||||
}
|
||||
TimerMtx.unlock();
|
||||
}
|
||||
|
||||
KfLowerIrql(OldIrql);
|
||||
|
@ -120,12 +125,15 @@ VOID xboxkrnl::KxInsertTimer(
|
|||
IN xboxkrnl::ULONG Hand
|
||||
)
|
||||
{
|
||||
TimerMtx.lock();
|
||||
|
||||
/* Try to insert the timer */
|
||||
if (KiInsertTimerTable(Timer, Hand))
|
||||
{
|
||||
/* Complete it */
|
||||
KiCompleteTimer(Timer, Hand);
|
||||
}
|
||||
TimerMtx.unlock();
|
||||
}
|
||||
|
||||
VOID FASTCALL xboxkrnl::KiCompleteTimer(
|
||||
|
@ -136,6 +144,8 @@ VOID FASTCALL xboxkrnl::KiCompleteTimer(
|
|||
LIST_ENTRY ListHead;
|
||||
BOOLEAN RequestInterrupt = FALSE;
|
||||
|
||||
TimerMtx.lock();
|
||||
|
||||
/* Remove it from the timer list */
|
||||
KiRemoveEntryTimer(Timer, Hand);
|
||||
|
||||
|
@ -154,6 +164,7 @@ VOID FASTCALL xboxkrnl::KiCompleteTimer(
|
|||
if (RequestInterrupt) {
|
||||
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
||||
}
|
||||
TimerMtx.unlock();
|
||||
}
|
||||
|
||||
VOID xboxkrnl::KiRemoveEntryTimer(
|
||||
|
@ -164,6 +175,8 @@ VOID xboxkrnl::KiRemoveEntryTimer(
|
|||
ULONG Hand;
|
||||
PKTIMER_TABLE_ENTRY TableEntry;
|
||||
|
||||
TimerMtx.lock();
|
||||
|
||||
/* Remove the timer from the timer list and check if it's empty */
|
||||
if (RemoveEntryList(&Timer->TimerListEntry))
|
||||
{
|
||||
|
@ -179,6 +192,7 @@ VOID xboxkrnl::KiRemoveEntryTimer(
|
|||
/* Clear the list entries so we can tell the timer is gone */
|
||||
Timer->TimerListEntry.Flink = NULL;
|
||||
Timer->TimerListEntry.Blink = NULL;
|
||||
TimerMtx.unlock();
|
||||
}
|
||||
|
||||
VOID xboxkrnl::KxRemoveTreeTimer(
|
||||
|
@ -188,6 +202,8 @@ VOID xboxkrnl::KxRemoveTreeTimer(
|
|||
ULONG Hand = KiComputeTimerTableIndex(Timer->DueTime.QuadPart);
|
||||
PKTIMER_TABLE_ENTRY TimerEntry;
|
||||
|
||||
TimerMtx.lock();
|
||||
|
||||
/* Set the timer as non-inserted */
|
||||
Timer->Header.Inserted = FALSE;
|
||||
|
||||
|
@ -202,6 +218,7 @@ VOID xboxkrnl::KxRemoveTreeTimer(
|
|||
TimerEntry->Time.u.HighPart = 0xFFFFFFFF;
|
||||
}
|
||||
}
|
||||
TimerMtx.unlock();
|
||||
}
|
||||
|
||||
xboxkrnl::BOOLEAN FASTCALL xboxkrnl::KiInsertTimerTable(
|
||||
|
@ -217,6 +234,8 @@ xboxkrnl::BOOLEAN FASTCALL xboxkrnl::KiInsertTimerTable(
|
|||
|
||||
DBG_PRINTF("%s: inserting Timer %p, Hand: %lu\n", __func__, Timer, Hand);
|
||||
|
||||
TimerMtx.lock();
|
||||
|
||||
/* Check if the period is zero */
|
||||
if (!Timer->Period) {
|
||||
Timer->Header.SignalState = FALSE;
|
||||
|
@ -253,6 +272,7 @@ xboxkrnl::BOOLEAN FASTCALL xboxkrnl::KiInsertTimerTable(
|
|||
Expired = TRUE;
|
||||
}
|
||||
}
|
||||
TimerMtx.unlock();
|
||||
|
||||
/* Return expired state */
|
||||
return Expired;
|
||||
|
@ -266,6 +286,8 @@ xboxkrnl::BOOLEAN FASTCALL xboxkrnl::KiInsertTreeTimer(
|
|||
BOOLEAN Inserted = FALSE;
|
||||
ULONG Hand = 0;
|
||||
|
||||
TimerMtx.lock();
|
||||
|
||||
/* Setup the timer's due time */
|
||||
if (KiComputeDueTime(Timer, Interval, &Hand))
|
||||
{
|
||||
|
@ -282,6 +304,7 @@ xboxkrnl::BOOLEAN FASTCALL xboxkrnl::KiInsertTreeTimer(
|
|||
Inserted = TRUE;
|
||||
}
|
||||
}
|
||||
TimerMtx.unlock();
|
||||
|
||||
return Inserted;
|
||||
}
|
||||
|
@ -300,6 +323,8 @@ xboxkrnl::BOOLEAN xboxkrnl::KiComputeDueTime(
|
|||
{
|
||||
LARGE_INTEGER InterruptTime, SystemTime, DifferenceTime;
|
||||
|
||||
TimerMtx.lock();
|
||||
|
||||
/* Convert to relative time if needed */
|
||||
Timer->Header.Absolute = FALSE;
|
||||
if (DueTime.u.HighPart >= 0)
|
||||
|
@ -319,6 +344,8 @@ xboxkrnl::BOOLEAN xboxkrnl::KiComputeDueTime(
|
|||
Timer->Header.SignalState = TRUE;
|
||||
Timer->DueTime.QuadPart = 0;
|
||||
*Hand = 0;
|
||||
TimerMtx.unlock();
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -335,6 +362,8 @@ xboxkrnl::BOOLEAN xboxkrnl::KiComputeDueTime(
|
|||
/* Get the handle */
|
||||
*Hand = KiComputeTimerTableIndex(Timer->DueTime.QuadPart);
|
||||
Timer->Header.Inserted = TRUE;
|
||||
TimerMtx.unlock();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -347,6 +376,8 @@ xboxkrnl::BOOLEAN FASTCALL xboxkrnl::KiSignalTimer(
|
|||
ULONG Period = Timer->Period;
|
||||
LARGE_INTEGER Interval, SystemTime;
|
||||
|
||||
TimerMtx.lock();
|
||||
|
||||
/* Set default values */
|
||||
Timer->Header.Inserted = FALSE;
|
||||
Timer->Header.SignalState = TRUE;
|
||||
|
@ -386,6 +417,8 @@ xboxkrnl::BOOLEAN FASTCALL xboxkrnl::KiSignalTimer(
|
|||
RequestInterrupt = TRUE;
|
||||
}
|
||||
|
||||
TimerMtx.unlock();
|
||||
|
||||
/* Return whether we need to request a DPC interrupt or not */
|
||||
return RequestInterrupt;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
// ******************************************************************
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
|
||||
namespace xboxkrnl
|
||||
{
|
||||
typedef struct _KTIMER_TABLE_ENTRY
|
||||
|
@ -43,6 +45,9 @@ namespace xboxkrnl
|
|||
|
||||
const ULONG CLOCK_TIME_INCREMENT = 0x2710;
|
||||
LIST_ENTRY KiWaitInListHead;
|
||||
// Actually, this lock isn't required, but because raising the irql to dpc level doesn't really prevent thread switching at the
|
||||
// moment, we need it for now to prevent concurrent access to the timer table
|
||||
std::recursive_mutex TimerMtx;
|
||||
|
||||
VOID KiInitSystem();
|
||||
|
||||
|
|
Loading…
Reference in New Issue