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=551…
==============================================================================
--- 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++;
}