#endif
CHAR KiTimerSystemAuditing = 0;
-static KDPC KiExpireTimerDpc;
+KDPC KiExpireTimerDpc;
BOOLEAN KiClockSetupComplete = FALSE;
-extern ULONG KiMaximumDpcQueueDepth;
-extern ULONG KiMinimumDpcRate;
-extern ULONG KiAdjustDpcThreshold;
-extern ULONG KiIdealDpcRate;
/*
* Number of timer interrupts since initialisation
{
TIME_FIELDS TimeFields;
- DPRINT("KiInitializeSystemClock()\n");
+ DPRINT1("KiInitializeSystemClock()\n");
InitializeListHead(&KiTimerListHead);
KeInitializeDpc(&KiExpireTimerDpc, (PKDEFERRED_ROUTINE)KiExpireTimers, 0);
SharedUserData->SystemTime.High1Time = SystemBootTime.u.HighPart;
KiClockSetupComplete = TRUE;
- DPRINT("Finished KiInitializeSystemClock()\n");
+ DPRINT1("Finished KiInitializeSystemClock()\n");
}
VOID
UNIMPLEMENTED;
}
-/*
- * NOTE: On Windows this function takes exactly one parameter and EBP is
- * guaranteed to point to KTRAP_FRAME. The function is used only
- * by HAL, so there's no point in keeping that prototype.
- *
- * @implemented
- */
-VOID
-STDCALL
-KeUpdateRunTime(IN PKTRAP_FRAME TrapFrame,
- IN KIRQL Irql)
-{
- PKPRCB Prcb = KeGetCurrentPrcb();
- PKTHREAD CurrentThread = Prcb->CurrentThread;
- PKPROCESS CurrentProcess = CurrentThread->ApcState.Process;
-
- /* Increase interrupt count */
- Prcb->InterruptCount++;
-
- /* Check if we came from user mode */
- if ((TrapFrame->EFlags & EFLAGS_V86_MASK) ||
- (TrapFrame->SegCs & MODE_MASK))
- {
- /* Update user times */
- CurrentThread->UserTime++;
- InterlockedIncrement((PLONG)&CurrentProcess->UserTime);
- Prcb->UserTime++;
- }
- else
- {
- /* Update CPU kernel time in all cases */
- Prcb->KernelTime++;
-
- /* Check IRQ */
- if (Irql > DISPATCH_LEVEL)
- {
- /* This was an interrupt */
- Prcb->InterruptTime++;
- }
- else if ((Irql < DISPATCH_LEVEL) || !(Prcb->DpcRoutineActive))
- {
- /* This was normal kernel time */
- CurrentThread->KernelTime++;
- InterlockedIncrement((PLONG)&CurrentProcess->KernelTime);
- }
- else if (Irql == DISPATCH_LEVEL)
- {
- /* This was DPC time */
- Prcb->DpcTime++;
- }
- }
-
- /* Set the last DPC Count and request rate */
- Prcb->DpcLastCount = Prcb->DpcData[0].DpcCount;
- Prcb->DpcRequestRate = ((Prcb->DpcData[0].DpcCount - Prcb->DpcLastCount) +
- Prcb->DpcRequestRate) / 2;
-
- /* Check if we should request a DPC */
- if ((Prcb->DpcData[0].DpcQueueDepth) &&
- !(Prcb->DpcRoutineActive) &&
- !(Prcb->DpcInterruptRequested))
- {
- /* Request one */
- HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
-
- /* Update the depth if needed */
- if ((Prcb->DpcRequestRate < KiIdealDpcRate) &&
- (Prcb->MaximumDpcQueueDepth > 1))
- {
- /* Decrease the maximum depth by one */
- Prcb->MaximumDpcQueueDepth--;
- }
- }
- else
- {
- /* Decrease the adjustment threshold */
- if (!(--Prcb->AdjustDpcThreshold))
- {
- /* We've hit 0, reset it */
- Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
-
- /* Check if we've hit queue maximum */
- if (KiMaximumDpcQueueDepth != Prcb->MaximumDpcQueueDepth)
- {
- /* Increase maximum by one */
- Prcb->MaximumDpcQueueDepth++;
- }
- }
- }
-
- /*
- * If we're at end of quantum request software interrupt. The rest
- * is handled in KiDispatchInterrupt.
- *
- * NOTE: If one stays at DISPATCH_LEVEL for a long time the DPC routine
- * which checks for quantum end will not be executed and decrementing
- * the quantum here can result in overflow. This is not a problem since
- * we don't care about the quantum value anymore after the QuantumEnd
- * flag is set.
- */
- if (((CurrentThread->Quantum -= 3) <= 0) &&
- (Prcb->IdleThread != CurrentThread))
- {
- Prcb->QuantumEnd = TRUE;
- HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
- }
-}
-
-
-/*
- * NOTE: On Windows this function takes exactly zero parameters and EBP is
- * guaranteed to point to KTRAP_FRAME. Also [esp+0] contains an IRQL.
- * The function is used only by HAL, so there's no point in keeping
- * that prototype.
- *
- * @implemented
- */
-VOID
-STDCALL
-KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame,
- IN KIRQL Irql,
- IN ULONG Increment)
-{
- LONG OldOffset;
- LARGE_INTEGER Time;
- ASSERT(KeGetCurrentIrql() == PROFILE_LEVEL);
-
- /* Update interrupt time */
- Time.LowPart = SharedUserData->InterruptTime.LowPart;
- Time.HighPart = SharedUserData->InterruptTime.High1Time;
- Time.QuadPart += Increment;
- SharedUserData->InterruptTime.High2Time = Time.u.HighPart;
- SharedUserData->InterruptTime.LowPart = Time.u.LowPart;
- SharedUserData->InterruptTime.High1Time = Time.u.HighPart;
-
- /* Increase the tick offset */
- KiTickOffset -= Increment;
- OldOffset = KiTickOffset;
-
- /* Check if this isn't a tick yet */
- if (KiTickOffset > 0)
- {
- /* Expire timers */
- KeInsertQueueDpc(&KiExpireTimerDpc, (PVOID)TrapFrame->Eip, 0);
- }
- else
- {
- /* Setup time structure for system time */
- Time.LowPart = SharedUserData->SystemTime.LowPart;
- Time.HighPart = SharedUserData->SystemTime.High1Time;
- Time.QuadPart += KeTimeAdjustment;
- SharedUserData->SystemTime.High2Time = Time.HighPart;
- SharedUserData->SystemTime.LowPart = Time.LowPart;
- SharedUserData->SystemTime.High1Time = Time.HighPart;
-
- /* Setup time structure for tick time */
- Time.LowPart = KeTickCount.LowPart;
- Time.HighPart = KeTickCount.High1Time;
- Time.QuadPart += 1;
- KeTickCount.High2Time = Time.HighPart;
- KeTickCount.LowPart = Time.LowPart;
- KeTickCount.High1Time = Time.HighPart;
- SharedUserData->TickCount.High2Time = Time.HighPart;
- SharedUserData->TickCount.LowPart = Time.LowPart;
- SharedUserData->TickCount.High1Time = Time.HighPart;
-
- /* Update tick count in shared user data as well */
- SharedUserData->TickCountLowDeprecated++;
-
- /* Queue a DPC that will expire timers */
- KeInsertQueueDpc(&KiExpireTimerDpc, (PVOID)TrapFrame->Eip, 0);
- }
-
- /* Update process and thread times */
- if (OldOffset <= 0)
- {
- /* This was a tick, calculate the next one */
- KiTickOffset += KeMaximumIncrement;
- KeUpdateRunTime(TrapFrame, Irql);
- }
-
- /* Return from the interrupt */
- Ke386DisableInterrupts();
- HalEndSystemInterrupt(Irql, 0);
-}
-
/*
* @implemented
*/
.extern _KiTickOffset\r
.extern _KeTickCount\r
.extern _KeMaximumIncrement\r
+.extern _KiExpireTimerDpc\r
\r
/* FUNCTIONS ******************************************************************/\r
\r
-.globl _KeUpdateRunTime2@0\r
-.func KeUpdateRunTime2@0\r
-_KeUpdateRunTime2@0:\r
+.globl _KeUpdateRunTime@4\r
+.func KeUpdateRunTime@4\r
+_KeUpdateRunTime@4:\r
\r
/* Get KPCR */\r
mov eax, [fs:KPCR_SELF]\r
ret 4\r
.endfunc\r
\r
-.globl _KeUpdateSystemTime2@0\r
-.func KeUpdateSystemTime2@0\r
-_KeUpdateSystemTime2@0:\r
+.globl _KeUpdateSystemTime@0\r
+.func KeUpdateSystemTime@0\r
+_KeUpdateSystemTime@0:\r
\r
/* Get shared data in ECX */\r
mov ecx, USER_SHARED_DATA\r
mov ebx, USER_SHARED_DATA\r
\r
/* Get system time */\r
- mov edi, [ebx+USER_SHARED_DATA_SYSTEM_TIME]\r
- mov esi, [ebx+USER_SHARED_DATA_SYSTEM_TIME+4]\r
+ mov ecx, [ebx+USER_SHARED_DATA_SYSTEM_TIME]\r
+ mov edx, [ebx+USER_SHARED_DATA_SYSTEM_TIME+4]\r
\r
/* Add the increment and get the carry */\r
add ecx, _KeTimeAdjustment\r
mov [USER_SHARED_DATA+USER_SHARED_DATA_TICK_COUNT], ecx\r
mov [USER_SHARED_DATA+USER_SHARED_DATA_TICK_COUNT+4], edx\r
\r
+ /* FIXME: HACK */\r
+ mov [USER_SHARED_DATA], ecx\r
+\r
IncompleteTick:\r
\r
- /* Queue DPC to handle registered timers */\r
+ /* FIXME: NASTY Queue DPC to handle registered timers */\r
+ push 0\r
+ push [esp+KTRAP_FRAME_EIP]\r
+ push offset _KiExpireTimerDpc\r
+ call _KeInsertQueueDpc@12\r
\r
/* Check if this was a full tick */\r
cmp dword ptr _KiTickOffset, 0\r
add _KiTickOffset, eax\r
\r
/* Update system run time */\r
- push esp\r
- call _KeUpdateRunTime@8\r
+ push [esp]\r
+ call _KeUpdateRunTime@4\r
jmp Done\r
\r
IncompleteTick2:\r
I486_INTERRUPT_GATE;
}
-STATIC VOID
-KeIRQTrapFrameToTrapFrame(PKIRQ_TRAPFRAME IrqTrapFrame,
- PKTRAP_FRAME TrapFrame)
-{
- TrapFrame->SegGs = (USHORT)IrqTrapFrame->Gs;
- TrapFrame->SegFs = (USHORT)IrqTrapFrame->Fs;
- TrapFrame->SegEs = (USHORT)IrqTrapFrame->Es;
- TrapFrame->SegDs = (USHORT)IrqTrapFrame->Ds;
- TrapFrame->Eax = IrqTrapFrame->Eax;
- TrapFrame->Ecx = IrqTrapFrame->Ecx;
- TrapFrame->Edx = IrqTrapFrame->Edx;
- TrapFrame->Ebx = IrqTrapFrame->Ebx;
- TrapFrame->HardwareEsp = IrqTrapFrame->Esp;
- TrapFrame->Ebp = IrqTrapFrame->Ebp;
- TrapFrame->Esi = IrqTrapFrame->Esi;
- TrapFrame->Edi = IrqTrapFrame->Edi;
- TrapFrame->Eip = IrqTrapFrame->Eip;
- TrapFrame->SegCs = IrqTrapFrame->Cs;
- TrapFrame->EFlags = IrqTrapFrame->Eflags;
-}
-
-extern BOOLEAN KiClockSetupComplete;
-
VOID
KiInterruptDispatch (ULONG vector, PKIRQ_TRAPFRAME Trapframe)
/*
*/
{
KIRQL old_level;
- KTRAP_FRAME KernelTrapFrame;
- ASSERT(vector == 0x30);
-#if 0
- PULONG Frame;
- DPRINT1("Received Interrupt: %lx\n", vector);
- DPRINT1("My trap frame: %p\n", Trapframe);
- DPRINT1("Stack trace\n");
- __asm__("mov %%ebp, %0" : "=r" (Frame) : );
- DPRINT1("Stack trace: %p %p %p %p\n", Frame, *Frame, Frame[1], *(PULONG)Frame[1]);
- DPRINT1("Clock setup: %lx\n", KiClockSetupComplete);
- if (KiClockSetupComplete) while(TRUE);
-#endif
-
- /*
- * At this point we have interrupts disabled, nothing has been done to
- * the PIC.
- */
KeGetCurrentPrcb()->InterruptCount++;
/*
return;
}
-
- /*
- * Enable interrupts
- * NOTE: Only higher priority interrupts will get through
- */
Ke386EnableInterrupts();
-
- //DPRINT1("Tick\n");
- if (KiClockSetupComplete)
- {
- KeIRQTrapFrameToTrapFrame(Trapframe, &KernelTrapFrame);
- return KeUpdateSystemTime(&KernelTrapFrame, old_level, 100000);
- }
-
- /*
- * End the system interrupt.
- */
Ke386DisableInterrupts();
HalEndSystemInterrupt (old_level, 0);
}