ReactOS  r75907
clock.c
Go to the documentation of this file.
1 /*
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)
7  */
8 
9 /* INCLUDES ******************************************************************/
10 
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14 
15 /* GLOBALS *******************************************************************/
16 
19 volatile KSYSTEM_TIME KeTickCount = { 0, 0, 0 };
23 
24 /* PRIVATE FUNCTIONS *********************************************************/
25 
26 VOID
27 NTAPI
29  OUT PLARGE_INTEGER OldTime,
30  IN BOOLEAN FixInterruptTime,
31  IN PLARGE_INTEGER HalTime OPTIONAL)
32 {
34  KIRQL OldIrql, OldIrql2;
35  LARGE_INTEGER DeltaTime;
36  PLIST_ENTRY ListHead, NextEntry;
37  PKTIMER Timer;
38  PKSPIN_LOCK_QUEUE LockQueue;
39  LIST_ENTRY TempList, TempList2;
40  ULONG Hand, i;
41 
42  /* Sanity checks */
43  ASSERT((NewTime->HighPart & 0xF0000000) == 0);
45 
46  /* Check if this is for the HAL */
47  if (HalTime) RtlTimeToTimeFields(HalTime, &TimeFields);
48 
49  /* Set affinity to this CPU, lock the dispatcher, and raise IRQL */
51  OldIrql = KiAcquireDispatcherLock();
52  KeRaiseIrql(HIGH_LEVEL, &OldIrql2);
53 
54  /* Query the system time now */
55  KeQuerySystemTime(OldTime);
56 
57  /* Set the new system time (ordering of these operations is critical) */
58  SharedUserData->SystemTime.High2Time = NewTime->HighPart;
59  SharedUserData->SystemTime.LowPart = NewTime->LowPart;
60  SharedUserData->SystemTime.High1Time = NewTime->HighPart;
61 
62  /* Check if this was for the HAL and set the RTC time */
63  if (HalTime) ExCmosClockIsSane = HalSetRealTimeClock(&TimeFields);
64 
65  /* Calculate the difference between the new and the old time */
66  DeltaTime.QuadPart = NewTime->QuadPart - OldTime->QuadPart;
67 
68  /* Update system boot time */
69  KeBootTime.QuadPart += DeltaTime.QuadPart;
71 
72  /* Lower IRQL back */
73  KeLowerIrql(OldIrql2);
74 
75  /* Check if we need to adjust interrupt time */
76  if (FixInterruptTime) ASSERT(FALSE);
77 
78  /* Setup a temporary list of absolute timers */
79  InitializeListHead(&TempList);
80 
81  /* Loop current timers */
82  for (i = 0; i < TIMER_TABLE_SIZE; i++)
83  {
84  /* Loop the entries in this table and lock the timers */
85  ListHead = &KiTimerTableListHead[i].Entry;
86  LockQueue = KiAcquireTimerLock(i);
87  NextEntry = ListHead->Flink;
88  while (NextEntry != ListHead)
89  {
90  /* Get the timer */
91  Timer = CONTAINING_RECORD(NextEntry, KTIMER, TimerListEntry);
92  NextEntry = NextEntry->Flink;
93 
94  /* Is it absolute? */
95  if (Timer->Header.Absolute)
96  {
97  /* Remove it from the timer list */
98  KiRemoveEntryTimer(Timer);
99 
100  /* Insert it into our temporary list */
101  InsertTailList(&TempList, &Timer->TimerListEntry);
102  }
103  }
104 
105  /* Release the lock */
106  KiReleaseTimerLock(LockQueue);
107  }
108 
109  /* Setup a temporary list of expired timers */
110  InitializeListHead(&TempList2);
111 
112  /* Loop absolute timers */
113  while (TempList.Flink != &TempList)
114  {
115  /* Get the timer */
116  Timer = CONTAINING_RECORD(TempList.Flink, KTIMER, TimerListEntry);
118 
119  /* Update the due time and handle */
120  Timer->DueTime.QuadPart -= DeltaTime.QuadPart;
122  Timer->Header.Hand = (UCHAR)Hand;
123 
124  /* Lock the timer and re-insert it */
125  LockQueue = KiAcquireTimerLock(Hand);
126  if (KiInsertTimerTable(Timer, Hand))
127  {
128  /* Remove it from the timer list */
129  KiRemoveEntryTimer(Timer);
130 
131  /* Insert it into our temporary list */
132  InsertTailList(&TempList2, &Timer->TimerListEntry);
133  }
134 
135  /* Release the lock */
136  KiReleaseTimerLock(LockQueue);
137  }
138 
139  /* Process expired timers. This releases the dispatcher lock. */
140  KiTimerListExpire(&TempList2, OldIrql);
141 
142  /* Revert affinity */
144 }
145 
146 /* PUBLIC FUNCTIONS **********************************************************/
147 
148 /*
149  * @implemented
150  */
151 ULONG
152 NTAPI
154 {
155  /* Return the increment */
156  return KeMaximumIncrement;
157 }
158 
159 /*
160  * @implemented
161  */
162 #undef KeQueryTickCount
163 VOID
164 NTAPI
166 {
167  /* Loop until we get a perfect match */
168  for (;;)
169  {
170  /* Read the tick count value */
171  TickCount->HighPart = KeTickCount.High1Time;
172  TickCount->LowPart = KeTickCount.LowPart;
173  if (TickCount->HighPart == KeTickCount.High2Time) break;
174  YieldProcessor();
175  }
176 }
177 
178 #ifndef _M_AMD64
179 /*
180  * @implemented
181  */
182 VOID
183 NTAPI
185 {
186  /* Loop until we get a perfect match */
187  for (;;)
188  {
189  /* Read the time value */
190  CurrentTime->HighPart = SharedUserData->SystemTime.High1Time;
191  CurrentTime->LowPart = SharedUserData->SystemTime.LowPart;
192  if (CurrentTime->HighPart ==
193  SharedUserData->SystemTime.High2Time) break;
194  YieldProcessor();
195  }
196 }
197 
198 /*
199  * @implemented
200  */
201 ULONGLONG
202 NTAPI
204 {
205  LARGE_INTEGER CurrentTime;
206 
207  /* Loop until we get a perfect match */
208  for (;;)
209  {
210  /* Read the time value */
211  CurrentTime.HighPart = SharedUserData->InterruptTime.High1Time;
212  CurrentTime.LowPart = SharedUserData->InterruptTime.LowPart;
213  if (CurrentTime.HighPart ==
214  SharedUserData->InterruptTime.High2Time) break;
215  YieldProcessor();
216  }
217 
218  /* Return the time value */
219  return CurrentTime.QuadPart;
220 }
221 #endif
222 
223 /*
224  * @implemented
225  */
226 VOID
227 NTAPI
229  IN ULONG MinIncrement)
230 {
231  /* Set some Internal Variables */
232  KeMaximumIncrement = MaxIncrement;
233  KeMinimumIncrement = max(MinIncrement, 10000);
234  KeTimeAdjustment = MaxIncrement;
235  KeTimeIncrement = MaxIncrement;
236  KiTickOffset = MaxIncrement;
237 }
238 
239 /* EOF */
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
ULONG KeMaximumIncrement
Definition: clock.c:20
ULONG LowPart
Definition: ketypes.h:895
VOID NTAPI KeSetSystemTime(IN PLARGE_INTEGER NewTime, OUT PLARGE_INTEGER OldTime, IN BOOLEAN FixInterruptTime, IN PLARGE_INTEGER HalTime OPTIONAL)
Definition: clock.c:28
#define IN
Definition: typedefs.h:39
#define max(a, b)
Definition: svc.c:63
#define KeRaiseIrql(irql, oldIrql)
Definition: env_spec_w32.h:597
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
ULONG KeMinimumIncrement
Definition: clock.c:21
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
VOID NTAPI KeRevertToUserAffinityThread(VOID)
Definition: thrdobj.c:1030
FORCEINLINE PKSPIN_LOCK_QUEUE KiAcquireTimerLock(IN ULONG Hand)
Definition: ke_x.h:280
ULONG NTAPI KeQueryTimeIncrement(VOID)
Definition: clock.c:153
ULONGLONG KeBootTimeBias
Definition: clock.c:18
LIST_ENTRY TimerListEntry
Definition: ketypes.h:827
VOID FASTCALL KiTimerListExpire(IN PLIST_ENTRY ExpiredListHead, IN KIRQL OldIrql)
Definition: dpc.c:338
#define InsertTailList(ListHead, Entry)
VOID NTAPI KeSetSystemAffinityThread(IN KAFFINITY Affinity)
Definition: thrdobj.c:1116
volatile KSYSTEM_TIME KeTickCount
Definition: clock.c:19
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
FORCEINLINE VOID YieldProcessor(VOID)
Definition: ke.h:32
UCHAR KIRQL
Definition: env_spec_w32.h:591
GLenum GLclampf GLint i
Definition: glfuncs.h:14
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
LONG KiTickOffset
Definition: time.c:17
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
#define FALSE
Definition: types.h:117
LARGE_INTEGER KeBootTime
Definition: clock.c:17
VOID NTAPI KeQuerySystemTime(OUT PLARGE_INTEGER CurrentTime)
Definition: clock.c:184
DISPATCHER_HEADER Header
Definition: ketypes.h:825
ULONG KeTimeAdjustment
Definition: time.c:18
BOOLEAN ExCmosClockIsSane
Definition: init.c:89
VOID NTAPI KeQueryTickCount(IN PLARGE_INTEGER TickCount)
Definition: clock.c:165
BOOLEAN FASTCALL KiInsertTimerTable(IN PKTIMER Timer, IN ULONG Hand)
Definition: timerobj.c:63
BOOLEAN RtlTimeToTimeFields(IN PLARGE_INTEGER Time, IN PTIME_FIELDS TimeFields)
struct _LIST_ENTRY * Flink
Definition: typedefs.h:120
unsigned char BOOLEAN
#define TIMER_TABLE_SIZE
Definition: ketypes.h:821
LIST_ENTRY Entry
Definition: ketypes.h:666
LONG High1Time
Definition: ketypes.h:896
uint64_t ULONGLONG
Definition: typedefs.h:66
ULARGE_INTEGER DueTime
Definition: ketypes.h:826
KTIMER_TABLE_ENTRY KiTimerTableListHead[TIMER_TABLE_SIZE]
Definition: timerobj.c:17
#define SharedUserData
unsigned char UCHAR
Definition: xmlstorage.h:181
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
VOID NTAPI KeSetTimeIncrement(IN ULONG MaxIncrement, IN ULONG MinIncrement)
Definition: clock.c:228
ULONG LowPart
Definition: typedefs.h:105
Definition: typedefs.h:118
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
LONG High2Time
Definition: ketypes.h:897
#define HIGH_LEVEL
Definition: env_spec_w32.h:703
UINT Timer
Definition: capclock.c:11
FORCEINLINE KIRQL KiAcquireDispatcherLock(VOID)
Definition: ke_x.h:144
ULONG KeTimeIncrement
Definition: clock.c:22
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
FORCEINLINE VOID KiRemoveEntryTimer(IN PKTIMER Timer)
Definition: ke_x.h:884
#define OUT
Definition: typedefs.h:40
unsigned int ULONG
Definition: retypes.h:1
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
static PTIME_FIELDS TimeFields
Definition: time.c:27
ULONGLONG NTAPI KeQueryInterruptTime(VOID)
Definition: clock.c:203
FORCEINLINE ULONG KiComputeTimerTableIndex(IN ULONGLONG DueTime)
Definition: ke_x.h:873
IN HDEVINFO IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
Definition: devinst.c:44
FORCEINLINE VOID KiReleaseTimerLock(IN PKSPIN_LOCK_QUEUE LockQueue)
Definition: ke_x.h:291
BOOLEAN NTAPI HalSetRealTimeClock(IN PTIME_FIELDS Time)
Definition: rtc.c:45
LONGLONG QuadPart
Definition: typedefs.h:113