Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

clock.c File Reference

#include "ki.h"
#include <ia64.h>
#include <ntia64.h>
#include <ntexapi.h>

Go to the source code of this file.

Functions

VOID KiProcessProfileList (IN PKTRAP_FRAME TrFrame, IN KPROFILE_SOURCE Source, IN PLIST_ENTRY ListHead)
BOOLEAN KiChkTimerExpireSysDpc (IN ULONGLONG TickCount)
VOID KeUpdateSystemTime (IN PKTRAP_FRAME TrFrame, IN ULONG Increment)
VOID KeUpdateRunTime (IN PKTRAP_FRAME TrFrame)
VOID KiDecrementQuantum ()
VOID KeProfileInterrupt (IN PKTRAP_FRAME TrFrame)
VOID KeProfileInterruptWithSource (IN PKTRAP_FRAME TrFrame, IN KPROFILE_SOURCE Source)


Function Documentation

VOID KeProfileInterrupt IN PKTRAP_FRAME  TrFrame  ) 
 

Definition at line 366 of file clock.c.

References KeProfileInterruptWithSource().

00371 : 00372 00373 This routine is executed on all processors in the processor complex. 00374 The routine is entered as the result of an interrupt generated by the profile 00375 timer. Its function is to update the profile information for the currently 00376 active profile objects. 00377 00378 N.B. KeProfileInterrupt is an alternate entry for backwards compatability that 00379 sets the source to zero (ProfileTime). 00380 00381 Arguments: 00382 00383 TrFrame - Supplies a pointer to a trap frame. 00384 00385 Return Value: 00386 00387 None. 00388 00389 --*/ 00390 00391 { 00392 KPROFILE_SOURCE Source = 0; 00393 00394 KeProfileInterruptWithSource(TrFrame, Source); 00395 00396 return; 00397 }

VOID KeProfileInterruptWithSource IN PKTRAP_FRAME  TrFrame,
IN KPROFILE_SOURCE  Source
 

Definition at line 401 of file clock.c.

References _KTHREAD::ApcState, KeGetCurrentThread, KiProcessProfileList(), KiProfileListHead, KiProfileLock, _KAPC_STATE::Process, and _KPROCESS::ProfileListHead.

Referenced by KeProfileInterrupt(), KiEmulateByteWord(), and KiEmulateReference().

00407 : 00408 00409 This routine is executed on all processors in the processor complex. 00410 The routine is entered as the result of an interrupt generated by the profile 00411 timer. Its function is to update the profile information for the currently 00412 active profile objects. 00413 00414 N.B. KeProfileInterruptWithSource is not currently fully implemented by any of 00415 the architectures. 00416 00417 Arguments: 00418 00419 TrFrame - Supplies a pointer to a trap frame. 00420 00421 Source - Supplies the source of the profile interrupt. 00422 00423 Return Value: 00424 00425 None. 00426 00427 --*/ 00428 00429 { 00430 PKTHREAD Thread = KeGetCurrentThread(); 00431 PKPROCESS Process = Thread->ApcState.Process; 00432 00433 #if !defined(NT_UP) 00434 KiAcquireSpinLock(&KiProfileLock); 00435 #endif 00436 00437 KiProcessProfileList(TrFrame, Source, &Process->ProfileListHead); 00438 00439 KiProcessProfileList(TrFrame, Source, &KiProfileListHead); 00440 00441 #if !defined(NT_UP) 00442 KiAcquireSpinLock(&KiProfileLock); 00443 #endif 00444 return; 00445 }

VOID KeUpdateRunTime IN PKTRAP_FRAME  TrFrame  ) 
 

Definition at line 208 of file clock.c.

References _KTHREAD::ApcState, CLOCK_QUANTUM_DECREMENT, DISPATCH_LEVEL, ExInterlockedIncrementLong(), KeGetCurrentPrcb, KeGetCurrentThread, KernelMode, _KPROCESS::KernelTime, _KTHREAD::KernelTime, KiAdjustDpcThreshold, KiIdealDpcRate, KiMaximumDpcQueueDepth, KiRequestSoftwareInterrupt(), Lock, _KAPC_STATE::Process, _KTHREAD::Quantum, _KPROCESS::UserTime, and _KTHREAD::UserTime.

Referenced by KeUpdateSystemTime().

00214 : 00215 00216 This routine is executed on all processors in the processor complex. 00217 It's function is to update the run time of the current thread, udpate the run 00218 time for the thread's process, and decrement the current thread's quantum. 00219 00220 Arguments: 00221 00222 TrFrame - Supplies a pointer to a trap frame. 00223 00224 Return Value: 00225 00226 None. 00227 00228 --*/ 00229 00230 { 00231 KSPIN_LOCK Lock; 00232 PKPRCB Prcb = KeGetCurrentPrcb(); 00233 PKTHREAD Thread = KeGetCurrentThread(); 00234 PKPROCESS Process = Thread->ApcState.Process; 00235 00236 // 00237 // If thread was executing in user mode: 00238 // increment the thread user time. 00239 // atomically increment the process user time. 00240 // else If the old IRQL is greater than the DPC level: 00241 // increment the time executing interrupt service routines. 00242 // else If the old IRQL is less than the DPC level or If a DPC is not active: 00243 // increment the thread kernel time. 00244 // atomically increment the process kernel time. 00245 // else 00246 // increment time executing DPC routines. 00247 // 00248 00249 if (TrFrame->PreviousMode != KernelMode) { 00250 ++Thread->UserTime; 00251 00252 // Atomic Update of Process User Time required. 00253 ExInterlockedIncrementLong(&Process->UserTime, &Lock); 00254 00255 // Update the time spent in user mode for the current processor. 00256 ++Prcb->UserTime; 00257 } else { 00258 00259 if (TrFrame->OldIrql > DISPATCH_LEVEL) { 00260 ++Prcb->InterruptTime; 00261 } else if ((TrFrame->OldIrql < DISPATCH_LEVEL) || 00262 (Prcb->DpcRoutineActive == 0)) { 00263 ++Thread->KernelTime; 00264 ExInterlockedIncrementLong(&Process->KernelTime, &Lock); 00265 } else { 00266 ++Prcb->DpcTime; 00267 } 00268 00269 // 00270 // Update the time spent in kernel mode for the current processor. 00271 // 00272 00273 ++Prcb->KernelTime; 00274 } 00275 00276 // 00277 // Update the DPC request rate which is computed as the average between the 00278 // previous rate and the current rate. 00279 // Update the DPC last count with the current DPC count. 00280 // 00281 Prcb->DpcRequestRate = ((Prcb->DpcCount - Prcb->DpcLastCount) + Prcb->DpcRequestRate) >> 1; 00282 Prcb->DpcLastCount = Prcb->DpcCount; 00283 00284 // 00285 // If the DPC queue depth is not zero and a DPC routine is not active. 00286 // Request a dispatch interrupt. 00287 // Decrement the maximum DPC queue depth. 00288 // Reset the threshold counter if appropriate. 00289 // 00290 if (Prcb->DpcQueueDepth != 0 && Prcb->DpcRoutineActive == 0) { 00291 00292 Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold; 00293 00294 // Need to request a DPC interrupt. 00295 KiRequestSoftwareInterrupt(DISPATCH_LEVEL); 00296 00297 if (Prcb->DpcRequestRate < KiIdealDpcRate && Prcb->MaximumDpcQueueDepth > 1) 00298 --Prcb->MaximumDpcQueueDepth; 00299 } else { 00300 // 00301 // The DPC queue is empty or a DPC routine is active or a DPC interrupt 00302 // has been requested. Count down the adjustment threshold and if the count 00303 // reaches zero, then increment the maximum DPC queue depth but not above 00304 // the initial value. Also, reset the adjustment threshold value. 00305 // 00306 --Prcb->AdjustDpcThreshold; 00307 if (Prcb->AdjustDpcThreshold == 0) { 00308 Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold; 00309 if (KiMaximumDpcQueueDepth != Prcb->MaximumDpcQueueDepth) 00310 ++Prcb->MaximumDpcQueueDepth; 00311 } 00312 } 00313 00314 // 00315 // Decrement current thread quantum and determine if quantum end has occurred. 00316 // 00317 Thread->Quantum -= CLOCK_QUANTUM_DECREMENT; 00318 00319 // Set quantum end if time expired, for any thread except idle thread. 00320 if (Thread->Quantum == 0 && Thread != Prcb->IdleThread) { 00321 00322 Prcb->QuantumEnd = 1; 00323 00324 // Need to request a DPC interrupt. 00325 KiRequestSoftwareInterrupt(DISPATCH_LEVEL); 00326 } 00327 00328 }

VOID KeUpdateSystemTime IN PKTRAP_FRAME  TrFrame,
IN ULONG  Increment
 

Definition at line 122 of file clock.c.

References Increment, KeMaximumIncrement, KeTickCount, KeTimeAdjustment, KeUpdateRunTime(), KiChkTimerExpireSysDpc(), and KiTickOffset.

00129 : 00130 00131 This routine is executed on a single processor in the processor complex. 00132 It's function is to update the system time and to check to determine if a 00133 timer has expired. 00134 00135 N.B. This routine is executed on a single processor in a multiprocess system. 00136 The remainder of the processors in the complex execute the quantum end and 00137 runtime update code. 00138 00139 Arguments: 00140 00141 TrFrame - Supplies a pointer to a trap frame. 00142 00143 Increment - The time increment to be used to adjust the time slice for the next 00144 tick. The value is supplied in 100ns units. 00145 00146 Return Value: 00147 00148 None. 00149 00150 --*/ 00151 00152 { 00153 long SaveTickOffset; 00154 LARGE_INTEGER SystemTime; 00155 00156 SharedUserData->InterruptTime += Increment; 00157 SharedUserData->InterruptHigh2Time = (LONG)(SharedUserData->InterruptTime >> 32); 00158 KiTickOffset -= Increment; 00159 00160 SaveTickOffset = KiTickOffset; 00161 00162 if ((LONG)KiTickOffset > 0) 00163 { 00164 // 00165 // Tick has not completed (100ns time units remain). 00166 // 00167 // Determine if a timer has expired at the current hand value. 00168 // 00169 00170 KiChkTimerExpireSysDpc(KeTickCount); 00171 00172 } else { 00173 00174 // 00175 // Tick has completed, tick count set to maximum increase plus any 00176 // residue and system time is updated. 00177 // 00178 // Compute next tick offset. 00179 // 00180 00181 KiTickOffset += KeMaximumIncrement; 00182 SystemTime.HighPart = SharedUserData->SystemHigh1Time; 00183 SystemTime.LowPart = SharedUserData->SystemLowTime; 00184 SystemTime.QuadPart += KeTimeAdjustment; 00185 SharedUserData->SystemHigh1Time = SystemTime.HighPart; 00186 SharedUserData->SystemLowTime = SystemTime.LowPart; 00187 SharedUserData->SystemHigh2Time = SystemTime.HighPart; 00188 ++KeTickCount; 00189 SharedUserData->TickCountLow = (ULONG)KeTickCount; 00190 00191 // 00192 // Determine if a timer has expired at either the current hand value or 00193 // the next hand value. 00194 // 00195 00196 if (!KiChkTimerExpireSysDpc(KeTickCount - 1)) 00197 KiChkTimerExpireSysDpc(KeTickCount); 00198 00199 } 00200 00201 if (SaveTickOffset <= 0) { 00202 KeUpdateRunTime(TrFrame); 00203 } 00204 }

BOOLEAN KiChkTimerExpireSysDpc IN ULONGLONG  TickCount  ) 
 

Definition at line 38 of file clock.c.

References DISPATCH_LEVEL, _KDPC::DpcListEntry, _KTIMER::DueTime, FALSE, KeGetCurrentPrcb, KiRequestSoftwareInterrupt(), KiTimerExpireDpc, KiTimerTableListHead, _KDPC::Lock, NULL, PKTIMER, _KDPC::SystemArgument1, _KDPC::SystemArgument2, TickCount(), TIMER_TABLE_SIZE, and TRUE.

Referenced by KeUpdateSystemTime().

00044 : 00045 00046 This routine determines if it should attempt to place a timer expiration DPC 00047 in the system DPC list and to drive the DPC by initiating a dispatch level interrupt 00048 on the current processor. 00049 00050 N.B. If DPC is already inserted on the DPC list, we're done. 00051 00052 Arguments: 00053 00054 TickCount - The lower tick count, timer table hand value 00055 00056 Return Value: 00057 00058 BOOLEAN - Set to true if Queued DPC or if DPC already Queued. 00059 00060 --*/ 00061 00062 { 00063 BOOLEAN ret = FALSE; // No DPC queued, default return value. 00064 00065 PLIST_ENTRY ListHead = &KiTimerTableListHead[(ULONG)TickCount%TIMER_TABLE_SIZE]; 00066 PLIST_ENTRY NextEntry = ListHead->Flink; 00067 00068 // 00069 // Check to see if the list is empty. 00070 // 00071 if (NextEntry != ListHead) { 00072 PKTIMER Timer = CONTAINING_RECORD(NextEntry, KTIMER, TimerListEntry); 00073 ULONGLONG TimeValue = Timer->DueTime.QuadPart; 00074 00075 // 00076 // See if timer expired. 00077 // 00078 00079 if (TimeValue <= SharedUserData->InterruptTime) { 00080 00081 PKPRCB Prcb = KeGetCurrentPrcb(); 00082 PKDPC Dpc = &KiTimerExpireDpc; 00083 00084 _disable(); 00085 #if !defined(NT_UP) 00086 KiAcquireSpinLock(&Prcb->DpcLock); 00087 #endif 00088 // 00089 // Insert DPC only if not already inserted. 00090 // 00091 if (Dpc->Lock == NULL) { 00092 00093 // 00094 // Put timer expiration DPC in the system DPC list and initiate 00095 // a dispatch interrupt on the current processor. 00096 // 00097 00098 Prcb->DpcCount += 1; 00099 Prcb->DpcQueueDepth += 1; 00100 Dpc->Lock = &Prcb->DpcLock; 00101 Dpc->SystemArgument1 = (PVOID)TickCount; 00102 Dpc->SystemArgument2 = 0; 00103 InsertTailList(&Prcb->DpcListHead, &Dpc->DpcListEntry); 00104 KiRequestSoftwareInterrupt(DISPATCH_LEVEL); 00105 } 00106 00107 ret = TRUE; 00108 00109 #if !defined(NT_UP) 00110 KiReleaseSpinLock(&Prcb->DpcLock); 00111 #endif 00112 00113 _enable(); 00114 } 00115 } 00116 00117 return(ret); 00118 }

VOID KiDecrementQuantum  ) 
 

Definition at line 332 of file clock.c.

References CLOCK_QUANTUM_DECREMENT, KeGetCurrentPrcb, KeGetCurrentThread, and _KTHREAD::Quantum.

00337 : 00338 00339 This routine is executed on all processors in the processor complex. 00340 Decrement current thread quantum and check to determine if a quantum end 00341 has occurred. 00342 00343 Arguments: 00344 00345 None. 00346 00347 Return Value: 00348 00349 None. 00350 00351 --*/ 00352 00353 { 00354 PKTHREAD Thread = KeGetCurrentThread(); 00355 PKPRCB Prcb = KeGetCurrentPrcb(); 00356 00357 Thread->Quantum -= CLOCK_QUANTUM_DECREMENT; 00358 00359 // Set quantum end if time expired, for any thread except idle thread. 00360 if (Thread->Quantum == 0 && Thread != Prcb->IdleThread) 00361 Prcb->QuantumEnd = 1; 00362 }

VOID KiProcessProfileList IN PKTRAP_FRAME  TrFrame,
IN KPROFILE_SOURCE  Source,
IN PLIST_ENTRY  ListHead
 

Definition at line 449 of file clock.c.

References _KPROFILE::Affinity, _KPROFILE::BucketShift, _KPROFILE::Buffer, KeGetCurrentPrcb, KPROFILE, PKPROFILE, _KPROFILE::RangeBase, _KPROFILE::RangeLimit, and _KPROFILE::Source.

Referenced by KeProfileInterruptWithSource().

00456 : 00457 00458 This routine is executed on all processors in the processor complex. 00459 The routine is entered as the result of an interrupt generated by the profile 00460 timer. Its function is to update the profile information for the currently 00461 active profile objects. 00462 00463 N.B. KeProfileInterruptWithSource is not currently fully implemented by any of 00464 the architectures. 00465 00466 Arguments: 00467 00468 TrFrame - Supplies a pointer to a trap frame. 00469 00470 Source - Supplies the source of the profile interrupt. 00471 00472 ListHead - Supplies a pointer to a profile list. 00473 00474 Return Value: 00475 00476 None. 00477 00478 --*/ 00479 00480 { 00481 PLIST_ENTRY NextEntry = ListHead->Flink; 00482 PKPRCB Prcb = KeGetCurrentPrcb(); 00483 00484 // 00485 // Scan profile list and increment profile buckets as appropriate. 00486 // 00487 for (; NextEntry != ListHead; NextEntry = NextEntry->Flink) { 00488 00489 PCHAR BucketPter; 00490 PULONG BucketValue; 00491 00492 PKPROFILE Profile = CONTAINING_RECORD(NextEntry, KPROFILE, ProfileListEntry); 00493 00494 if (Profile->Source != Source || ((Profile->Affinity & Prcb->SetMember) == 0)) 00495 continue; 00496 00497 if ((PVOID)TrFrame->StIIP < Profile->RangeBase || (PVOID)TrFrame->StIIP > Profile->RangeLimit) 00498 continue; 00499 00500 BucketPter = (PCHAR)Profile->Buffer + 00501 ((((PCHAR)TrFrame->StIIP - (PCHAR)Profile->RangeBase) 00502 >> Profile->BucketShift) & 0xFFFFFFFC); 00503 00504 BucketValue = (PULONG) BucketPter; 00505 ++BucketValue; 00506 } 00507 00508 return; 00509 } }


Generated on Sat May 15 19:43:05 2004 for test by doxygen 1.3.7