/*++ Routine Description: Clock interrupt handler for processors other than 0. Arguments: Interrupt ServiceContext TrapFrame Return Value: TRUE --*/ BOOLEAN HalpHandleDecrementerInterrupt1( IN PKINTERRUPT Interrupt, IN PVOID ServiceContext, IN PVOID TrapFrame ) { KIRQL OldIrql; ULONG CpuId; HASSERT(!MSR(EE)); CpuId = GetCpuId(); // // Raise irql via updating the PCR // OldIrql = PCR->CurrentIrql; PCR->CurrentIrql = CLOCK2_LEVEL; RInterruptMask(CpuId) = (Irql2Mask[CLOCK2_LEVEL] & registeredInts[CpuId]); WaitForRInterruptMask(CpuId); // // Reset DECREMENTER (no account for latency) // HalpUpdateDecrementer(HalpFullTickClockCount); // // Call the kernel to update run time for this thread and process. // KeUpdateRunTime(TrapFrame); HDBG(DBG_PROC1DBG, { // // Check for the debugger BreakIn only every minute or so. // (decrementer is interms of ms so we multiple by 10,000 // on the order of a minute). // static Count = 0; if (++Count > 10000) { Count = 0; if (KdDebuggerEnabled && KdPollBreakIn()) { HalpEnableInterrupts(); DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C); HalpDisableInterrupts(); } } } );
VOID FASTCALL KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame, IN ULONG Increment, IN KIRQL Irql) { PKPRCB Prcb = KeGetCurrentPrcb(); ULARGE_INTEGER CurrentTime, InterruptTime; LONG OldTickOffset; /* Check if this tick is being skipped */ if (Prcb->SkipTick) { /* Handle it next time */ Prcb->SkipTick = FALSE; /* Increase interrupt count and end the interrupt */ Prcb->InterruptCount++; KiEndInterrupt(Irql, TrapFrame); /* Note: non-x86 return back to the caller! */ return; } /* Add the increment time to the shared data */ InterruptTime.QuadPart = *(ULONGLONG*)&SharedUserData->InterruptTime; InterruptTime.QuadPart += Increment; KiWriteSystemTime(&SharedUserData->InterruptTime, InterruptTime); /* Check for timer expiration */ KiCheckForTimerExpiration(Prcb, TrapFrame, InterruptTime); /* Update the tick offset */ OldTickOffset = InterlockedExchangeAdd(&KiTickOffset, -(LONG)Increment); /* If the debugger is enabled, check for break-in request */ if (KdDebuggerEnabled && KdPollBreakIn()) { /* Break-in requested! */ DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C); } /* Check for full tick */ if (OldTickOffset <= (LONG)Increment) { /* Update the system time */ CurrentTime.QuadPart = *(ULONGLONG*)&SharedUserData->SystemTime; CurrentTime.QuadPart += KeTimeAdjustment; KiWriteSystemTime(&SharedUserData->SystemTime, CurrentTime); /* Update the tick count */ CurrentTime.QuadPart = (*(ULONGLONG*)&KeTickCount) + 1; KiWriteSystemTime(&KeTickCount, CurrentTime); /* Update it in the shared user data */ KiWriteSystemTime(&SharedUserData->TickCount, CurrentTime); /* Check for expiration with the new tick count as well */ KiCheckForTimerExpiration(Prcb, TrapFrame, InterruptTime); /* Reset the tick offset */ KiTickOffset += KeMaximumIncrement; /* Update processor/thread runtime */ KeUpdateRunTime(TrapFrame, Irql); } else { /* Increase interrupt count only */ Prcb->InterruptCount++; } /* Disable interrupts and end the interrupt */ KiEndInterrupt(Irql, TrapFrame); }