Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240/* * PROJECT: ReactOS Kernel * LICENSE: GPL - See COPYING in the top level directory * FILE: ntoskrnl/ke/clock.c * PURPOSE: System Clock Support * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) */
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>#define NDEBUG#include <debug.h>
/* GLOBALS *******************************************************************/
LARGE_INTEGER KeBootTime;ULONGLONG KeBootTimeBias;volatile KSYSTEM_TIME KeTickCount = { 0, 0, 0 };ULONG KeMaximumIncrement;ULONG KeMinimumIncrement;ULONG KeTimeIncrement;
/* PRIVATE FUNCTIONS *********************************************************/
VOIDNTAPIKeSetSystemTime(IN PLARGE_INTEGER NewTime, OUT PLARGE_INTEGER OldTime, IN BOOLEAN FixInterruptTime, IN PLARGE_INTEGER HalTime OPTIONAL){ TIME_FIELDS TimeFields; KIRQL OldIrql, OldIrql2; LARGE_INTEGER DeltaTime; PLIST_ENTRY ListHead, NextEntry; PKTIMER Timer; PKSPIN_LOCK_QUEUE LockQueue; LIST_ENTRY TempList, TempList2; ULONG Hand, i;
/* Sanity checks */ ASSERT((NewTime->HighPart & 0xF0000000) == 0); ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
/* Check if this is for the HAL */ if (HalTime) RtlTimeToTimeFields(HalTime, &TimeFields);
/* Set affinity to this CPU, lock the dispatcher, and raise IRQL */ KeSetSystemAffinityThread(1); OldIrql = KiAcquireDispatcherLock(); KeRaiseIrql(HIGH_LEVEL, &OldIrql2);
/* Query the system time now */ KeQuerySystemTime(OldTime);
/* Set the new system time (ordering of these operations is critical) */ SharedUserData->SystemTime.High2Time = NewTime->HighPart; SharedUserData->SystemTime.LowPart = NewTime->LowPart; SharedUserData->SystemTime.High1Time = NewTime->HighPart;
/* Check if this was for the HAL and set the RTC time */ if (HalTime) ExCmosClockIsSane = HalSetRealTimeClock(&TimeFields);
/* Calculate the difference between the new and the old time */ DeltaTime.QuadPart = NewTime->QuadPart - OldTime->QuadPart;
/* Update system boot time */ KeBootTime.QuadPart += DeltaTime.QuadPart; KeBootTimeBias = KeBootTimeBias + DeltaTime.QuadPart;
/* Lower IRQL back */ KeLowerIrql(OldIrql2);
/* Check if we need to adjust interrupt time */ if (FixInterruptTime) ASSERT(FALSE);
/* Setup a temporary list of absolute timers */ InitializeListHead(&TempList);
/* Loop current timers */ for (i = 0; i < TIMER_TABLE_SIZE; i++) { /* Loop the entries in this table and lock the timers */ ListHead = &KiTimerTableListHead[i].Entry; LockQueue = KiAcquireTimerLock(i); NextEntry = ListHead->Flink; while (NextEntry != ListHead) { /* Get the timer */ Timer = CONTAINING_RECORD(NextEntry, KTIMER, TimerListEntry); NextEntry = NextEntry->Flink;
/* Is it absolute? */ if (Timer->Header.Absolute) { /* Remove it from the timer list */ KiRemoveEntryTimer(Timer);
/* Insert it into our temporary list */ InsertTailList(&TempList, &Timer->TimerListEntry); } }
/* Release the lock */ KiReleaseTimerLock(LockQueue); }
/* Setup a temporary list of expired timers */ InitializeListHead(&TempList2);
/* Loop absolute timers */ while (TempList.Flink != &TempList) { /* Get the timer */ Timer = CONTAINING_RECORD(TempList.Flink, KTIMER, TimerListEntry); RemoveEntryList(&Timer->TimerListEntry);
/* Update the due time and handle */ Timer->DueTime.QuadPart -= DeltaTime.QuadPart; Hand = KiComputeTimerTableIndex(Timer->DueTime.QuadPart); Timer->Header.Hand = (UCHAR)Hand;
/* Lock the timer and re-insert it */ LockQueue = KiAcquireTimerLock(Hand); if (KiInsertTimerTable(Timer, Hand)) { /* Remove it from the timer list */ KiRemoveEntryTimer(Timer);
/* Insert it into our temporary list */ InsertTailList(&TempList2, &Timer->TimerListEntry); }
/* Release the lock */ KiReleaseTimerLock(LockQueue); }
/* Process expired timers. This releases the dispatcher lock. */ KiTimerListExpire(&TempList2, OldIrql);
/* Revert affinity */ KeRevertToUserAffinityThread();}
/* PUBLIC FUNCTIONS **********************************************************/
/* * @implemented */ULONGNTAPIKeQueryTimeIncrement(VOID){ /* Return the increment */ return KeMaximumIncrement;}
/* * @implemented */#undef KeQueryTickCountVOIDNTAPIKeQueryTickCount(IN PLARGE_INTEGER TickCount){ /* Loop until we get a perfect match */ for (;;) { /* Read the tick count value */ TickCount->HighPart = KeTickCount.High1Time; TickCount->LowPart = KeTickCount.LowPart; if (TickCount->HighPart == KeTickCount.High2Time) break; YieldProcessor(); }}
#ifndef _M_AMD64/* * @implemented */VOIDNTAPIKeQuerySystemTime(OUT PLARGE_INTEGER CurrentTime){ /* Loop until we get a perfect match */ for (;;) { /* Read the time value */ CurrentTime->HighPart = SharedUserData->SystemTime.High1Time; CurrentTime->LowPart = SharedUserData->SystemTime.LowPart; if (CurrentTime->HighPart == SharedUserData->SystemTime.High2Time) break; YieldProcessor(); }}
/* * @implemented */ULONGLONGNTAPIKeQueryInterruptTime(VOID){ LARGE_INTEGER CurrentTime;
/* Loop until we get a perfect match */ for (;;) { /* Read the time value */ CurrentTime.HighPart = SharedUserData->InterruptTime.High1Time; CurrentTime.LowPart = SharedUserData->InterruptTime.LowPart; if (CurrentTime.HighPart == SharedUserData->InterruptTime.High2Time) break; YieldProcessor(); }
/* Return the time value */ return CurrentTime.QuadPart;}#endif
/* * @implemented */VOIDNTAPIKeSetTimeIncrement(IN ULONG MaxIncrement, IN ULONG MinIncrement){ /* Set some Internal Variables */ KeMaximumIncrement = MaxIncrement; KeMinimumIncrement = max(MinIncrement, 10000); KeTimeAdjustment = MaxIncrement; KeTimeIncrement = MaxIncrement; KiTickOffset = MaxIncrement;}
/* EOF */