mirror of
https://github.com/reactos/reactos.git
synced 2025-08-02 04:35:53 +00:00
- 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
This commit is contained in:
parent
d43585136b
commit
fe2d752e93
6 changed files with 27 additions and 269 deletions
|
@ -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();
|
||||
|
|
|
@ -38,7 +38,8 @@ _HalpClockInterrupt@0:
|
|||
jz Spurious
|
||||
|
||||
/* Do a tick */
|
||||
//jmp _KeUpdateSystemTime@0
|
||||
mov eax, 100000
|
||||
jmp _KeUpdateSystemTime@0
|
||||
|
||||
Spurious:
|
||||
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue