mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-02 19:26:32 +00:00
- Save and restore the trap frame for the current thread when we take an interrupt, so that ISRs can read it.
- We use this in the clock ISR, that can now actually send the trap frame to KeUpdateSystemTime. - Implement KeUpdateRunTime to handle time accounting and DPC rescheduling as well as Quantum End. - Ignore quantum end for now. - We now have a working timebase, and we're back to our earlier checkpoint around CmInitSystem1!. svn path=/trunk/; revision=34088
This commit is contained in:
@@ -485,7 +485,9 @@ HalpClockInterrupt(VOID)
|
||||
//
|
||||
// Call the kernel
|
||||
//
|
||||
KeUpdateSystemTime(NULL, CLOCK2_LEVEL, HalpCurrentTimeIncrement);
|
||||
KeUpdateSystemTime(KeGetCurrentThread()->TrapFrame,
|
||||
CLOCK2_LEVEL,
|
||||
HalpCurrentTimeIncrement);
|
||||
|
||||
//
|
||||
// We're done
|
||||
|
||||
@@ -39,10 +39,6 @@ KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame,
|
||||
PKPRCB Prcb = KeGetPcr()->Prcb;
|
||||
ULARGE_INTEGER SystemTime, InterruptTime;
|
||||
ULONG Hand;
|
||||
DPRINT1("TIMEBASE: %I64d %I64d %I64d\n",
|
||||
*(PLARGE_INTEGER)&SharedUserData->InterruptTime,
|
||||
*(PLARGE_INTEGER)&SharedUserData->SystemTime,
|
||||
*(PLARGE_INTEGER)&SharedUserData->TickCount);
|
||||
|
||||
//
|
||||
// Do nothing if this tick is being skipped
|
||||
@@ -143,7 +139,7 @@ KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame,
|
||||
//
|
||||
// Update system runtime
|
||||
//
|
||||
KeUpdateRunTime(NULL, CLOCK2_LEVEL);
|
||||
KeUpdateRunTime(TrapFrame, CLOCK2_LEVEL);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -159,6 +155,138 @@ NTAPI
|
||||
KeUpdateRunTime(IN PKTRAP_FRAME TrapFrame,
|
||||
IN KIRQL Irql)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
while (TRUE);
|
||||
PKTHREAD Thread = KeGetCurrentThread();
|
||||
PKPROCESS Process = Thread->ApcState.Process;
|
||||
PKPRCB Prcb = KeGetCurrentPrcb();
|
||||
|
||||
//
|
||||
// Do nothing if this tick is being skipped
|
||||
//
|
||||
if (Prcb->SkipTick)
|
||||
{
|
||||
//
|
||||
// Handle it next time
|
||||
//
|
||||
Prcb->SkipTick = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Increase interrupt count
|
||||
//
|
||||
Prcb->InterruptCount++;
|
||||
|
||||
//
|
||||
// Check if we came from user mode
|
||||
//
|
||||
if (0) //(TrapFrame->PreviousMode != KernelMode)
|
||||
{
|
||||
//
|
||||
// Increase process user time
|
||||
//
|
||||
InterlockedIncrement((PLONG)&Process->UserTime);
|
||||
Prcb->UserTime++;
|
||||
Thread->UserTime++;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// See if we were in an ISR
|
||||
//
|
||||
if (TrapFrame->OldIrql > DISPATCH_LEVEL)
|
||||
{
|
||||
//
|
||||
// Handle that
|
||||
//
|
||||
Prcb->InterruptTime++;
|
||||
}
|
||||
else if ((TrapFrame->OldIrql < DISPATCH_LEVEL) ||
|
||||
!(Prcb->DpcRoutineActive))
|
||||
{
|
||||
//
|
||||
// Handle being in kernel mode
|
||||
//
|
||||
Thread->KernelTime++;
|
||||
InterlockedIncrement((PLONG)&Process->KernelTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Handle being in a DPC
|
||||
//
|
||||
Prcb->DpcTime++;
|
||||
|
||||
//
|
||||
// FIXME: Handle DPC checks
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Update DPC rates
|
||||
//
|
||||
Prcb->DpcRequestRate = ((Prcb->DpcData[0].DpcCount - Prcb->DpcLastCount) +
|
||||
Prcb->DpcRequestRate) >> 1;
|
||||
Prcb->DpcLastCount = Prcb->DpcData[0].DpcCount;
|
||||
|
||||
//
|
||||
// Check if the queue is large enough
|
||||
//
|
||||
if ((Prcb->DpcData[0].DpcQueueDepth) && !(Prcb->DpcRoutineActive))
|
||||
{
|
||||
//
|
||||
// Request a DPC
|
||||
//
|
||||
Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
|
||||
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
||||
|
||||
//
|
||||
// Fix the maximum queue depth
|
||||
//
|
||||
if ((Prcb->DpcRequestRate < KiIdealDpcRate) &&
|
||||
(Prcb->MaximumDpcQueueDepth > 1))
|
||||
{
|
||||
//
|
||||
// Make it smaller
|
||||
//
|
||||
Prcb->MaximumDpcQueueDepth--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Check if we've reached the adjustment limit
|
||||
//
|
||||
if (!(--Prcb->AdjustDpcThreshold))
|
||||
{
|
||||
//
|
||||
// Reset it, and check the queue maximum
|
||||
//
|
||||
Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
|
||||
if (KiMaximumDpcQueueDepth != Prcb->MaximumDpcQueueDepth)
|
||||
{
|
||||
//
|
||||
// Increase it
|
||||
//
|
||||
Prcb->MaximumDpcQueueDepth++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Decrement the thread quantum
|
||||
//
|
||||
Thread->Quantum -= CLOCK_QUANTUM_DECREMENT;
|
||||
|
||||
//
|
||||
// Check if the time expired
|
||||
//
|
||||
if ((Thread->Quantum <= 0) && (Thread != Prcb->IdleThread))
|
||||
{
|
||||
//
|
||||
// Schedule a quantum end
|
||||
//
|
||||
Prcb->QuantumEnd = 1;
|
||||
//HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -310,6 +310,7 @@ KiInterruptHandler(IN PKTRAP_FRAME TrapFrame,
|
||||
KIRQL OldIrql, Irql;
|
||||
ULONG InterruptCause, InterruptMask;
|
||||
PKPCR Pcr;
|
||||
PKTRAP_FRAME OldTrapFrame;
|
||||
|
||||
//
|
||||
// Increment interrupt count
|
||||
@@ -339,12 +340,18 @@ KiInterruptHandler(IN PKTRAP_FRAME TrapFrame,
|
||||
// Raise to the new IRQL
|
||||
//
|
||||
KfRaiseIrql(Irql);
|
||||
|
||||
//
|
||||
// The clock ISR wants the trap frame as a parameter
|
||||
//
|
||||
OldTrapFrame = KeGetCurrentThread()->TrapFrame;
|
||||
KeGetCurrentThread()->TrapFrame = TrapFrame;
|
||||
|
||||
//
|
||||
// Check if this interrupt is at DISPATCH or higher
|
||||
//
|
||||
if (Irql > DISPATCH_LEVEL)
|
||||
{
|
||||
{
|
||||
//
|
||||
// FIXME: Switch to interrupt stack
|
||||
//
|
||||
@@ -358,11 +365,13 @@ KiInterruptHandler(IN PKTRAP_FRAME TrapFrame,
|
||||
//DPRINT1("[DPC/APC]\n");
|
||||
HalClearSoftwareInterrupt(Irql);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Call the registered interrupt routine
|
||||
//
|
||||
Pcr->InterruptRoutine[Irql]();
|
||||
ASSERT(KeGetCurrentThread()->TrapFrame == TrapFrame);
|
||||
KeGetCurrentThread()->TrapFrame = OldTrapFrame;
|
||||
// DPRINT1("[ISR RETURN]\n");
|
||||
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user