2 * PROJECT: ReactOS Kernel
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: ntoskrnl/ke/arm/time.c
5 * PURPOSE: Implements timebase functionality on ARM processors
6 * PROGRAMMERS: ReactOS Portable Systems Group
9 /* INCLUDES *******************************************************************/
15 /* GLOBALS ********************************************************************/
18 ULONG KeTimeAdjustment
;
20 /* FUNCTIONS ******************************************************************/
23 KiComputeTimerTableIndex(IN LONGLONG DueTime
)
28 // Compute the timer table index
30 Hand
= (DueTime
/ KeMaximumIncrement
);
31 Hand
%= TIMER_TABLE_SIZE
;
37 KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame
,
41 PKPRCB Prcb
= KeGetPcr()->Prcb
;
42 ULARGE_INTEGER SystemTime
, InterruptTime
;
46 // Do nothing if this tick is being skipped
51 // Handle it next time
53 Prcb
->SkipTick
= FALSE
;
58 // Add the increment time to the shared data
60 InterruptTime
.HighPart
= SharedUserData
->InterruptTime
.High1Time
;
61 InterruptTime
.LowPart
= SharedUserData
->InterruptTime
.LowPart
;
62 InterruptTime
.QuadPart
+= Increment
;
63 SharedUserData
->InterruptTime
.High1Time
= InterruptTime
.HighPart
;
64 SharedUserData
->InterruptTime
.LowPart
= InterruptTime
.LowPart
;
65 SharedUserData
->InterruptTime
.High2Time
= InterruptTime
.HighPart
;
70 KiTickOffset
-= Increment
;
73 // Check for incomplete tick
75 if (KiTickOffset
<= 0)
78 // Update the system time
80 SystemTime
.HighPart
= SharedUserData
->SystemTime
.High1Time
;
81 SystemTime
.LowPart
= SharedUserData
->SystemTime
.LowPart
;
82 SystemTime
.QuadPart
+= KeTimeAdjustment
;
83 SharedUserData
->SystemTime
.High1Time
= SystemTime
.HighPart
;
84 SharedUserData
->SystemTime
.LowPart
= SystemTime
.LowPart
;
85 SharedUserData
->SystemTime
.High2Time
= SystemTime
.HighPart
;
88 // Update the tick count
90 SystemTime
.HighPart
= KeTickCount
.High1Time
;
91 SystemTime
.LowPart
= KeTickCount
.LowPart
;
92 SystemTime
.QuadPart
+= 1;
93 KeTickCount
.High1Time
= SystemTime
.HighPart
;
94 KeTickCount
.LowPart
= SystemTime
.LowPart
;
95 KeTickCount
.High2Time
= SystemTime
.HighPart
;
98 // Update it in the shared user data
100 SharedUserData
->TickCount
.High1Time
= SystemTime
.HighPart
;
101 SharedUserData
->TickCount
.LowPart
= SystemTime
.LowPart
;
102 SharedUserData
->TickCount
.High2Time
= SystemTime
.HighPart
;
106 // Check for timer expiration
108 Hand
= KeTickCount
.LowPart
% TIMER_TABLE_SIZE
;
109 if (KiTimerTableListHead
[Hand
].Time
.QuadPart
<= InterruptTime
.QuadPart
)
112 // Check if we are already doing expiration
114 if (!Prcb
->TimerRequest
)
117 // Request a DPC to handle this
119 Prcb
->TimerRequest
= TrapFrame
->SvcSp
;
120 Prcb
->TimerHand
= Hand
;
121 HalRequestSoftwareInterrupt(DISPATCH_LEVEL
);
126 // Check if we should request a debugger break
128 if (KdDebuggerEnabled
)
131 // Check if we should break
133 if (KdPollBreakIn()) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C
);
137 // Check if this was a full tick
139 if (KiTickOffset
<= 0)
142 // Updare the tick offset
144 KiTickOffset
+= KeMaximumIncrement
;
147 // Update system runtime
149 KeUpdateRunTime(TrapFrame
, CLOCK2_LEVEL
);
154 // Increase interrupt count and exit
156 Prcb
->InterruptCount
++;
162 KeUpdateRunTime(IN PKTRAP_FRAME TrapFrame
,
165 PKTHREAD Thread
= KeGetCurrentThread();
166 PKPROCESS Process
= Thread
->ApcState
.Process
;
167 PKPRCB Prcb
= KeGetCurrentPrcb();
170 // Do nothing if this tick is being skipped
175 // Handle it next time
177 Prcb
->SkipTick
= FALSE
;
182 // Increase interrupt count
184 Prcb
->InterruptCount
++;
187 // Check if we came from user mode
189 if (TrapFrame
->PreviousMode
!= KernelMode
)
192 // Increase process user time
194 InterlockedIncrement((PLONG
)&Process
->UserTime
);
201 // See if we were in an ISR
203 if (TrapFrame
->OldIrql
> DISPATCH_LEVEL
)
208 Prcb
->InterruptTime
++;
210 else if ((TrapFrame
->OldIrql
< DISPATCH_LEVEL
) ||
211 !(Prcb
->DpcRoutineActive
))
214 // Handle being in kernel mode
216 Thread
->KernelTime
++;
217 InterlockedIncrement((PLONG
)&Process
->KernelTime
);
222 // Handle being in a DPC
227 // Update Debug DPC time
229 Prcb
->DebugDpcTime
++;
232 // Check if we've timed out
234 if (Prcb
->DebugDpcTime
>= KiDPCTimeout
)
239 DbgPrint("\n*** DPC routine > 1 sec --- This is not a break in "
240 "KeUpdateSystemTime\n");
243 // Break if a debugger is attached
245 if (KdDebuggerEnabled
) DbgBreakPoint();
248 // Restore the debug DPC time
250 Prcb
->DebugDpcTime
= 0;
258 Prcb
->DpcRequestRate
= ((Prcb
->DpcData
[0].DpcCount
- Prcb
->DpcLastCount
) +
259 Prcb
->DpcRequestRate
) >> 1;
260 Prcb
->DpcLastCount
= Prcb
->DpcData
[0].DpcCount
;
263 // Check if the queue is large enough
265 if ((Prcb
->DpcData
[0].DpcQueueDepth
) && !(Prcb
->DpcRoutineActive
))
270 Prcb
->AdjustDpcThreshold
= KiAdjustDpcThreshold
;
271 HalRequestSoftwareInterrupt(DISPATCH_LEVEL
);
274 // Fix the maximum queue depth
276 if ((Prcb
->DpcRequestRate
< KiIdealDpcRate
) &&
277 (Prcb
->MaximumDpcQueueDepth
> 1))
282 Prcb
->MaximumDpcQueueDepth
--;
288 // Check if we've reached the adjustment limit
290 if (!(--Prcb
->AdjustDpcThreshold
))
293 // Reset it, and check the queue maximum
295 Prcb
->AdjustDpcThreshold
= KiAdjustDpcThreshold
;
296 if (KiMaximumDpcQueueDepth
!= Prcb
->MaximumDpcQueueDepth
)
301 Prcb
->MaximumDpcQueueDepth
++;
307 // Decrement the thread quantum
309 Thread
->Quantum
-= CLOCK_QUANTUM_DECREMENT
;
312 // Check if the time expired
314 if ((Thread
->Quantum
<= 0) && (Thread
!= Prcb
->IdleThread
))
317 // Schedule a quantum end
319 Prcb
->QuantumEnd
= 1;
320 HalRequestSoftwareInterrupt(DISPATCH_LEVEL
);