ReactOS 0.4.15-dev-7961-gdcf9eb0
time.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: ntoskrnl/ke/time.c
5 * PURPOSE: Implements timebase functionality
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9/* INCLUDES *******************************************************************/
10
11#include <ntoskrnl.h>
12#define NDEBUG
13#include <debug.h>
14
15/* GLOBALS ********************************************************************/
16
20
21/* FUNCTIONS ******************************************************************/
22
24VOID
25KiWriteSystemTime(volatile KSYSTEM_TIME *SystemTime, ULARGE_INTEGER NewTime)
26{
27#ifdef _WIN64
28 /* Do a single atomic write */
29 *(ULONGLONG*)SystemTime = NewTime.QuadPart;
30#else
31 /* Update in 3 steps, so that a reader can recognize partial updates */
32 SystemTime->High1Time = NewTime.HighPart;
33 SystemTime->LowPart = NewTime.LowPart;
34#endif
35 SystemTime->High2Time = NewTime.HighPart;
36}
37
39VOID
41 PKPRCB Prcb,
42 PKTRAP_FRAME TrapFrame,
43 ULARGE_INTEGER InterruptTime)
44{
45 ULONG Hand;
46
47 /* Check for timer expiration */
49 if (KiTimerTableListHead[Hand].Time.QuadPart <= InterruptTime.QuadPart)
50 {
51 /* Check if we are already doing expiration */
52 if (!Prcb->TimerRequest)
53 {
54 /* Request a DPC to handle this */
55 Prcb->TimerRequest = (ULONG_PTR)TrapFrame;
56 Prcb->TimerHand = Hand;
58 }
59 }
60}
61
62VOID
67{
68 PKPRCB Prcb = KeGetCurrentPrcb();
69 ULARGE_INTEGER CurrentTime, InterruptTime;
70 LONG OldTickOffset;
71
72 /* Check if this tick is being skipped */
73 if (Prcb->SkipTick)
74 {
75 /* Handle it next time */
76 Prcb->SkipTick = FALSE;
77
78 /* Increase interrupt count and end the interrupt */
79 Prcb->InterruptCount++;
80 KiEndInterrupt(Irql, TrapFrame);
81
82 /* Note: non-x86 return back to the caller! */
83 return;
84 }
85
86 /* Add the increment time to the shared data */
87 InterruptTime.QuadPart = *(ULONGLONG*)&SharedUserData->InterruptTime;
88 InterruptTime.QuadPart += Increment;
89 KiWriteSystemTime(&SharedUserData->InterruptTime, InterruptTime);
90
91 /* Check for timer expiration */
92 KiCheckForTimerExpiration(Prcb, TrapFrame, InterruptTime);
93
94 /* Update the tick offset */
96
97 /* If the debugger is enabled, check for break-in request */
99 {
100 /* Break-in requested! */
102 }
103
104 /* Check for full tick */
105 if (OldTickOffset <= (LONG)Increment)
106 {
107 /* Update the system time */
108 CurrentTime.QuadPart = *(ULONGLONG*)&SharedUserData->SystemTime;
109 CurrentTime.QuadPart += KeTimeAdjustment;
110 KiWriteSystemTime(&SharedUserData->SystemTime, CurrentTime);
111
112 /* Update the tick count */
113 CurrentTime.QuadPart = (*(ULONGLONG*)&KeTickCount) + 1;
114 KiWriteSystemTime(&KeTickCount, CurrentTime);
115
116 /* Update it in the shared user data */
117 KiWriteSystemTime(&SharedUserData->TickCount, CurrentTime);
118
119 /* Check for expiration with the new tick count as well */
120 KiCheckForTimerExpiration(Prcb, TrapFrame, InterruptTime);
121
122 /* Reset the tick offset */
124
125 /* Update processor/thread runtime */
126 KeUpdateRunTime(TrapFrame, Irql);
127 }
128 else
129 {
130 /* Increase interrupt count only */
131 Prcb->InterruptCount++;
132 }
133
134 /* Disable interrupts and end the interrupt */
135 KiEndInterrupt(Irql, TrapFrame);
136}
137
138VOID
139NTAPI
141 IN KIRQL Irql)
142{
144 PKPRCB Prcb = KeGetCurrentPrcb();
145
146 /* Check if this tick is being skipped */
147 if (Prcb->SkipTick)
148 {
149 /* Handle it next time */
150 Prcb->SkipTick = FALSE;
151 return;
152 }
153
154 /* Increase interrupt count */
155 Prcb->InterruptCount++;
156
157 /* Check if we came from user mode */
158#ifndef _M_ARM
159 if (KiUserTrap(TrapFrame) || (TrapFrame->EFlags & EFLAGS_V86_MASK))
160#else
161 if (TrapFrame->PreviousMode == UserMode)
162#endif
163 {
164 /* Increase thread user time */
165 Prcb->UserTime++;
166 Thread->UserTime++;
167 }
168 else
169 {
170 /* See if we were in an ISR */
171 Prcb->KernelTime++;
172 if (Irql > DISPATCH_LEVEL)
173 {
174 /* Handle that */
175 Prcb->InterruptTime++;
176 }
177 else if ((Irql < DISPATCH_LEVEL) || !(Prcb->DpcRoutineActive))
178 {
179 /* Handle being in kernel mode */
180 Thread->KernelTime++;
181 }
182 else
183 {
184 /* Handle being in a DPC */
185 Prcb->DpcTime++;
186
187#if DBG
188 /* Update the DPC time */
189 Prcb->DebugDpcTime++;
190
191 /* Check if we have timed out */
192 if (Prcb->DebugDpcTime == KiDPCTimeout)
193 {
194 /* We did! */
195 DbgPrint("*** DPC routine > 1 sec --- This is not a break in KeUpdateSystemTime\n");
196
197 /* Break if debugger is enabled */
199
200 /* Clear state */
201 Prcb->DebugDpcTime = 0;
202 }
203#endif
204 }
205 }
206
207 /* Update DPC rates */
208 Prcb->DpcRequestRate = ((Prcb->DpcData[0].DpcCount - Prcb->DpcLastCount) +
209 Prcb->DpcRequestRate) >> 1;
210 Prcb->DpcLastCount = Prcb->DpcData[0].DpcCount;
211
212 /* Check if the queue is large enough */
213 if ((Prcb->DpcData[0].DpcQueueDepth) && !(Prcb->DpcRoutineActive))
214 {
215 /* Request a DPC */
218
219 /* Fix the maximum queue depth */
220 if ((Prcb->DpcRequestRate < KiIdealDpcRate) &&
221 (Prcb->MaximumDpcQueueDepth > 1))
222 {
223 /* Make it smaller */
224 Prcb->MaximumDpcQueueDepth--;
225 }
226 }
227 else
228 {
229 /* Check if we've reached the adjustment limit */
230 if (!(--Prcb->AdjustDpcThreshold))
231 {
232 /* Reset it, and check the queue maximum */
235 {
236 /* Increase it */
237 Prcb->MaximumDpcQueueDepth++;
238 }
239 }
240 }
241
242 /* Decrement the thread quantum */
244
245 /* Check if the time expired */
246 if ((Thread->Quantum <= 0) && (Thread != Prcb->IdleThread))
247 {
248 /* Schedule a quantum end */
249 Prcb->QuantumEnd = 1;
251 }
252}
unsigned char BOOLEAN
_Out_ PKIRQL Irql
Definition: csq.h:179
#define FALSE
Definition: types.h:117
#define ULONG_PTR
Definition: config.h:101
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
IN OUT PLONG IN OUT PLONG Addend IN OUT PLONG IN LONG Increment
Definition: CrNtStubs.h:46
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
VOID FASTCALL HalRequestSoftwareInterrupt(IN KIRQL Irql)
Definition: pic.c:271
#define DbgPrint
Definition: hal.h:12
#define KeGetCurrentThread
Definition: hal.h:55
NTSYSAPI void WINAPI DbgBreakPoint(void)
#define InterlockedExchangeAdd
Definition: interlocked.h:181
BOOLEAN KdDebuggerEnabled
Definition: kddata.c:82
BOOLEAN NTAPI KdPollBreakIn(VOID)
Definition: kdlock.c:75
static PLARGE_INTEGER Time
Definition: time.c:105
#define UserMode
Definition: asm.h:35
#define EFLAGS_V86_MASK
Definition: ketypes.h:193
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1161
#define DBG_STATUS_CONTROL_C
Definition: kdtypes.h:39
#define CLOCK_QUANTUM_DECREMENT
Definition: ketypes.h:138
#define FASTCALL
Definition: nt_native.h:50
NTKERNELAPI volatile KSYSTEM_TIME KeTickCount
Definition: clock.c:19
FORCEINLINE BOOLEAN KiUserTrap(IN PKTRAP_FRAME TrapFrame)
Definition: ke.h:364
#define KiEndInterrupt(x, y)
Definition: ke.h:175
KTIMER_TABLE_ENTRY KiTimerTableListHead[TIMER_TABLE_SIZE]
Definition: timerobj.c:17
ULONG KiAdjustDpcThreshold
Definition: dpc.c:21
ULONG KiMaximumDpcQueueDepth
Definition: dpc.c:19
ULONG KiDPCTimeout
Definition: dpc.c:27
ULONG KiIdealDpcRate
Definition: dpc.c:22
ULONG KeMaximumIncrement
Definition: clock.c:20
BOOLEAN KiTimeAdjustmentEnabled
Definition: time.c:19
LONG KiTickOffset
Definition: time.c:17
ULONG KeTimeAdjustment
Definition: time.c:18
FORCEINLINE VOID KiCheckForTimerExpiration(PKPRCB Prcb, PKTRAP_FRAME TrapFrame, ULARGE_INTEGER InterruptTime)
Definition: time.c:40
FORCEINLINE VOID KiWriteSystemTime(volatile KSYSTEM_TIME *SystemTime, ULARGE_INTEGER NewTime)
Definition: time.c:25
VOID NTAPI KeUpdateRunTime(IN PKTRAP_FRAME TrapFrame, IN KIRQL Irql)
Definition: time.c:140
VOID FASTCALL KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame, IN ULONG Increment, IN KIRQL Irql)
Definition: time.c:64
long LONG
Definition: pedump.c:60
#define SharedUserData
ULONG DpcCount
Definition: ketypes.h:860
volatile ULONG DpcQueueDepth
Definition: ketypes.h:858
UCHAR QuantumEnd
Definition: ketypes.h:780
ULONG InterruptTime
Definition: ketypes.h:820
struct _KTHREAD * IdleThread
Definition: ketypes.h:652
ULONG UserTime
Definition: ketypes.h:818
UCHAR DpcRoutineActive
Definition: ketypes.h:772
ULONG InterruptCount
Definition: ketypes.h:816
ULONG DpcLastCount
Definition: ketypes.h:778
UCHAR SkipTick
Definition: ketypes.h:822
KDPC_DATA DpcData[2]
Definition: ketypes.h:760
ULONG DebugDpcTime
Definition: ketypes.h:572
ULONG DpcTime
Definition: ketypes.h:819
LONG MaximumDpcQueueDepth
Definition: ketypes.h:767
ULONG AdjustDpcThreshold
Definition: ketypes.h:821
ULONG KernelTime
Definition: ketypes.h:817
UINT64 TimerRequest
Definition: ketypes.h:775
ULONG DpcRequestRate
Definition: ketypes.h:768
UINT64 TimerHand
Definition: ketypes.h:774
LONG High1Time
Definition: ketypes.h:930
LONG High2Time
Definition: ketypes.h:931
ULONG LowPart
Definition: ketypes.h:929
$ULONG LowPart
Definition: ntbasedef.h:569
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
$ULONG HighPart
Definition: ntbasedef.h:570
#define NTAPI
Definition: typedefs.h:36
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
__analysis_noreturn NTSYSAPI VOID NTAPI DbgBreakPointWithStatus(_In_ ULONG Status)
LONGLONG QuadPart
Definition: typedefs.h:114
#define FORCEINLINE
Definition: wdftypes.h:67
#define TIMER_TABLE_SIZE
Definition: ketypes.h:848