2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ke/clock.c
5 * PURPOSE: System Clock Support
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
15 /* GLOBALS *******************************************************************/
17 LARGE_INTEGER KeBootTime
;
18 ULONGLONG KeBootTimeBias
;
19 volatile KSYSTEM_TIME KeTickCount
= {0};
20 volatile ULONG KiRawTicks
= 0;
21 ULONG KeMaximumIncrement
;
22 ULONG KeMinimumIncrement
;
23 ULONG KeTimeAdjustment
;
24 ULONG KeTimeIncrement
;
25 LONG KiTickOffset
= 0;
27 /* PRIVATE FUNCTIONS *********************************************************/
31 KeSetSystemTime(IN PLARGE_INTEGER NewTime
,
32 OUT PLARGE_INTEGER OldTime
,
33 IN BOOLEAN FixInterruptTime
,
34 IN PLARGE_INTEGER HalTime OPTIONAL
)
36 TIME_FIELDS TimeFields
;
37 KIRQL OldIrql
, OldIrql2
;
38 LARGE_INTEGER DeltaTime
;
39 PLIST_ENTRY ListHead
, NextEntry
;
41 PKSPIN_LOCK_QUEUE LockQueue
;
42 LIST_ENTRY TempList
, TempList2
;
44 PKTIMER_TABLE_ENTRY TimerEntry
;
47 ASSERT((NewTime
->HighPart
& 0xF0000000) == 0);
48 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
50 /* Check if this is for the HAL */
51 if (HalTime
) RtlTimeToTimeFields(HalTime
, &TimeFields
);
53 /* Set affinity to this CPU, lock the dispatcher, and raise IRQL */
54 KeSetSystemAffinityThread(1);
55 OldIrql
= KiAcquireDispatcherLock();
56 KeRaiseIrql(HIGH_LEVEL
, &OldIrql2
);
58 /* Query the system time now */
59 KeQuerySystemTime(OldTime
);
61 /* Set the new system time */
62 SharedUserData
->SystemTime
.LowPart
= NewTime
->LowPart
;
63 SharedUserData
->SystemTime
.High1Time
= NewTime
->HighPart
;
64 SharedUserData
->SystemTime
.High2Time
= NewTime
->HighPart
;
66 /* Check if this was for the HAL and set the RTC time */
67 if (HalTime
) ExCmosClockIsSane
= HalSetRealTimeClock(&TimeFields
);
69 /* Calculate the difference between the new and the old time */
70 DeltaTime
.QuadPart
= NewTime
->QuadPart
- OldTime
->QuadPart
;
72 /* Update system boot time */
73 KeBootTime
.QuadPart
+= DeltaTime
.QuadPart
;
74 KeBootTimeBias
= KeBootTimeBias
+ DeltaTime
.QuadPart
;
77 KeLowerIrql(OldIrql2
);
79 /* Check if we need to adjust interrupt time */
80 if (FixInterruptTime
) KEBUGCHECK(0);
82 /* Setup a temporary list of absolute timers */
83 InitializeListHead(&TempList
);
85 /* Loop current timers */
86 for (i
= 0; i
< TIMER_TABLE_SIZE
; i
++)
88 /* Loop the entries in this table and lock the timers */
89 ListHead
= &KiTimerTableListHead
[i
].Entry
;
90 LockQueue
= KiAcquireTimerLock(i
);
91 NextEntry
= ListHead
->Flink
;
92 while (NextEntry
!= ListHead
)
95 Timer
= CONTAINING_RECORD(NextEntry
, KTIMER
, TimerListEntry
);
96 NextEntry
= NextEntry
->Flink
;
99 if (Timer
->Header
.Absolute
)
101 /* Remove it from the timer list */
102 if (RemoveEntryList(&Timer
->TimerListEntry
))
104 /* Get the entry and check if it's empty */
105 TimerEntry
= &KiTimerTableListHead
[Timer
->Header
.Hand
];
106 if (IsListEmpty(&TimerEntry
->Entry
))
108 /* Clear the time then */
109 TimerEntry
->Time
.HighPart
= 0xFFFFFFFF;
113 /* Insert it into our temporary list */
114 DPRINT1("Adding a timer!\n");
115 InsertTailList(&TempList
, &Timer
->TimerListEntry
);
119 /* Release the lock */
120 KiReleaseTimerLock(LockQueue
);
123 /* Setup a temporary list of expired timers */
124 InitializeListHead(&TempList2
);
126 /* Loop absolute timers */
127 while (TempList
.Flink
!= &TempList
)
130 Timer
= CONTAINING_RECORD(TempList
.Flink
, KTIMER
, TimerListEntry
);
131 RemoveEntryList(&Timer
->TimerListEntry
);
133 /* Update the due time and handle */
134 Timer
->DueTime
.QuadPart
-= DeltaTime
.QuadPart
;
135 Hand
= KiComputeTimerTableIndex(Timer
->DueTime
.QuadPart
);
136 Timer
->Header
.Hand
= (UCHAR
)Hand
;
138 /* Lock the timer and re-insert it */
139 LockQueue
= KiAcquireTimerLock(Hand
);
140 if (KiInsertTimerTable(Timer
, Hand
))
142 /* Remove it from the timer list */
143 if (RemoveEntryList(&Timer
->TimerListEntry
))
145 /* Get the entry and check if it's empty */
146 TimerEntry
= &KiTimerTableListHead
[Timer
->Header
.Hand
];
147 if (IsListEmpty(&TimerEntry
->Entry
))
149 /* Clear the time then */
150 TimerEntry
->Time
.HighPart
= 0xFFFFFFFF;
154 /* Insert it into our temporary list */
155 DPRINT1("Adding a timer 2!\n");
156 InsertTailList(&TempList2
, &Timer
->TimerListEntry
);
159 /* Release the lock */
160 KiReleaseTimerLock(LockQueue
);
163 /* FIXME: Process expired timers! */
164 KiReleaseDispatcherLock(OldIrql
);
166 /* Revert affinity */
167 KeRevertToUserAffinityThread();
170 /* PUBLIC FUNCTIONS **********************************************************/
177 KeQueryTimeIncrement(VOID
)
179 /* Return the increment */
180 return KeMaximumIncrement
;
186 #undef KeQueryTickCount
189 KeQueryTickCount(IN PLARGE_INTEGER TickCount
)
191 /* Loop until we get a perfect match */
194 /* Read the tick count value */
195 TickCount
->HighPart
= KeTickCount
.High1Time
;
196 TickCount
->LowPart
= KeTickCount
.LowPart
;
197 if (TickCount
->HighPart
== KeTickCount
.High2Time
) break;
207 KeQuerySystemTime(OUT PLARGE_INTEGER CurrentTime
)
209 /* Loop until we get a perfect match */
212 /* Read the time value */
213 CurrentTime
->HighPart
= SharedUserData
->SystemTime
.High1Time
;
214 CurrentTime
->LowPart
= SharedUserData
->SystemTime
.LowPart
;
215 if (CurrentTime
->HighPart
==
216 SharedUserData
->SystemTime
.High2Time
) break;
226 KeQueryInterruptTime(VOID
)
228 LARGE_INTEGER CurrentTime
;
230 /* Loop until we get a perfect match */
233 /* Read the time value */
234 CurrentTime
.HighPart
= SharedUserData
->InterruptTime
.High1Time
;
235 CurrentTime
.LowPart
= SharedUserData
->InterruptTime
.LowPart
;
236 if (CurrentTime
.HighPart
==
237 SharedUserData
->InterruptTime
.High2Time
) break;
241 /* Return the time value */
242 return CurrentTime
.QuadPart
;
250 KeSetTimeIncrement(IN ULONG MaxIncrement
,
251 IN ULONG MinIncrement
)
253 /* Set some Internal Variables */
254 KeMaximumIncrement
= MaxIncrement
;
255 KeMinimumIncrement
= max(MinIncrement
, 10000);
256 KeTimeAdjustment
= MaxIncrement
;
257 KeTimeIncrement
= MaxIncrement
;
258 KiTickOffset
= MaxIncrement
;
263 NtQueryTimerResolution(OUT PULONG MinimumResolution
,
264 OUT PULONG MaximumResolution
,
265 OUT PULONG ActualResolution
)
268 return STATUS_NOT_IMPLEMENTED
;
273 NtSetTimerResolution(IN ULONG DesiredResolution
,
274 IN BOOLEAN SetResolution
,
275 OUT PULONG CurrentResolution
)
278 return STATUS_NOT_IMPLEMENTED
;