[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 ******************************************************************/
VOID
FASTCALL
KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame,
IN ULONG Increment,
IN KIRQL Irql)
FORCEINLINE
KiWriteSystemTime(volatile KSYSTEM_TIME *SystemTime, ULARGE_INTEGER NewTime)
{
PKPRCB Prcb = KeGetCurrentPrcb();
ULARGE_INTEGER CurrentTime, InterruptTime;
ULONG Hand, OldTickCount;
#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
}
/* Add the increment time to the shared data */
InterruptTime.HighPart = SharedUserData->InterruptTime.High1Time;
InterruptTime.LowPart = SharedUserData->InterruptTime.LowPart;
InterruptTime.QuadPart += Increment;
SharedUserData->InterruptTime.High1Time = InterruptTime.HighPart;
SharedUserData->InterruptTime.LowPart = InterruptTime.LowPart;
SharedUserData->InterruptTime.High2Time = InterruptTime.HighPart;
/* 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++;
}
VOID
FORCEINLINE
KiCheckForTimerExpiration(
PKPRCB Prcb,
PKTRAP_FRAME TrapFrame,
ULARGE_INTEGER InterruptTime)
{
ULONG Hand;
/* Check for timer expiration */
Hand = OldTickCount & (TIMER_TABLE_SIZE - 1);
Hand = KeTickCount.LowPart & (TIMER_TABLE_SIZE - 1);
if (KiTimerTableListHead[Hand].Time.QuadPart <= InterruptTime.QuadPart)
{
/* Check if we are already doing expiration */
@ -97,19 +57,56 @@ KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame,
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
}
}
}
/* Check if this was a full tick */
if (KiTickOffset <= 0)
VOID
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;
/* Update system runtime */
/* Update processor/thread runtime */
KeUpdateRunTime(TrapFrame, Irql);
}
else
{
/* Increase interrupt count and exit */
/* Increase interrupt count only */
Prcb->InterruptCount++;
}