* Sync up to trunk r55544.
[reactos.git] / ntoskrnl / ke / time.c
index 49ca79d..1f83b26 100644 (file)
@@ -20,6 +20,45 @@ BOOLEAN KiTimeAdjustmentEnabled = FALSE;
 
 /* 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,
@@ -28,88 +67,46 @@ KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame,
 {
     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;
+    KiWriteSystemTime(&SharedUserData->InterruptTime, InterruptTime);
 
-    /* Update tick count */
-    InterlockedExchangeAdd(&KiTickOffset, -(LONG)Increment);
+    /* Check for timer expiration */
+    KiCheckForTimerExpiration(Prcb, TrapFrame, InterruptTime);
+
+    /* Update the tick offset */
+    OldTickOffset = InterlockedExchangeAdd(&KiTickOffset, -(LONG)Increment);
 
-    /* Check for incomplete tick */
-    OldTickCount = KeTickCount.LowPart;
-    if (KiTickOffset <= 0)
+    /* 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);
-        }
-    }
+        KiCheckForTimerExpiration(Prcb, TrapFrame, InterruptTime);
 
-    /* Check if this was a full tick */
-    if (KiTickOffset <= 0)
-    {
-        /* Update the tick offset */
+        /* 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++;
     }