mirror of
https://github.com/reactos/reactos.git
synced 2025-07-23 12:54:02 +00:00
[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:
parent
c707066acb
commit
3468e87b38
1 changed files with 63 additions and 66 deletions
|
@ -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++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue