From 241449fc0e70195fa7bddd1ab502983e62388257 Mon Sep 17 00:00:00 2001 From: ReactOS Portable Systems Group Date: Thu, 26 Jun 2008 05:56:35 +0000 Subject: [PATCH] - 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 --- reactos/hal/halarm/generic/hal.c | 4 +- reactos/ntoskrnl/ke/arm/stubs.c | 142 +++++++++++++++++++++++++++++-- reactos/ntoskrnl/ke/arm/trapc.c | 13 ++- 3 files changed, 149 insertions(+), 10 deletions(-) diff --git a/reactos/hal/halarm/generic/hal.c b/reactos/hal/halarm/generic/hal.c index 88b6f7233de..928f4aaa918 100644 --- a/reactos/hal/halarm/generic/hal.c +++ b/reactos/hal/halarm/generic/hal.c @@ -485,7 +485,9 @@ HalpClockInterrupt(VOID) // // Call the kernel // - KeUpdateSystemTime(NULL, CLOCK2_LEVEL, HalpCurrentTimeIncrement); + KeUpdateSystemTime(KeGetCurrentThread()->TrapFrame, + CLOCK2_LEVEL, + HalpCurrentTimeIncrement); // // We're done diff --git a/reactos/ntoskrnl/ke/arm/stubs.c b/reactos/ntoskrnl/ke/arm/stubs.c index aa7147b66fd..5b944538de9 100644 --- a/reactos/ntoskrnl/ke/arm/stubs.c +++ b/reactos/ntoskrnl/ke/arm/stubs.c @@ -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); + } } diff --git a/reactos/ntoskrnl/ke/arm/trapc.c b/reactos/ntoskrnl/ke/arm/trapc.c index 1e3eadd096c..0afe44336c0 100644 --- a/reactos/ntoskrnl/ke/arm/trapc.c +++ b/reactos/ntoskrnl/ke/arm/trapc.c @@ -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"); //