ReactOS 0.4.17-dev-116-ga4b6fe9
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
26 PKPRCB Prcb,
27 PKTRAP_FRAME TrapFrame,
28 LARGE_INTEGER InterruptTime)
29{
30 ULONG Hand;
31
32 /* Check for timer expiration */
34 if (KiTimerTableListHead[Hand].Time.QuadPart <= (ULONG64)InterruptTime.QuadPart)
35 {
36 /* Check if we are already doing expiration */
37 if (!Prcb->TimerRequest)
38 {
39 /* Request a DPC to handle this */
40 Prcb->TimerRequest = (ULONG_PTR)TrapFrame;
41 Prcb->TimerHand = Hand;
43 }
44 }
45}
46
47VOID
52{
53 PKPRCB Prcb = KeGetCurrentPrcb();
54 LARGE_INTEGER CurrentTime, InterruptTime;
55 LONG OldTickOffset;
56
57 /* Check if this tick is being skipped */
58 if (Prcb->SkipTick)
59 {
60 /* Handle it next time */
61 Prcb->SkipTick = FALSE;
62
63 /* Increase interrupt count and end the interrupt */
64 Prcb->InterruptCount++;
65
66#ifdef _M_IX86 // x86 optimization
67 KiEndInterrupt(Irql, TrapFrame);
68#endif
69
70 /* Note: non-x86 return back to the caller! */
71 return;
72 }
73
74 /* Add the increment time to the shared data */
75 InterruptTime.QuadPart = *(ULONGLONG*)&SharedUserData->InterruptTime;
76 InterruptTime.QuadPart += Increment;
77 KiWriteSystemTime(&SharedUserData->InterruptTime, InterruptTime);
78
79 /* Check for timer expiration */
80 KiCheckForTimerExpiration(Prcb, TrapFrame, InterruptTime);
81
82 /* Update the tick offset */
84
85 /* If the debugger is enabled, check for break-in request */
87 {
88 /* Break-in requested! */
90 }
91
92 /* Check for full tick */
93 if (OldTickOffset <= (LONG)Increment)
94 {
95 /* Update the system time */
96 CurrentTime.QuadPart = *(ULONGLONG*)&SharedUserData->SystemTime;
97 CurrentTime.QuadPart += KeTimeAdjustment;
98 KiWriteSystemTime(&SharedUserData->SystemTime, CurrentTime);
99
100 /* Update the tick count */
101 CurrentTime.QuadPart = (*(ULONGLONG*)&KeTickCount) + 1;
102 KiWriteSystemTime(&KeTickCount, CurrentTime);
103
104 /* Update it in the shared user data */
105 KiWriteSystemTime(&SharedUserData->TickCount, CurrentTime);
106
107 /* Check for expiration with the new tick count as well */
108 KiCheckForTimerExpiration(Prcb, TrapFrame, InterruptTime);
109
110 /* Reset the tick offset */
112
113 /* Update processor/thread runtime */
114 KeUpdateRunTime(TrapFrame, Irql);
115 }
116 else
117 {
118 /* Increase interrupt count only */
119 Prcb->InterruptCount++;
120 }
121
122#ifdef _M_IX86 // x86 optimization
123 /* Disable interrupts and end the interrupt */
124 KiEndInterrupt(Irql, TrapFrame);
125#endif
126}
127
128VOID
129NTAPI
131 IN KIRQL Irql)
132{
134 PKPRCB Prcb = KeGetCurrentPrcb();
135
136 /* Check if this tick is being skipped */
137 if (Prcb->SkipTick)
138 {
139 /* Handle it next time */
140 Prcb->SkipTick = FALSE;
141 return;
142 }
143
144 /* Increase interrupt count */
145 Prcb->InterruptCount++;
146
147 /* Check if we came from user mode */
148#ifndef _M_ARM
149 if (KiUserTrap(TrapFrame) || (TrapFrame->EFlags & EFLAGS_V86_MASK))
150#else
151 if (TrapFrame->PreviousMode == UserMode)
152#endif
153 {
154 /* Increase thread user time */
155 Prcb->UserTime++;
156 Thread->UserTime++;
157 }
158 else
159 {
160 /* See if we were in an ISR */
161 Prcb->KernelTime++;
162 if (Irql > DISPATCH_LEVEL)
163 {
164 /* Handle that */
165 Prcb->InterruptTime++;
166 }
167 else if ((Irql < DISPATCH_LEVEL) || !(Prcb->DpcRoutineActive))
168 {
169 /* Handle being in kernel mode */
170 Thread->KernelTime++;
171 }
172 else
173 {
174 /* Handle being in a DPC */
175 Prcb->DpcTime++;
176
177#if DBG
178 /* Update the DPC time */
179 Prcb->DebugDpcTime++;
180
181 /* Check if we have timed out */
182 if (Prcb->DebugDpcTime == KiDPCTimeout)
183 {
184 /* We did! */
185 DbgPrint("*** DPC routine > 1 sec --- This is not a break in KeUpdateSystemTime\n");
186
187 /* Break if debugger is enabled */
189
190 /* Clear state */
191 Prcb->DebugDpcTime = 0;
192 }
193#endif
194 }
195 }
196
197 /* Update DPC rates */
198 Prcb->DpcRequestRate = ((Prcb->DpcData[0].DpcCount - Prcb->DpcLastCount) +
199 Prcb->DpcRequestRate) >> 1;
200 Prcb->DpcLastCount = Prcb->DpcData[0].DpcCount;
201
202 /* Check if the queue is large enough */
203 if ((Prcb->DpcData[0].DpcQueueDepth) && !(Prcb->DpcRoutineActive))
204 {
205 /* Request a DPC */
208
209 /* Fix the maximum queue depth */
210 if ((Prcb->DpcRequestRate < KiIdealDpcRate) &&
211 (Prcb->MaximumDpcQueueDepth > 1))
212 {
213 /* Make it smaller */
214 Prcb->MaximumDpcQueueDepth--;
215 }
216 }
217 else
218 {
219 /* Check if we've reached the adjustment limit */
220 if (!(--Prcb->AdjustDpcThreshold))
221 {
222 /* Reset it, and check the queue maximum */
225 {
226 /* Increase it */
227 Prcb->MaximumDpcQueueDepth++;
228 }
229 }
230 }
231
232 /* Decrement the thread quantum */
234
235 /* Check if the time expired */
236 if ((Thread->Quantum <= 0) && (Thread != Prcb->IdleThread))
237 {
238 /* Schedule a quantum end */
239 Prcb->QuantumEnd = 1;
241 }
242}
unsigned char BOOLEAN
Definition: actypes.h:127
_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
#define InterlockedExchangeAdd
Definition: interlocked.h:196
BOOLEAN KdDebuggerEnabled
Definition: kddata.c:82
BOOLEAN NTAPI KdPollBreakIn(VOID)
Definition: kdlock.c:75
unsigned __int64 ULONG64
Definition: imports.h:198
static PLARGE_INTEGER Time
Definition: time.c:37
#define EFLAGS_V86_MASK
Definition: ketypes.h:202
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1187
#define UserMode
Definition: asm.h:39
#define DBG_STATUS_CONTROL_C
Definition: kdtypes.h:39
FORCEINLINE VOID KiWriteSystemTime(_Out_ volatile KSYSTEM_TIME *SystemTime, _In_ LARGE_INTEGER NewTime)
Definition: kefuncs.h:429
#define CLOCK_QUANTUM_DECREMENT
Definition: ketypes.h:133
#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:369
#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
FORCEINLINE VOID KiCheckForTimerExpiration(PKPRCB Prcb, PKTRAP_FRAME TrapFrame, LARGE_INTEGER InterruptTime)
Definition: time.c:25
ULONG KeTimeAdjustment
Definition: time.c:18
VOID NTAPI KeUpdateRunTime(IN PKTRAP_FRAME TrapFrame, IN KIRQL Irql)
Definition: time.c:130
VOID FASTCALL KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame, IN ULONG Increment, IN KIRQL Irql)
Definition: time.c:49
long LONG
Definition: pedump.c:60
#define SharedUserData
ULONG DpcCount
Definition: ketypes.h:985
volatile ULONG DpcQueueDepth
Definition: ketypes.h:983
UINT64 TimerHand
Definition: ketypes.h:788
UINT64 TimerRequest
Definition: ketypes.h:789
ULONG InterruptTime
Definition: ketypes.h:834
struct _KTHREAD * IdleThread
Definition: ketypes.h:666
ULONG UserTime
Definition: ketypes.h:832
ULONG InterruptCount
Definition: ketypes.h:830
LONG MaximumDpcQueueDepth
Definition: ketypes.h:781
ULONG DpcLastCount
Definition: ketypes.h:792
UCHAR SkipTick
Definition: ketypes.h:836
ULONG DebugDpcTime
Definition: ketypes.h:572
KDPC_DATA DpcData[2]
Definition: ketypes.h:774
UCHAR QuantumEnd
Definition: ketypes.h:794
ULONG DpcTime
Definition: ketypes.h:833
ULONG AdjustDpcThreshold
Definition: ketypes.h:835
ULONG KernelTime
Definition: ketypes.h:831
ULONG DpcRequestRate
Definition: ketypes.h:782
UCHAR DpcRoutineActive
Definition: ketypes.h:786
ULONG LowPart
Definition: wdm.h:5
#define NTAPI
Definition: typedefs.h:36
uint64_t ULONGLONG
Definition: typedefs.h:67
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
__analysis_noreturn NTSYSAPI VOID NTAPI DbgBreakPointWithStatus(_In_ ULONG Status)
LONGLONG QuadPart
Definition: typedefs.h:114
#define FORCEINLINE
Definition: wdftypes.h:67
NTSYSAPI void WINAPI DbgBreakPoint(void)
#define TIMER_TABLE_SIZE
Definition: ketypes.h:900