Author: tkreuzer Date: Wed Jan 25 16:56:06 2012 New Revision: 55174
URL: http://svn.reactos.org/svn/reactos?rev=55174&view=rev Log: [NTOSKRNL] Refactor KeUpdateSystemTime, improving readability, fixing a concurrency issue and fixing the code for 64 bit.
Modified: trunk/reactos/ntoskrnl/ke/time.c
Modified: trunk/reactos/ntoskrnl/ke/time.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/time.c?rev=5517... ============================================================================== --- trunk/reactos/ntoskrnl/ke/time.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/ke/time.c [iso-8859-1] Wed Jan 25 16:56:06 2012 @@ -21,6 +21,45 @@ /* 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 FASTCALL KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame, IN ULONG Increment, @@ -28,88 +67,46 @@ { PKPRCB Prcb = KeGetCurrentPrcb(); ULARGE_INTEGER CurrentTime, InterruptTime; - ULONG Hand, OldTickCount; + LONG OldTickOffset;
/* Add the increment time to the shared data */ - InterruptTime.HighPart = SharedUserData->InterruptTime.High1Time; - InterruptTime.LowPart = SharedUserData->InterruptTime.LowPart; + InterruptTime.QuadPart = *(ULONGLONG*)&SharedUserData->InterruptTime; 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) + 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 system time */ - CurrentTime.HighPart = SharedUserData->SystemTime.High1Time; - CurrentTime.LowPart = SharedUserData->SystemTime.LowPart; + CurrentTime.QuadPart = *(ULONGLONG*)&SharedUserData->SystemTime; CurrentTime.QuadPart += KeTimeAdjustment; - SharedUserData->SystemTime.High2Time = CurrentTime.HighPart; - SharedUserData->SystemTime.LowPart = CurrentTime.LowPart; - SharedUserData->SystemTime.High1Time = CurrentTime.HighPart; + KiWriteSystemTime(&SharedUserData->SystemTime, CurrentTime);
/* 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; + CurrentTime.QuadPart = (*(ULONGLONG*)&KeTickCount) + 1; + KiWriteSystemTime(&KeTickCount, CurrentTime);
/* 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); - } - } + KiWriteSystemTime(&SharedUserData->TickCount, CurrentTime);
/* Check for expiration with the new tick count as well */ - OldTickCount++; - } - - /* 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 if this was a full tick */ - if (KiTickOffset <= 0) - { - /* Update the tick offset */ + 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++; }