From fe2d752e934de6efe671d84f2412823b45fef785 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Thu, 24 Aug 2006 19:17:14 +0000 Subject: [PATCH] - Fix some bugs in clock.S - Enable clock.S versions of KeUpdateSystem/RunTime and export them properly. - Enable systimer.S to call into kernel's KeUpdateSystemTime. - Enable Hal's Clock Interrupt during Phase 1. - Remove most of the code that was still left in irq.c - Only one large problem remains now, which is the spurious firing of the clock interrupt before we're ready to handle it... I will try to fix this today. svn path=/trunk/; revision=23692 --- reactos/hal/halx86/generic/halinit.c | 7 +- reactos/hal/halx86/generic/systimer.S | 3 +- reactos/ntoskrnl/ke/clock.c | 196 +------------------------- reactos/ntoskrnl/ke/i386/clock.S | 30 ++-- reactos/ntoskrnl/ke/i386/irq.c | 56 -------- reactos/ntoskrnl/ntoskrnl.def | 4 +- 6 files changed, 27 insertions(+), 269 deletions(-) diff --git a/reactos/hal/halx86/generic/halinit.c b/reactos/hal/halx86/generic/halinit.c index 60af79fc294..c3c65a735cd 100644 --- a/reactos/hal/halx86/generic/halinit.c +++ b/reactos/hal/halx86/generic/halinit.c @@ -32,10 +32,6 @@ DriverEntry( return STATUS_SUCCESS; } -#define MAKEULONG(x, y) \ - (((((ULONG)(x))<<16) & 0xffff0000) | \ - ((ULONG)(y) & 0xffff)) - BOOLEAN STDCALL HalInitSystem (ULONG BootPhase, PLOADER_PARAMETER_BLOCK LoaderBlock) @@ -47,14 +43,13 @@ HalInitSystem (ULONG BootPhase, } else if (BootPhase == 1) { -#if 0 /* Enable the clock interrupt */ ((PKIPCR)KeGetPcr())->IDT[IRQ2VECTOR(0)].ExtendedOffset = (USHORT)(((ULONG_PTR)HalpClockInterrupt >> 16) & 0xFFFF); ((PKIPCR)KeGetPcr())->IDT[IRQ2VECTOR(0)].Offset = (USHORT)HalpClockInterrupt; HalEnableSystemInterrupt(IRQ2VECTOR(0), CLOCK2_LEVEL, Latched); -#endif + /* Initialize display and make the screen black */ HalInitializeDisplay ((PROS_LOADER_PARAMETER_BLOCK)LoaderBlock); HalpInitBusHandlers(); diff --git a/reactos/hal/halx86/generic/systimer.S b/reactos/hal/halx86/generic/systimer.S index f2dfebbfd27..170f9234809 100644 --- a/reactos/hal/halx86/generic/systimer.S +++ b/reactos/hal/halx86/generic/systimer.S @@ -38,7 +38,8 @@ _HalpClockInterrupt@0: jz Spurious /* Do a tick */ - //jmp _KeUpdateSystemTime@0 + mov eax, 100000 + jmp _KeUpdateSystemTime@0 Spurious: diff --git a/reactos/ntoskrnl/ke/clock.c b/reactos/ntoskrnl/ke/clock.c index f2eb528a618..924d2d2f25e 100644 --- a/reactos/ntoskrnl/ke/clock.c +++ b/reactos/ntoskrnl/ke/clock.c @@ -36,13 +36,9 @@ LARGE_INTEGER SystemBootTime = { 0 }; #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 @@ -82,7 +78,7 @@ KiInitializeSystemClock(VOID) { TIME_FIELDS TimeFields; - DPRINT("KiInitializeSystemClock()\n"); + DPRINT1("KiInitializeSystemClock()\n"); InitializeListHead(&KiTimerListHead); KeInitializeDpc(&KiExpireTimerDpc, (PKDEFERRED_ROUTINE)KiExpireTimers, 0); @@ -101,7 +97,7 @@ KiInitializeSystemClock(VOID) SharedUserData->SystemTime.High1Time = SystemBootTime.u.HighPart; KiClockSetupComplete = TRUE; - DPRINT("Finished KiInitializeSystemClock()\n"); + DPRINT1("Finished KiInitializeSystemClock()\n"); } VOID @@ -234,192 +230,6 @@ KeSetTimeUpdateNotifyRoutine( 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 */ diff --git a/reactos/ntoskrnl/ke/i386/clock.S b/reactos/ntoskrnl/ke/i386/clock.S index 6c7b7afefce..cb2a26b7564 100644 --- a/reactos/ntoskrnl/ke/i386/clock.S +++ b/reactos/ntoskrnl/ke/i386/clock.S @@ -17,12 +17,13 @@ .extern _KiTickOffset .extern _KeTickCount .extern _KeMaximumIncrement +.extern _KiExpireTimerDpc /* FUNCTIONS ******************************************************************/ -.globl _KeUpdateRunTime2@0 -.func KeUpdateRunTime2@0 -_KeUpdateRunTime2@0: +.globl _KeUpdateRunTime@4 +.func KeUpdateRunTime@4 +_KeUpdateRunTime@4: /* Get KPCR */ mov eax, [fs:KPCR_SELF] @@ -155,9 +156,9 @@ QuantumNotEmpty: ret 4 .endfunc -.globl _KeUpdateSystemTime2@0 -.func KeUpdateSystemTime2@0 -_KeUpdateSystemTime2@0: +.globl _KeUpdateSystemTime@0 +.func KeUpdateSystemTime@0 +_KeUpdateSystemTime@0: /* Get shared data in ECX */ mov ecx, USER_SHARED_DATA @@ -185,8 +186,8 @@ _KeUpdateSystemTime2@0: mov ebx, USER_SHARED_DATA /* Get system time */ - mov edi, [ebx+USER_SHARED_DATA_SYSTEM_TIME] - mov esi, [ebx+USER_SHARED_DATA_SYSTEM_TIME+4] + mov ecx, [ebx+USER_SHARED_DATA_SYSTEM_TIME] + mov edx, [ebx+USER_SHARED_DATA_SYSTEM_TIME+4] /* Add the increment and get the carry */ add ecx, _KeTimeAdjustment @@ -218,9 +219,16 @@ _KeUpdateSystemTime2@0: mov [USER_SHARED_DATA+USER_SHARED_DATA_TICK_COUNT], ecx mov [USER_SHARED_DATA+USER_SHARED_DATA_TICK_COUNT+4], edx + /* FIXME: HACK */ + mov [USER_SHARED_DATA], ecx + IncompleteTick: - /* Queue DPC to handle registered timers */ + /* FIXME: NASTY Queue DPC to handle registered timers */ + push 0 + push [esp+KTRAP_FRAME_EIP] + push offset _KiExpireTimerDpc + call _KeInsertQueueDpc@12 /* Check if this was a full tick */ cmp dword ptr _KiTickOffset, 0 @@ -231,8 +239,8 @@ IncompleteTick: add _KiTickOffset, eax /* Update system run time */ - push esp - call _KeUpdateRunTime@8 + push [esp] + call _KeUpdateRunTime@4 jmp Done IncompleteTick2: diff --git a/reactos/ntoskrnl/ke/i386/irq.c b/reactos/ntoskrnl/ke/i386/irq.c index 158cd165bd8..edda59b38f5 100644 --- a/reactos/ntoskrnl/ke/i386/irq.c +++ b/reactos/ntoskrnl/ke/i386/irq.c @@ -83,29 +83,6 @@ KeInitInterrupts (VOID) 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) /* @@ -115,23 +92,6 @@ 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++; /* @@ -145,23 +105,7 @@ KiInterruptDispatch (ULONG vector, PKIRQ_TRAPFRAME Trapframe) 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); } diff --git a/reactos/ntoskrnl/ntoskrnl.def b/reactos/ntoskrnl/ntoskrnl.def index 6cacb7a9fa8..f2873681262 100644 --- a/reactos/ntoskrnl/ntoskrnl.def +++ b/reactos/ntoskrnl/ntoskrnl.def @@ -647,8 +647,8 @@ KeSynchronizeExecution@12 KeTerminateThread@4 KeTickCount DATA @KeTryToAcquireGuardedMutex@4 -KeUpdateRunTime@8 -KeUpdateSystemTime@12 +KeUpdateRunTime@4 +KeUpdateSystemTime@0 KeUnstackDetachProcess@4 KeUserModeCallback@20 KeWaitForMultipleObjects@32