ReactOS  0.4.14-dev-606-g14ebc0b
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 */
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 */
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 */
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);
117  RemoveEntryList(&Timer->TimerListEntry);
118 
119  /* Update the due time and handle */
120  Timer->DueTime.QuadPart -= DeltaTime.QuadPart;
121  Hand = KiComputeTimerTableIndex(Timer->DueTime.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 */
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:910
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:38
#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
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
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
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
LONG KiTickOffset
Definition: time.c:17
LARGE_INTEGER KeBootTime
Definition: clock.c:17
VOID NTAPI KeQuerySystemTime(OUT PLARGE_INTEGER CurrentTime)
Definition: clock.c:184
unsigned char BOOLEAN
ULONG KeTimeAdjustment
Definition: time.c:18
BOOLEAN ExCmosClockIsSane
Definition: init.c:89
VOID NTAPI KeQueryTickCount(IN PLARGE_INTEGER TickCount)
Definition: clock.c:165
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
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:119
#define TIMER_TABLE_SIZE
Definition: ketypes.h:836
LIST_ENTRY Entry
Definition: ketypes.h:666
LONG High1Time
Definition: ketypes.h:911
uint64_t ULONGLONG
Definition: typedefs.h:65
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
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:104
Definition: typedefs.h:117
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
LONG High2Time
Definition: ketypes.h:912
#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:39
unsigned int ULONG
Definition: retypes.h:1
static PTIME_FIELDS TimeFields
Definition: time.c:104
ULONGLONG NTAPI KeQueryInterruptTime(VOID)
Definition: clock.c:203
FORCEINLINE ULONG KiComputeTimerTableIndex(IN ULONGLONG DueTime)
Definition: ke_x.h:873
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:112
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68