[NTOSKRNL]

Refactor KeUpdateSystemTime, improving readability, fixing a concurrency issue and fixing the code for 64 bit.

svn path=/trunk/; revision=55174
This commit is contained in:
Timo Kreuzer 2012-01-25 16:56:06 +00:00
parent c707066acb
commit 3468e87b38

View file

@ -20,6 +20,45 @@ BOOLEAN KiTimeAdjustmentEnabled = FALSE;
/* FUNCTIONS ******************************************************************/ /* FUNCTIONS ******************************************************************/
VOID
FORCEINLINE
KiWriteSystemTime(volatile KSYSTEM_TIME *SystemTime, ULARGE_INTEGER NewTime)
{
#ifdef _WIN64
/* Do a single atomic write */
*(ULONGLONG*)SystemTime = NewTime.QuadPart;
#else
/* Update in 3 steps, so that a reader can recognize partial updates */
SystemTime->High1Time = NewTime.HighPart;
SystemTime->LowPart = NewTime.LowPart;
SystemTime->High2Time = NewTime.HighPart;
#endif
}
VOID
FORCEINLINE
KiCheckForTimerExpiration(
PKPRCB Prcb,
PKTRAP_FRAME TrapFrame,
ULARGE_INTEGER InterruptTime)
{
ULONG Hand;
/* Check for timer expiration */
Hand = KeTickCount.LowPart & (TIMER_TABLE_SIZE - 1);
if (KiTimerTableListHead[Hand].Time.QuadPart <= InterruptTime.QuadPart)
{
/* Check if we are already doing expiration */
if (!Prcb->TimerRequest)
{
/* Request a DPC to handle this */
Prcb->TimerRequest = (ULONG_PTR)TrapFrame;
Prcb->TimerHand = Hand;
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
}
}
}
VOID VOID
FASTCALL FASTCALL
KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame, KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame,
@ -28,88 +67,46 @@ KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame,
{ {
PKPRCB Prcb = KeGetCurrentPrcb(); PKPRCB Prcb = KeGetCurrentPrcb();
ULARGE_INTEGER CurrentTime, InterruptTime; ULARGE_INTEGER CurrentTime, InterruptTime;
ULONG Hand, OldTickCount; LONG OldTickOffset;
/* Add the increment time to the shared data */ /* Add the increment time to the shared data */
InterruptTime.HighPart = SharedUserData->InterruptTime.High1Time; InterruptTime.QuadPart = *(ULONGLONG*)&SharedUserData->InterruptTime;
InterruptTime.LowPart = SharedUserData->InterruptTime.LowPart;
InterruptTime.QuadPart += Increment; InterruptTime.QuadPart += Increment;
SharedUserData->InterruptTime.High1Time = InterruptTime.HighPart; KiWriteSystemTime(&SharedUserData->InterruptTime, InterruptTime);
SharedUserData->InterruptTime.LowPart = InterruptTime.LowPart;
SharedUserData->InterruptTime.High2Time = InterruptTime.HighPart;
/* Update tick count */ /* Check for timer expiration */
InterlockedExchangeAdd(&KiTickOffset, -(LONG)Increment); KiCheckForTimerExpiration(Prcb, TrapFrame, InterruptTime);
/* Check for incomplete tick */ /* Update the tick offset */
OldTickCount = KeTickCount.LowPart; OldTickOffset = InterlockedExchangeAdd(&KiTickOffset, -(LONG)Increment);
if (KiTickOffset <= 0)
/* Check for full tick */
if (OldTickOffset <= (LONG)Increment)
{ {
/* Update the system time */ /* Update the system time */
CurrentTime.HighPart = SharedUserData->SystemTime.High1Time; CurrentTime.QuadPart = *(ULONGLONG*)&SharedUserData->SystemTime;
CurrentTime.LowPart = SharedUserData->SystemTime.LowPart;
CurrentTime.QuadPart += KeTimeAdjustment; CurrentTime.QuadPart += KeTimeAdjustment;
SharedUserData->SystemTime.High2Time = CurrentTime.HighPart; KiWriteSystemTime(&SharedUserData->SystemTime, CurrentTime);
SharedUserData->SystemTime.LowPart = CurrentTime.LowPart;
SharedUserData->SystemTime.High1Time = CurrentTime.HighPart;
/* Update the tick count */ /* Update the tick count */
CurrentTime.HighPart = KeTickCount.High1Time; CurrentTime.QuadPart = (*(ULONGLONG*)&KeTickCount) + 1;
CurrentTime.LowPart = OldTickCount; KiWriteSystemTime(&KeTickCount, CurrentTime);
CurrentTime.QuadPart += 1;
KeTickCount.High2Time = CurrentTime.HighPart;
KeTickCount.LowPart = CurrentTime.LowPart;
KeTickCount.High1Time = CurrentTime.HighPart;
/* Update it in the shared user data */ /* Update it in the shared user data */
SharedUserData->TickCount.High2Time = CurrentTime.HighPart; KiWriteSystemTime(&SharedUserData->TickCount, CurrentTime);
SharedUserData->TickCount.LowPart = CurrentTime.LowPart;
SharedUserData->TickCount.High1Time = CurrentTime.HighPart;
/* Check for timer expiration */
Hand = OldTickCount & (TIMER_TABLE_SIZE - 1);
if (KiTimerTableListHead[Hand].Time.QuadPart <= InterruptTime.QuadPart)
{
/* Check if we are already doing expiration */
if (!Prcb->TimerRequest)
{
/* Request a DPC to handle this */
Prcb->TimerRequest = (ULONG_PTR)TrapFrame;
Prcb->TimerHand = Hand;
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
}
}
/* Check for expiration with the new tick count as well */ /* Check for expiration with the new tick count as well */
OldTickCount++; KiCheckForTimerExpiration(Prcb, TrapFrame, InterruptTime);
}
/* Check for timer expiration */ /* Reset the tick offset */
Hand = OldTickCount & (TIMER_TABLE_SIZE - 1);
if (KiTimerTableListHead[Hand].Time.QuadPart <= InterruptTime.QuadPart)
{
/* Check if we are already doing expiration */
if (!Prcb->TimerRequest)
{
/* Request a DPC to handle this */
Prcb->TimerRequest = (ULONG_PTR)TrapFrame;
Prcb->TimerHand = Hand;
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
}
}
/* Check if this was a full tick */
if (KiTickOffset <= 0)
{
/* Update the tick offset */
KiTickOffset += KeMaximumIncrement; KiTickOffset += KeMaximumIncrement;
/* Update system runtime */ /* Update processor/thread runtime */
KeUpdateRunTime(TrapFrame, Irql); KeUpdateRunTime(TrapFrame, Irql);
} }
else else
{ {
/* Increase interrupt count and exit */ /* Increase interrupt count only */
Prcb->InterruptCount++; Prcb->InterruptCount++;
} }