Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygentime.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * LICENSE: BSD - See COPYING.ARM in the top level directory 00004 * FILE: ntoskrnl/ke/time.c 00005 * PURPOSE: Implements timebase functionality 00006 * PROGRAMMERS: ReactOS Portable Systems Group 00007 */ 00008 00009 /* INCLUDES *******************************************************************/ 00010 00011 #include <ntoskrnl.h> 00012 #define NDEBUG 00013 #include <debug.h> 00014 00015 /* GLOBALS ********************************************************************/ 00016 00017 LONG KiTickOffset; 00018 ULONG KeTimeAdjustment; 00019 BOOLEAN KiTimeAdjustmentEnabled = FALSE; 00020 00021 /* FUNCTIONS ******************************************************************/ 00022 00023 VOID 00024 FORCEINLINE 00025 KiWriteSystemTime(volatile KSYSTEM_TIME *SystemTime, ULARGE_INTEGER NewTime) 00026 { 00027 #ifdef _WIN64 00028 /* Do a single atomic write */ 00029 *(ULONGLONG*)SystemTime = NewTime.QuadPart; 00030 #else 00031 /* Update in 3 steps, so that a reader can recognize partial updates */ 00032 SystemTime->High1Time = NewTime.HighPart; 00033 SystemTime->LowPart = NewTime.LowPart; 00034 SystemTime->High2Time = NewTime.HighPart; 00035 #endif 00036 } 00037 00038 VOID 00039 FORCEINLINE 00040 KiCheckForTimerExpiration( 00041 PKPRCB Prcb, 00042 PKTRAP_FRAME TrapFrame, 00043 ULARGE_INTEGER InterruptTime) 00044 { 00045 ULONG Hand; 00046 00047 /* Check for timer expiration */ 00048 Hand = KeTickCount.LowPart & (TIMER_TABLE_SIZE - 1); 00049 if (KiTimerTableListHead[Hand].Time.QuadPart <= InterruptTime.QuadPart) 00050 { 00051 /* Check if we are already doing expiration */ 00052 if (!Prcb->TimerRequest) 00053 { 00054 /* Request a DPC to handle this */ 00055 Prcb->TimerRequest = (ULONG_PTR)TrapFrame; 00056 Prcb->TimerHand = Hand; 00057 HalRequestSoftwareInterrupt(DISPATCH_LEVEL); 00058 } 00059 } 00060 } 00061 00062 VOID 00063 FASTCALL 00064 KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame, 00065 IN ULONG Increment, 00066 IN KIRQL Irql) 00067 { 00068 PKPRCB Prcb = KeGetCurrentPrcb(); 00069 ULARGE_INTEGER CurrentTime, InterruptTime; 00070 LONG OldTickOffset; 00071 00072 /* Check if this tick is being skipped */ 00073 if (Prcb->SkipTick) 00074 { 00075 /* Handle it next time */ 00076 Prcb->SkipTick = FALSE; 00077 00078 /* Increase interrupt count and end the interrupt */ 00079 Prcb->InterruptCount++; 00080 KiEndInterrupt(Irql, TrapFrame); 00081 } 00082 00083 /* Add the increment time to the shared data */ 00084 InterruptTime.QuadPart = *(ULONGLONG*)&SharedUserData->InterruptTime; 00085 InterruptTime.QuadPart += Increment; 00086 KiWriteSystemTime(&SharedUserData->InterruptTime, InterruptTime); 00087 00088 /* Check for timer expiration */ 00089 KiCheckForTimerExpiration(Prcb, TrapFrame, InterruptTime); 00090 00091 /* Update the tick offset */ 00092 OldTickOffset = InterlockedExchangeAdd(&KiTickOffset, -(LONG)Increment); 00093 00094 /* If the debugger is enabled, check for break-in request */ 00095 if (KdDebuggerEnabled && KdPollBreakIn()) 00096 { 00097 /* Break-in requested! */ 00098 DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C); 00099 } 00100 00101 /* Check for full tick */ 00102 if (OldTickOffset <= (LONG)Increment) 00103 { 00104 /* Update the system time */ 00105 CurrentTime.QuadPart = *(ULONGLONG*)&SharedUserData->SystemTime; 00106 CurrentTime.QuadPart += KeTimeAdjustment; 00107 KiWriteSystemTime(&SharedUserData->SystemTime, CurrentTime); 00108 00109 /* Update the tick count */ 00110 CurrentTime.QuadPart = (*(ULONGLONG*)&KeTickCount) + 1; 00111 KiWriteSystemTime(&KeTickCount, CurrentTime); 00112 00113 /* Update it in the shared user data */ 00114 KiWriteSystemTime(&SharedUserData->TickCount, CurrentTime); 00115 00116 /* Check for expiration with the new tick count as well */ 00117 KiCheckForTimerExpiration(Prcb, TrapFrame, InterruptTime); 00118 00119 /* Reset the tick offset */ 00120 KiTickOffset += KeMaximumIncrement; 00121 00122 /* Update processor/thread runtime */ 00123 KeUpdateRunTime(TrapFrame, Irql); 00124 } 00125 else 00126 { 00127 /* Increase interrupt count only */ 00128 Prcb->InterruptCount++; 00129 } 00130 00131 /* Disable interrupts and end the interrupt */ 00132 KiEndInterrupt(Irql, TrapFrame); 00133 } 00134 00135 VOID 00136 NTAPI 00137 KeUpdateRunTime(IN PKTRAP_FRAME TrapFrame, 00138 IN KIRQL Irql) 00139 { 00140 PKTHREAD Thread = KeGetCurrentThread(); 00141 PKPRCB Prcb = KeGetCurrentPrcb(); 00142 00143 /* Check if this tick is being skipped */ 00144 if (Prcb->SkipTick) 00145 { 00146 /* Handle it next time */ 00147 Prcb->SkipTick = FALSE; 00148 return; 00149 } 00150 00151 /* Increase interrupt count */ 00152 Prcb->InterruptCount++; 00153 00154 /* Check if we came from user mode */ 00155 #ifndef _M_ARM 00156 if ((TrapFrame->SegCs & MODE_MASK) || (TrapFrame->EFlags & EFLAGS_V86_MASK)) 00157 #else 00158 if (TrapFrame->PreviousMode == UserMode) 00159 #endif 00160 { 00161 /* Increase thread user time */ 00162 Prcb->UserTime++; 00163 Thread->UserTime++; 00164 } 00165 else 00166 { 00167 /* See if we were in an ISR */ 00168 Prcb->KernelTime++; 00169 if (Irql > DISPATCH_LEVEL) 00170 { 00171 /* Handle that */ 00172 Prcb->InterruptTime++; 00173 } 00174 else if ((Irql < DISPATCH_LEVEL) || !(Prcb->DpcRoutineActive)) 00175 { 00176 /* Handle being in kernel mode */ 00177 Thread->KernelTime++; 00178 } 00179 else 00180 { 00181 /* Handle being in a DPC */ 00182 Prcb->DpcTime++; 00183 00184 #if 0 //DBG 00185 /* Update the DPC time */ 00186 Prcb->DebugDpcTime++; 00187 00188 /* Check if we have timed out */ 00189 if (Prcb->DebugDpcTime == KiDPCTimeout); 00190 { 00191 /* We did! */ 00192 DbgPrint("*** DPC routine > 1 sec --- This is not a break in KeUpdateSystemTime\n"); 00193 00194 /* Break if debugger is enabled */ 00195 if (KdDebuggerEnabled) DbgBreakPoint(); 00196 00197 /* Clear state */ 00198 Prcb->DebugDpcTime = 0; 00199 } 00200 #endif 00201 } 00202 } 00203 00204 /* Update DPC rates */ 00205 Prcb->DpcRequestRate = ((Prcb->DpcData[0].DpcCount - Prcb->DpcLastCount) + 00206 Prcb->DpcRequestRate) >> 1; 00207 Prcb->DpcLastCount = Prcb->DpcData[0].DpcCount; 00208 00209 /* Check if the queue is large enough */ 00210 if ((Prcb->DpcData[0].DpcQueueDepth) && !(Prcb->DpcRoutineActive)) 00211 { 00212 /* Request a DPC */ 00213 Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold; 00214 HalRequestSoftwareInterrupt(DISPATCH_LEVEL); 00215 00216 /* Fix the maximum queue depth */ 00217 if ((Prcb->DpcRequestRate < KiIdealDpcRate) && 00218 (Prcb->MaximumDpcQueueDepth > 1)) 00219 { 00220 /* Make it smaller */ 00221 Prcb->MaximumDpcQueueDepth--; 00222 } 00223 } 00224 else 00225 { 00226 /* Check if we've reached the adjustment limit */ 00227 if (!(--Prcb->AdjustDpcThreshold)) 00228 { 00229 /* Reset it, and check the queue maximum */ 00230 Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold; 00231 if (KiMaximumDpcQueueDepth != Prcb->MaximumDpcQueueDepth) 00232 { 00233 /* Increase it */ 00234 Prcb->MaximumDpcQueueDepth++; 00235 } 00236 } 00237 } 00238 00239 /* Decrement the thread quantum */ 00240 Thread->Quantum -= CLOCK_QUANTUM_DECREMENT; 00241 00242 /* Check if the time expired */ 00243 if ((Thread->Quantum <= 0) && (Thread != Prcb->IdleThread)) 00244 { 00245 /* Schedule a quantum end */ 00246 Prcb->QuantumEnd = 1; 00247 HalRequestSoftwareInterrupt(DISPATCH_LEVEL); 00248 } 00249 } Generated on Sat May 26 2012 04:17:07 for ReactOS by
1.7.6.1
|