Author: ros-arm-bringup Date: Thu Jun 26 00:56:35 2008 New Revision: 34088
URL: http://svn.reactos.org/svn/reactos?rev=34088&view=rev Log: - 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!.
Modified: trunk/reactos/hal/halarm/generic/hal.c trunk/reactos/ntoskrnl/ke/arm/stubs.c trunk/reactos/ntoskrnl/ke/arm/trapc.c
Modified: trunk/reactos/hal/halarm/generic/hal.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halarm/generic/hal.c?re... ============================================================================== --- trunk/reactos/hal/halarm/generic/hal.c [iso-8859-1] (original) +++ trunk/reactos/hal/halarm/generic/hal.c [iso-8859-1] Thu Jun 26 00:56:35 2008 @@ -485,7 +485,9 @@ // // Call the kernel // - KeUpdateSystemTime(NULL, CLOCK2_LEVEL, HalpCurrentTimeIncrement); + KeUpdateSystemTime(KeGetCurrentThread()->TrapFrame, + CLOCK2_LEVEL, + HalpCurrentTimeIncrement);
// // We're done
Modified: trunk/reactos/ntoskrnl/ke/arm/stubs.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/arm/stubs.c?rev... ============================================================================== --- trunk/reactos/ntoskrnl/ke/arm/stubs.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/ke/arm/stubs.c [iso-8859-1] Thu Jun 26 00:56:35 2008 @@ -39,10 +39,6 @@ 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 @@ // // Update system runtime // - KeUpdateRunTime(NULL, CLOCK2_LEVEL); + KeUpdateRunTime(TrapFrame, CLOCK2_LEVEL); } else { @@ -159,6 +155,138 @@ 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); + } }
Modified: trunk/reactos/ntoskrnl/ke/arm/trapc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/arm/trapc.c?rev... ============================================================================== --- trunk/reactos/ntoskrnl/ke/arm/trapc.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/ke/arm/trapc.c [iso-8859-1] Thu Jun 26 00:56:35 2008 @@ -310,6 +310,7 @@ KIRQL OldIrql, Irql; ULONG InterruptCause, InterruptMask; PKPCR Pcr; + PKTRAP_FRAME OldTrapFrame;
// // Increment interrupt count @@ -339,12 +340,18 @@ // 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 @@ //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");
//