[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

@ -21,71 +21,31 @@ BOOLEAN KiTimeAdjustmentEnabled = FALSE;
/* FUNCTIONS ******************************************************************/ /* FUNCTIONS ******************************************************************/
VOID VOID
FASTCALL FORCEINLINE
KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame, KiWriteSystemTime(volatile KSYSTEM_TIME *SystemTime, ULARGE_INTEGER NewTime)
IN ULONG Increment,
IN KIRQL Irql)
{ {
PKPRCB Prcb = KeGetCurrentPrcb(); #ifdef _WIN64
ULARGE_INTEGER CurrentTime, InterruptTime; /* Do a single atomic write */
ULONG Hand, OldTickCount; *(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
}
/* Add the increment time to the shared data */ VOID
InterruptTime.HighPart = SharedUserData->InterruptTime.High1Time; FORCEINLINE
InterruptTime.LowPart = SharedUserData->InterruptTime.LowPart; KiCheckForTimerExpiration(
InterruptTime.QuadPart += Increment; PKPRCB Prcb,
SharedUserData->InterruptTime.High1Time = InterruptTime.HighPart; PKTRAP_FRAME TrapFrame,
SharedUserData->InterruptTime.LowPart = InterruptTime.LowPart; ULARGE_INTEGER InterruptTime)
SharedUserData->InterruptTime.High2Time = InterruptTime.HighPart; {
ULONG Hand;
/* Update tick count */
InterlockedExchangeAdd(&KiTickOffset, -(LONG)Increment);
/* Check for incomplete tick */
OldTickCount = KeTickCount.LowPart;
if (KiTickOffset <= 0)
{
/* Update the system time */
CurrentTime.HighPart = SharedUserData->SystemTime.High1Time;
CurrentTime.LowPart = SharedUserData->SystemTime.LowPart;
CurrentTime.QuadPart += KeTimeAdjustment;
SharedUserData->SystemTime.High2Time = CurrentTime.HighPart;
SharedUserData->SystemTime.LowPart = CurrentTime.LowPart;
SharedUserData->SystemTime.High1Time = CurrentTime.HighPart;
/* Update the tick count */
CurrentTime.HighPart = KeTickCount.High1Time;
CurrentTime.LowPart = OldTickCount;
CurrentTime.QuadPart += 1;
KeTickCount.High2Time = CurrentTime.HighPart;
KeTickCount.LowPart = CurrentTime.LowPart;
KeTickCount.High1Time = CurrentTime.HighPart;
/* Update it in the shared user data */
SharedUserData->TickCount.High2Time = CurrentTime.HighPart;
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 */
OldTickCount++;
}
/* Check for timer expiration */ /* Check for timer expiration */
Hand = OldTickCount & (TIMER_TABLE_SIZE - 1); Hand = KeTickCount.LowPart & (TIMER_TABLE_SIZE - 1);
if (KiTimerTableListHead[Hand].Time.QuadPart <= InterruptTime.QuadPart) if (KiTimerTableListHead[Hand].Time.QuadPart <= InterruptTime.QuadPart)
{ {
/* Check if we are already doing expiration */ /* Check if we are already doing expiration */
@ -97,19 +57,56 @@ KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame,
HalRequestSoftwareInterrupt(DISPATCH_LEVEL); HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
} }
} }
}
/* Check if this was a full tick */ VOID
if (KiTickOffset <= 0) FASTCALL
KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame,
IN ULONG Increment,
IN KIRQL Irql)
{
PKPRCB Prcb = KeGetCurrentPrcb();
ULARGE_INTEGER CurrentTime, InterruptTime;
LONG OldTickOffset;
/* Add the increment time to the shared data */
InterruptTime.QuadPart = *(ULONGLONG*)&SharedUserData->InterruptTime;
InterruptTime.QuadPart += Increment;
KiWriteSystemTime(&SharedUserData->InterruptTime, InterruptTime);
/* Check for timer expiration */
KiCheckForTimerExpiration(Prcb, TrapFrame, InterruptTime);
/* Update the tick offset */
OldTickOffset = InterlockedExchangeAdd(&KiTickOffset, -(LONG)Increment);
/* Check for full tick */
if (OldTickOffset <= (LONG)Increment)
{ {
/* Update the tick offset */ /* Update the system time */
CurrentTime.QuadPart = *(ULONGLONG*)&SharedUserData->SystemTime;
CurrentTime.QuadPart += KeTimeAdjustment;
KiWriteSystemTime(&SharedUserData->SystemTime, CurrentTime);
/* Update the tick count */
CurrentTime.QuadPart = (*(ULONGLONG*)&KeTickCount) + 1;
KiWriteSystemTime(&KeTickCount, CurrentTime);
/* Update it in the shared user data */
KiWriteSystemTime(&SharedUserData->TickCount, CurrentTime);
/* Check for expiration with the new tick count as well */
KiCheckForTimerExpiration(Prcb, TrapFrame, InterruptTime);
/* Reset 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++;
} }