Author: sir_richard
Date: Tue Jan 19 07:16:47 2010
New Revision: 45140
URL:
http://svn.reactos.org/svn/reactos?rev=45140&view=rev
Log:
[NTOS]: Implement KeUpdateSystemTime and KeUpdateRunTime in C instead of ASM. Based off
eVb's ARM implementation, with multiple bugs fixed (incorrect update of system
counters, incorrect expiration of timers, remove non-used debug features, use locks when
needed).
[NTOS]: Implement KiComputeTimerTableIndex in C instead of ASM. Based off eVb's ARM
implementation, bugfixed to do correct math instead.
As a side effect, this should fix timers on ARM ;-)
Added:
trunk/reactos/ntoskrnl/ke/time.c
- copied, changed from r45139, trunk/reactos/ntoskrnl/ke/arm/time.c
Removed:
trunk/reactos/ntoskrnl/ke/arm/time.c
trunk/reactos/ntoskrnl/ke/i386/systimer.S
Modified:
trunk/reactos/ntoskrnl/include/internal/ke.h
trunk/reactos/ntoskrnl/include/internal/ke_x.h
trunk/reactos/ntoskrnl/ke/i386/trap.s
trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild
Modified: trunk/reactos/ntoskrnl/include/internal/ke.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/ke.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/ke.h [iso-8859-1] Tue Jan 19 07:16:47 2010
@@ -730,12 +730,6 @@
ULONG
NTAPI
-KiComputeTimerTableIndex(
- IN LONGLONG TimeValue
-);
-
-ULONG
-NTAPI
KeSetProcess(
struct _KPROCESS* Process,
KPRIORITY Increment,
Modified: trunk/reactos/ntoskrnl/include/internal/ke_x.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/ke_x.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/ke_x.h [iso-8859-1] Tue Jan 19 07:16:47 2010
@@ -972,6 +972,13 @@
return STATUS_WAIT_0;
}
+ULONG
+FORCEINLINE
+KiComputeTimerTableIndex(IN ULONGLONG DueTime)
+{
+ return (DueTime / KeMaximumIncrement) & (TIMER_TABLE_SIZE - 1);
+}
+
//
// Called from KiCompleteTimer, KiInsertTreeTimer, KeSetSystemTime
// to remove timer entries
Removed: trunk/reactos/ntoskrnl/ke/arm/time.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/arm/time.c?rev…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/arm/time.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ke/arm/time.c (removed)
@@ -1,322 +1,0 @@
-/*
- * PROJECT: ReactOS Kernel
- * LICENSE: BSD - See COPYING.ARM in the top level directory
- * FILE: ntoskrnl/ke/arm/time.c
- * PURPOSE: Implements timebase functionality on ARM processors
- * PROGRAMMERS: ReactOS Portable Systems Group
- */
-
-/* INCLUDES *******************************************************************/
-
-#include <ntoskrnl.h>
-#define NDEBUG
-#include <debug.h>
-
-/* GLOBALS ********************************************************************/
-
-LONG KiTickOffset;
-ULONG KeTimeAdjustment;
-
-/* FUNCTIONS ******************************************************************/
-
-ULONG
-KiComputeTimerTableIndex(IN LONGLONG DueTime)
-{
- ULONG Hand;
-
- //
- // Compute the timer table index
- //
- Hand = (DueTime / KeMaximumIncrement);
- Hand %= TIMER_TABLE_SIZE;
- return Hand;
-}
-
-VOID
-NTAPI
-KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame,
- IN KIRQL Irql,
- IN ULONG Increment)
-{
- PKPRCB Prcb = KeGetPcr()->Prcb;
- ULARGE_INTEGER SystemTime, InterruptTime;
- ULONG Hand;
-
- //
- // Do nothing if this tick is being skipped
- //
- if (Prcb->SkipTick)
- {
- //
- // Handle it next time
- //
- Prcb->SkipTick = FALSE;
- return;
- }
-
- //
- // Add the increment time to the shared data
- //
- InterruptTime.HighPart = SharedUserData->InterruptTime.High1Time;
- InterruptTime.LowPart = SharedUserData->InterruptTime.LowPart;
- InterruptTime.QuadPart += Increment;
- SharedUserData->InterruptTime.High1Time = InterruptTime.HighPart;
- SharedUserData->InterruptTime.LowPart = InterruptTime.LowPart;
- SharedUserData->InterruptTime.High2Time = InterruptTime.HighPart;
-
- //
- // Update tick count
- //
- KiTickOffset -= Increment;
-
- //
- // Check for incomplete tick
- //
- if (KiTickOffset <= 0)
- {
- //
- // Update the system time
- //
- SystemTime.HighPart = SharedUserData->SystemTime.High1Time;
- SystemTime.LowPart = SharedUserData->SystemTime.LowPart;
- SystemTime.QuadPart += KeTimeAdjustment;
- SharedUserData->SystemTime.High1Time = SystemTime.HighPart;
- SharedUserData->SystemTime.LowPart = SystemTime.LowPart;
- SharedUserData->SystemTime.High2Time = SystemTime.HighPart;
-
- //
- // Update the tick count
- //
- SystemTime.HighPart = KeTickCount.High1Time;
- SystemTime.LowPart = KeTickCount.LowPart;
- SystemTime.QuadPart += 1;
- KeTickCount.High1Time = SystemTime.HighPart;
- KeTickCount.LowPart = SystemTime.LowPart;
- KeTickCount.High2Time = SystemTime.HighPart;
-
- //
- // Update it in the shared user data
- //
- SharedUserData->TickCount.High1Time = SystemTime.HighPart;
- SharedUserData->TickCount.LowPart = SystemTime.LowPart;
- SharedUserData->TickCount.High2Time = SystemTime.HighPart;
- }
-
- //
- // Check for timer expiration
- //
- Hand = KeTickCount.LowPart % TIMER_TABLE_SIZE;
- if (KiTimerTableListHead[Hand].Time.QuadPart <= InterruptTime.QuadPart)
- {
- //
- // Check if we are already doing expiration
- //
- if (!Prcb->TimerRequest)
- {
- //
- // Request a DPC to handle this
- //
- Prcb->TimerRequest = TrapFrame->SvcSp;
- Prcb->TimerHand = Hand;
- HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
- }
- }
-
- //
- // Check if we should request a debugger break
- //
- if (KdDebuggerEnabled)
- {
- //
- // Check if we should break
- //
- if (KdPollBreakIn()) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
- }
-
- //
- // Check if this was a full tick
- //
- if (KiTickOffset <= 0)
- {
- //
- // Updare the tick offset
- //
- KiTickOffset += KeMaximumIncrement;
-
- //
- // Update system runtime
- //
- KeUpdateRunTime(TrapFrame, CLOCK2_LEVEL);
- }
- else
- {
- //
- // Increase interrupt count and exit
- //
- Prcb->InterruptCount++;
- }
-}
-
-VOID
-NTAPI
-KeUpdateRunTime(IN PKTRAP_FRAME TrapFrame,
- IN KIRQL Irql)
-{
- 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 (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++;
-
- //
- // Update Debug DPC time
- //
- Prcb->DebugDpcTime++;
-
- //
- // Check if we've timed out
- //
- if (Prcb->DebugDpcTime >= KiDPCTimeout)
- {
- //
- // Print a message
- //
- DbgPrint("\n*** DPC routine > 1 sec --- This is not a break in
"
- "KeUpdateSystemTime\n");
-
- //
- // Break if a debugger is attached
- //
- if (KdDebuggerEnabled) DbgBreakPoint();
-
- //
- // Restore the debug DPC time
- //
- Prcb->DebugDpcTime = 0;
- }
- }
- }
-
- //
- // 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);
- }
-}
Removed: trunk/reactos/ntoskrnl/ke/i386/systimer.S
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/systimer.…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/systimer.S [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ke/i386/systimer.S (removed)
@@ -1,383 +1,0 @@
-/*
- * FILE: ntoskrnl/ke/i386/clock.S
- * COPYRIGHT: See COPYING in the top level directory
- * PURPOSE: System Clock Management
- * PROGRAMMER: Alex Ionescu (alex(a)relsoft.net)
- */
-
-/* INCLUDES ******************************************************************/
-
-#include <asm.h>
-#include <internal/i386/asmmacro.S>
-.intel_syntax noprefix
-
-/* GLOBALS *******************************************************************/
-
-_DpcTimeoutMsg:
- .asciz "\n*** DPC routine > 1 sec --- This is not a break in
KeUpdateSystemTime\n"
-
-/* FUNCTIONS ******************************************************************/
-
-.globl _KiComputeTimerTableIndex@8
-.func KiComputeTimerTableIndex@8
-_KiComputeTimerTableIndex@8:
-
- /* Save registers */
- push ebx
-
- /* Make the first multiplication */
- mov eax, [esp+8]
- mul dword ptr [_KiTimeIncrementReciprocal+4]
- mov ebx, eax
- mov ecx, edx
-
- /* Make the second multiplication */
- mov eax, [esp+12]
- mul dword ptr [_KiTimeIncrementReciprocal]
- add ebx, eax
- adc ecx, edx
-
- /* Multiply by the reciprocal */
- mov eax, [esp+8]
- mul dword ptr [_KiTimeIncrementReciprocal]
- mov eax, [esp+12]
- push edx
- mul dword ptr [_KiTimeIncrementReciprocal+4]
- pop edx
- add edx, ebx
- adc eax, ecx
-
- /* Shift the result and generate the index */
- mov cl, [_KiTimeIncrementShiftCount]
- shr eax, cl
- and eax, TIMER_TABLE_SIZE - 1
-
- /* Return */
- pop ebx
- ret 8
-.endfunc
-
-.globl _KeUpdateRunTime@8
-.func KeUpdateRunTime@8
-_KeUpdateRunTime@8:
-
- /* Get KPCR */
- mov eax, [fs:KPCR_SELF]
-
- /* Check if this tick is getting skipped */
- cmp byte ptr [eax+KPCR_PRCB_SKIP_TICK], 0
- jnz SkipTick
-
- /* Save EBX */
- push ebx
-
- /* Increase interrupt count */
- inc dword ptr [eax+KPCR_PRCB_INTERRUPT_COUNT]
-
- /* Get the current thread and process */
- mov ebx, [eax+KPCR_CURRENT_THREAD]
- mov ecx, [ebx+KTHREAD_APCSTATE_PROCESS]
-
- /* Check if this was V86 or user mode */
- test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
- jnz NotKern
- test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
- jnz NotKern
-
- /* Increase kernel time */
- inc dword ptr [eax+KPCR_PRCB_KERNEL_TIME]
-
- /* Check if IRQL was DISPATCH_LEVEL */
- cmp byte ptr [esp+8], DISPATCH_LEVEL
- jb BelowDispatch
- ja AboveDispatch
-
- /* Check if the DPC routine is active */
- cmp byte ptr fs:[KPCR_PRCB_DPC_ROUTINE_ACTIVE], 0
- jz BelowDispatch
-
- /* At dispatch, increase DPC time */
- inc dword ptr [eax+KPCR_PRCB_DPC_TIME]
-#if DBG
- /* Update the DPC time */
- inc dword ptr [eax+KPCR_PRCB_DEBUG_DPC_TIME]
-
- /* Check if we've timed out */
- mov edx, _KiDPCTimeout
- cmp dword ptr [eax+KPCR_PRCB_DEBUG_DPC_TIME], edx
- jc AfterSet
-
- /* We did, print out a message */
- push offset _DpcTimeoutMsg
- call _DbgPrint
- add esp, 4
-
- /* Check if the debugger is enabled */
- cmp byte ptr __KdDebuggerEnabled, 0
- jz ResetDpcTime
-
- /* Breakpoint */
- call _DbgBreakPoint@0
-
-ResetDpcTime:
- /* Restore state */
- mov eax, PCR[KPCR_SELF]
- mov dword ptr [eax+KPCR_PRCB_DEBUG_DPC_TIME], 0
-#endif
- jmp AfterSet
-
-AboveDispatch:
- /* Update interrupt time */
- inc dword ptr [eax+KPCR_PRCB_INTERRUPT_TIME]
- jmp AfterSet
-
-BelowDispatch:
- /* Update kernel time */
- inc dword ptr [ebx+KTHREAD_KERNEL_TIME]
- jmp AfterSet
-
-NotKern:
- /* Update user time */
- inc dword ptr [eax+KPCR_PRCB_USER_TIME]
- inc dword ptr [ebx+KTHREAD_USER_TIME]
-
-AfterSet:
- /* Get the DPC Count and last count, and set the ne wone */
- mov ecx, [eax+KPCR_PRCB_DPC_COUNT]
- mov edx, [eax+KPCR_PRCB_DPC_LAST_COUNT]
- mov [eax+KPCR_PRCB_DPC_LAST_COUNT], ecx
-
- /* Substract counts and add request rate, divide by two to get average */
- sub ecx, edx
- add ecx, [eax+KPCR_PRCB_DPC_REQUEST_RATE]
- shr ecx, 1
-
- /* Set this as the new request rate */
- mov [eax+KPCR_PRCB_DPC_REQUEST_RATE], ecx
-
- /* Check for depth > 0, DPCs to be inactive, and no other pending request */
- cmp dword ptr [eax+KPCR_PRCB_DPC_QUEUE_DEPTH], 0
- je DontRequest
- cmp byte ptr [eax+KPCR_PRCB_DPC_ROUTINE_ACTIVE], 0
- jnz DontRequest
- cmp byte ptr [eax+KPCR_PRCB_DPC_INTERRUPT_REQUESTED], 0
- jnz DontRequest
-
- /* Request a DPC */
- mov ecx, DISPATCH_LEVEL
- call @HalRequestSoftwareInterrupt@4
-
- /* Restore PCR address */
- mov eax, [fs:KPCR_SELF]
-
- /* Get the DPC request rate and threshold adjust, and set it */
- mov ecx, [eax+KPCR_PRCB_DPC_REQUEST_RATE]
- mov edx, _KiAdjustDpcThreshold
- mov [eax+KPCR_PRCB_ADJUST_DPC_THRESHOLD], edx
-
- /* Check if the rate now is not ideal */
- cmp ecx, _KiIdealDpcRate
- jge RateOk
- cmp dword ptr [eax+KPCR_PRCB_MAXIMUM_DPC_QUEUE_DEPTH], 1
- je RateOk
-
- /* Fix the depth */
- dec dword ptr [eax+KPCR_PRCB_MAXIMUM_DPC_QUEUE_DEPTH]
- jmp RateOk
-
-DontRequest:
- /* We didn't request a DPC, decrease the threshold */
- dec dword ptr [eax+KPCR_PRCB_ADJUST_DPC_THRESHOLD]
- jnz RateOk
-
- /* We're at 0 now, reset it */
- mov ecx, _KiAdjustDpcThreshold
- mov [eax+KPCR_PRCB_ADJUST_DPC_THRESHOLD], ecx
-
- /* Get maximum depth and check it */
- mov ecx, _KiMaximumDpcQueueDepth
- cmp ecx, [eax+KPCR_PRCB_MAXIMUM_DPC_QUEUE_DEPTH]
- je RateOk
-
- /* Increase it, it's below maximum */
- inc dword ptr [eax+KPCR_PRCB_MAXIMUM_DPC_QUEUE_DEPTH]
-
-RateOk:
- /* Decrement quantum and verify it */
- sub byte ptr [ebx+KTHREAD_QUANTUM], CLOCK_QUANTUM_DECREMENT
- jg QuantumNotEmpty
-
- /* Make sure this isn't the idle thread */
- cmp ebx, [eax+KPCR_PRCB_IDLE_THREAD]
- jz QuantumNotEmpty
-
- /* Set quantum end */
- mov byte ptr [eax+KPCR_PRCB_QUANTUM_END], 1
- mov ecx, DISPATCH_LEVEL
- call @HalRequestSoftwareInterrupt@4
-
-QuantumNotEmpty:
- /* Restore ebx and return */
- pop ebx
- ret 4
-
-SkipTick:
- /* Disable skipping the next tick and return */
- mov byte ptr [eax+KPCR_PRCB_SKIP_TICK], 0
- ret 4
-.endfunc
-
-.globl _KeUpdateSystemTime@0
-.func KeUpdateSystemTime@0
-_KeUpdateSystemTime@0:
-
- /* Check if this tick is getting skipped */
- cmp byte ptr fs:[KPCR_PRCB_SKIP_TICK], 0
- jnz SkipTickSys
-
- /* Get shared data in ECX */
- mov ecx, USER_SHARED_DATA
-
- /* Get interrupt time */
- mov edi, [ecx+USER_SHARED_DATA_INTERRUPT_TIME]
- mov esi, [ecx+USER_SHARED_DATA_INTERRUPT_TIME+4]
-
- /* Add the increment and get the carry */
- add edi, eax
- adc esi, 0
-
- /* Now store the updated times */
- mov [ecx+USER_SHARED_DATA_INTERRUPT_TIME+8], esi
- mov [ecx+USER_SHARED_DATA_INTERRUPT_TIME], edi
- mov [ecx+USER_SHARED_DATA_INTERRUPT_TIME+4], esi
-
- /* Substract tick count and get the low count */
- LOCK sub _KiTickOffset, eax
- mov eax, _KeTickCount
- mov ebx, eax
- jg IncompleteTick
-
- /* Get shared data in ECX */
- mov ebx, USER_SHARED_DATA
-
- /* Get system time */
- 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
- adc edx, 0
-
- /* Now store the updated times */
- mov [ebx+USER_SHARED_DATA_SYSTEM_TIME+8], edx
- mov [ebx+USER_SHARED_DATA_SYSTEM_TIME], ecx
- mov [ebx+USER_SHARED_DATA_SYSTEM_TIME+4], edx
-
- /* Put tick count back in EBX */
- mov ebx, eax
-
- /* Copy it in ECX and get high count */
- mov ecx, eax
- mov edx, _KeTickCount + 4
-
- /* Add the increment and get the carry */
- add ecx, 1
- adc edx, 0
-
- /* Now store the updated tick */
- mov [_KeTickCount+8], edx
- mov [_KeTickCount], ecx
- mov [_KeTickCount+4], edx
-
- /* Store in in shared data too */
- mov ds:[USER_SHARED_DATA+USER_SHARED_DATA_TICK_COUNT+8], edx
- mov ds:[USER_SHARED_DATA+USER_SHARED_DATA_TICK_COUNT], ecx
- mov ds:[USER_SHARED_DATA+USER_SHARED_DATA_TICK_COUNT+4], edx
-
- /* Get hand index and entry into the table */
- and eax, TIMER_TABLE_SIZE - 1
- shl eax, 4
-
- /* Compare the due time */
- cmp esi, [eax+_KiTimerTableListHead+KTIMER_TABLE_TIME+4]
- jb NextHand
- ja TimerExpired
- cmp edi, [eax+_KiTimerTableListHead+KTIMER_TABLE_TIME]
- jnb TimerExpired
-
-NextHand:
- /* Move to the next hand */
- inc ebx
- mov eax, ebx
-
-IncompleteTick:
-
- /* Get hand index and entry into the table */
- and eax, TIMER_TABLE_SIZE - 1
- shl eax, 4
-
- /* Compare the due time */
- cmp esi, [eax+_KiTimerTableListHead+KTIMER_TABLE_TIME+4]
- jb DebugCheck
- ja TimerExpired
- cmp edi, [eax+_KiTimerTableListHead+KTIMER_TABLE_TIME]
- jb DebugCheck
-
-TimerExpired:
-
- /* Check if expiration is active */
- mov ecx, [fs:KPCR_PRCB]
- cmp dword ptr [ecx+KPRCB_TIMER_REQUEST], 0
- jne DebugCheck
-
- /* It's not, register it */
- mov [ecx+KPRCB_TIMER_REQUEST], esp
- mov [ecx+KPRCB_TIMER_HAND], ebx
- mov ecx, DISPATCH_LEVEL
- call @HalRequestSoftwareInterrupt@4
-
-DebugCheck:
- /* Check if the debugger is enabled */
- cmp byte ptr __KdDebuggerEnabled, 0
- jnz DebuggerEnabled
-
- /* Check if this was a full tick */
-NoDebug:
- cmp dword ptr _KiTickOffset, 0
- jg IncompleteTick2
-
- /* Increase tick offset */
- mov eax, _KeMaximumIncrement
- add _KiTickOffset, eax
-
- /* Update system run time */
- push [esp]
- call _KeUpdateRunTime@8
- jmp Done
-
-IncompleteTick2:
- /* Increase interrupt count */
- inc dword ptr [fs:KPCR_PRCB_INTERRUPT_COUNT]
-
-Done:
- /* Exit the interrupt */
- cli
- call _HalEndSystemInterrupt@8
- jmp _Kei386EoiHelper@0
-
-DebuggerEnabled:
- /* Check for break-in request */
- call _KdPollBreakIn@0
- or al, al
- jz NoDebug
-
- /* Break-in requested! */
- push DBG_STATUS_CONTROL_C
- call _DbgBreakPointWithStatus@4
- jmp NoDebug
-
-SkipTickSys:
- /* Disable skipping the next tick and return */
- mov byte ptr fs:[KPCR_PRCB_SKIP_TICK], 0
- jmp IncompleteTick2
-.endfunc
Modified: trunk/reactos/ntoskrnl/ke/i386/trap.s
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/trap.s?re…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/trap.s [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ke/i386/trap.s [iso-8859-1] Tue Jan 19 07:16:47 2010
@@ -656,6 +656,41 @@
/* INTERRUPT HANDLERS ********************************************************/
+.globl _KeUpdateSystemTime@0
+.func KeUpdateSystemTime@0
+_KeUpdateSystemTime@0:
+
+ /*
+ * When we enter here, the ASM HAL has:
+ * - Entered here with a JMP, not a CALL
+ * - Put increment in EAX
+ * - Pushed OldIRQL on the stack earlier [ESP]
+ * - Pushed Vector on the stack earlier [ESP + 4]
+ * - The trap frame at ESP + 8
+ *
+ * When the HAL moves to C, this shit needs to die!!!
+ *
+ */
+
+ /* Call the regparm with Increment, OldIrql, TrapFrame */
+ mov edx, [esp]
+ mov ecx, ebp
+ call _KeUpdateSystemTimeHandler
+
+ /*
+ * The code below cannot be done in C because HalEndSystemInterrupt will
+ * fuck with your stack sideways when it decides to handle a pending APC or
+ * DPC!
+ */
+
+ /* Stack is back where it was, HalEndSystemInterrupt will clean it up */
+ cli
+ call _HalEndSystemInterrupt@8
+
+ /* Now the stack has become the trap frame */
+ jmp _Kei386EoiHelper@0
+.endfunc
+
.func KiDispatchInterrupt@0
_KiDispatchInterrupt@0:
Copied: trunk/reactos/ntoskrnl/ke/time.c (from r45139,
trunk/reactos/ntoskrnl/ke/arm/time.c)
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/time.c?p2=trun…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/arm/time.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ke/time.c [iso-8859-1] Tue Jan 19 07:16:47 2010
@@ -1,8 +1,8 @@
/*
* PROJECT: ReactOS Kernel
* LICENSE: BSD - See COPYING.ARM in the top level directory
- * FILE: ntoskrnl/ke/arm/time.c
- * PURPOSE: Implements timebase functionality on ARM processors
+ * FILE: ntoskrnl/ke/time.c
+ * PURPOSE: Implements timebase functionality
* PROGRAMMERS: ReactOS Portable Systems Group
*/
@@ -19,44 +19,25 @@
/* FUNCTIONS ******************************************************************/
-ULONG
-KiComputeTimerTableIndex(IN LONGLONG DueTime)
-{
- ULONG Hand;
-
- //
- // Compute the timer table index
- //
- Hand = (DueTime / KeMaximumIncrement);
- Hand %= TIMER_TABLE_SIZE;
- return Hand;
-}
-
+#ifndef _M_ARM
+VOID
+__attribute__((regparm(3)))
+KeUpdateSystemTimeHandler(IN ULONG Increment,
+ IN KIRQL Irql,
+ IN PKTRAP_FRAME TrapFrame)
+#else
VOID
NTAPI
KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame,
- IN KIRQL Irql,
- IN ULONG Increment)
+ IN ULONG Increment,
+ IN KIRQL Irql)
+#endif
{
- PKPRCB Prcb = KeGetPcr()->Prcb;
- ULARGE_INTEGER SystemTime, InterruptTime;
- ULONG Hand;
-
- //
- // Do nothing if this tick is being skipped
- //
- if (Prcb->SkipTick)
- {
- //
- // Handle it next time
- //
- Prcb->SkipTick = FALSE;
- return;
- }
-
- //
- // Add the increment time to the shared data
- //
+ PKPRCB Prcb = KeGetCurrentPrcb();
+ ULARGE_INTEGER CurrentTime, InterruptTime;
+ ULONG Hand, OldTickCount;
+
+ /* Add the increment time to the shared data */
InterruptTime.HighPart = SharedUserData->InterruptTime.High1Time;
InterruptTime.LowPart = SharedUserData->InterruptTime.LowPart;
InterruptTime.QuadPart += Increment;
@@ -64,95 +45,78 @@
SharedUserData->InterruptTime.LowPart = InterruptTime.LowPart;
SharedUserData->InterruptTime.High2Time = InterruptTime.HighPart;
- //
- // Update tick count
- //
- KiTickOffset -= Increment;
-
- //
- // Check for incomplete tick
- //
+ /* Update tick count */
+ InterlockedExchangeAdd(&KiTickOffset, -(LONG)Increment);
+
+ /* Check for incomplete tick */
+ OldTickCount = KeTickCount.LowPart;
if (KiTickOffset <= 0)
{
- //
- // Update the system time
- //
- SystemTime.HighPart = SharedUserData->SystemTime.High1Time;
- SystemTime.LowPart = SharedUserData->SystemTime.LowPart;
- SystemTime.QuadPart += KeTimeAdjustment;
- SharedUserData->SystemTime.High1Time = SystemTime.HighPart;
- SharedUserData->SystemTime.LowPart = SystemTime.LowPart;
- SharedUserData->SystemTime.High2Time = SystemTime.HighPart;
-
- //
- // Update the tick count
- //
- SystemTime.HighPart = KeTickCount.High1Time;
- SystemTime.LowPart = KeTickCount.LowPart;
- SystemTime.QuadPart += 1;
- KeTickCount.High1Time = SystemTime.HighPart;
- KeTickCount.LowPart = SystemTime.LowPart;
- KeTickCount.High2Time = SystemTime.HighPart;
-
- //
- // Update it in the shared user data
- //
- SharedUserData->TickCount.High1Time = SystemTime.HighPart;
- SharedUserData->TickCount.LowPart = SystemTime.LowPart;
- SharedUserData->TickCount.High2Time = SystemTime.HighPart;
- }
-
- //
- // Check for timer expiration
- //
- Hand = KeTickCount.LowPart % TIMER_TABLE_SIZE;
+ /* Update the system time */
+ CurrentTime.HighPart = SharedUserData->SystemTime.High1Time;
+ CurrentTime.LowPart = SharedUserData->SystemTime.LowPart;
+ CurrentTime.QuadPart += KeTimeAdjustment;
+ SharedUserData->SystemTime.High2Time = CurrentTime.HighPart;
+ SharedUserData->SystemTime.LowPart = CurrentTime.LowPart;
+ SharedUserData->SystemTime.High1Time = CurrentTime.HighPart;
+
+ /* Update the tick count */
+ CurrentTime.HighPart = KeTickCount.High1Time;
+ CurrentTime.LowPart = OldTickCount;
+ CurrentTime.QuadPart += 1;
+ KeTickCount.High2Time = CurrentTime.HighPart;
+ KeTickCount.LowPart = CurrentTime.LowPart;
+ KeTickCount.High1Time = CurrentTime.HighPart;
+
+ /* Update it in the shared user data */
+ SharedUserData->TickCount.High2Time = CurrentTime.HighPart;
+ SharedUserData->TickCount.LowPart = CurrentTime.LowPart;
+ SharedUserData->TickCount.High1Time = CurrentTime.HighPart;
+
+ /* Check for timer expiration */
+ Hand = OldTickCount & (TIMER_TABLE_SIZE - 1);
+ if (KiTimerTableListHead[Hand].Time.QuadPart <= InterruptTime.QuadPart)
+ {
+ /* Check if we are already doing expiration */
+ if (!Prcb->TimerRequest)
+ {
+ /* Request a DPC to handle this */
+ Prcb->TimerRequest = (ULONG_PTR)TrapFrame;
+ Prcb->TimerHand = Hand;
+ HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
+ }
+ }
+
+ /* Check for expiration with the new tick count as well */
+ OldTickCount++;
+ }
+
+ /* Check for timer expiration */
+ Hand = OldTickCount & (TIMER_TABLE_SIZE - 1);
if (KiTimerTableListHead[Hand].Time.QuadPart <= InterruptTime.QuadPart)
{
- //
- // Check if we are already doing expiration
- //
+ /* Check if we are already doing expiration */
if (!Prcb->TimerRequest)
{
- //
- // Request a DPC to handle this
- //
- Prcb->TimerRequest = TrapFrame->SvcSp;
+ /* Request a DPC to handle this */
+ Prcb->TimerRequest = (ULONG_PTR)TrapFrame;
Prcb->TimerHand = Hand;
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
}
}
- //
- // Check if we should request a debugger break
- //
- if (KdDebuggerEnabled)
- {
- //
- // Check if we should break
- //
- if (KdPollBreakIn()) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
- }
-
- //
- // Check if this was a full tick
- //
+ /* Check if this was a full tick */
if (KiTickOffset <= 0)
{
- //
- // Updare the tick offset
- //
+ /* Update the tick offset */
KiTickOffset += KeMaximumIncrement;
- //
- // Update system runtime
- //
- KeUpdateRunTime(TrapFrame, CLOCK2_LEVEL);
+ /* Update system runtime */
+ KeUpdateRunTime(TrapFrame, Irql);
}
else
{
- //
- // Increase interrupt count and exit
- //
+ /* Increase interrupt count and exit */
Prcb->InterruptCount++;
}
}
@@ -163,159 +127,85 @@
IN KIRQL Irql)
{
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
- //
+ /* Increase interrupt count */
Prcb->InterruptCount++;
- //
- // Check if we came from user mode
- //
- if (TrapFrame->PreviousMode != KernelMode)
- {
- //
- // Increase process user time
- //
- InterlockedIncrement((PLONG)&Process->UserTime);
+ /* Check if we came from user mode */
+#ifndef _M_ARM
+ if ((TrapFrame->SegCs & MODE_MASK) || (TrapFrame->EFlags &
EFLAGS_V86_MASK))
+#else
+ if (TrapFrame->PreviousMode == UserMode)
+#endif
+ {
+ /* Increase thread user time */
Prcb->UserTime++;
Thread->UserTime++;
}
else
{
- //
- // See if we were in an ISR
- //
- if (TrapFrame->OldIrql > DISPATCH_LEVEL)
- {
- //
- // Handle that
- //
+ /* See if we were in an ISR */
+ Prcb->KernelTime++;
+ if (Irql > DISPATCH_LEVEL)
+ {
+ /* Handle that */
Prcb->InterruptTime++;
}
- else if ((TrapFrame->OldIrql < DISPATCH_LEVEL) ||
- !(Prcb->DpcRoutineActive))
- {
- //
- // Handle being in kernel mode
- //
+ else if ((Irql < DISPATCH_LEVEL) || !(Prcb->DpcRoutineActive))
+ {
+ /* Handle being in kernel mode */
Thread->KernelTime++;
- InterlockedIncrement((PLONG)&Process->KernelTime);
}
else
{
- //
- // Handle being in a DPC
- //
+ /* Handle being in a DPC */
Prcb->DpcTime++;
-
- //
- // Update Debug DPC time
- //
- Prcb->DebugDpcTime++;
-
- //
- // Check if we've timed out
- //
- if (Prcb->DebugDpcTime >= KiDPCTimeout)
- {
- //
- // Print a message
- //
- DbgPrint("\n*** DPC routine > 1 sec --- This is not a break in
"
- "KeUpdateSystemTime\n");
-
- //
- // Break if a debugger is attached
- //
- if (KdDebuggerEnabled) DbgBreakPoint();
-
- //
- // Restore the debug DPC time
- //
- Prcb->DebugDpcTime = 0;
- }
- }
- }
-
- //
- // Update DPC rates
- //
+ }
+ }
+
+ /* 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
- //
+ /* Check if the queue is large enough */
if ((Prcb->DpcData[0].DpcQueueDepth) && !(Prcb->DpcRoutineActive))
{
- //
- // Request a DPC
- //
+ /* Request a DPC */
Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
- //
- // Fix the maximum queue depth
- //
+ /* Fix the maximum queue depth */
if ((Prcb->DpcRequestRate < KiIdealDpcRate) &&
(Prcb->MaximumDpcQueueDepth > 1))
{
- //
- // Make it smaller
- //
+ /* Make it smaller */
Prcb->MaximumDpcQueueDepth--;
}
}
else
{
- //
- // Check if we've reached the adjustment limit
- //
+ /* Check if we've reached the adjustment limit */
if (!(--Prcb->AdjustDpcThreshold))
{
- //
- // Reset it, and check the queue maximum
- //
+ /* Reset it, and check the queue maximum */
Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
if (KiMaximumDpcQueueDepth != Prcb->MaximumDpcQueueDepth)
{
- //
- // Increase it
- //
+ /* Increase it */
Prcb->MaximumDpcQueueDepth++;
}
}
}
- //
- // Decrement the thread quantum
- //
+ /* Decrement the thread quantum */
Thread->Quantum -= CLOCK_QUANTUM_DECREMENT;
-
- //
- // Check if the time expired
- //
+
+ /* Check if the time expired */
if ((Thread->Quantum <= 0) && (Thread != Prcb->IdleThread))
{
- //
- // Schedule a quantum end
- //
+ /* Schedule a quantum end */
Prcb->QuantumEnd = 1;
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
}
Modified: trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ntoskrnl-generic.…
==============================================================================
--- trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild [iso-8859-1] Tue Jan 19 07:16:47 2010
@@ -48,7 +48,6 @@
<file>ldt.c</file>
<file>mtrr.c</file>
<file>patpge.c</file>
- <file>systimer.S</file>
<file>thrdini.c</file>
<file>trap.s</file>
<file>traphdlr.c</file>
@@ -66,7 +65,6 @@
<file>kiinit.c</file>
<file>stubs_asm.s</file>
<file>thrdini.c</file>
- <file>time.c</file>
<file>trap.s</file>
<file>trapc.c</file>
<file>usercall.c</file>
@@ -107,6 +105,7 @@
<file>queue.c</file>
<file>semphobj.c</file>
<file>spinlock.c</file>
+ <file>time.c</file>
<file>thrdschd.c</file>
<file>thrdobj.c</file>
<file>timerobj.c</file>