diff --git a/reactos/include/ndk/asm.h b/reactos/include/ndk/asm.h index 92ed46d6861..fa999b2377b 100644 --- a/reactos/include/ndk/asm.h +++ b/reactos/include/ndk/asm.h @@ -109,6 +109,9 @@ Author: #define KTHREAD_CALLBACK_STACK 0x114 #define KTHREAD_APC_STATE_INDEX 0x11C #define KTHREAD_STACK_BASE 0x158 +#define KTHREAD_QUANTUM 0x15D +#define KTHREAD_KERNEL_TIME 0x160 +#define KTHREAD_USER_TIME 0x18C // // KPROCESS Offsets @@ -145,6 +148,7 @@ Author: #define KPCR_SET_MEMBER 0x48 #define KPCR_NUMBER 0x51 #define KPCR_CURRENT_THREAD 0x124 +#define KPCR_PRCB_IDLE_THREAD 0x12C #define KPCR_PROCESSOR_NUMBER 0x130 #define KPCR_PRCB_SET_MEMBER 0x134 #define KPCR_PRCB_CPU_TYPE 0x138 @@ -152,8 +156,21 @@ Author: #define KPCR_DR6 0x428 #define KPCR_DR7 0x42C #define KPCR_PRCB_INTERRUPT_COUNT 0x644 +#define KPCR_PRCB_KERNEL_TIME 0x648 +#define KPCR_PRCB_USER_TIME 0x64C +#define KPCR_PRCB_DPC_TIME 0x650 +#define KPCR_PRCB_DEBUG_DPC_TIME 0x654 +#define KPCR_PRCB_INTERRUPT_TIME 0x658 +#define KPCR_PRCB_ADJUST_DPC_THRESHOLD 0x65C #define KPCR_SYSTEM_CALLS 0x6B8 -#define KPCR_PRCB_DPC_ROUTINE_ACTIVE 0x994 +#define KPCR_PRCB_DPC_QUEUE_DEPTH 0xA4C +#define KPCR_PRCB_DPC_COUNT 0xA50 +#define KPCR_PRCB_MAXIMUM_DPC_QUEUE_DEPTH 0xA6C +#define KPCR_PRCB_DPC_REQUEST_RATE 0xA70 +#define KPCR_PRCB_DPC_INTERRUPT_REQUESTED 0xA78 +#define KPCR_PRCB_DPC_ROUTINE_ACTIVE 0xA7A +#define KPCR_PRCB_DPC_LAST_COUNT 0xA80 +#define KPCR_PRCB_QUANTUM_END 0xAA1 // // KINTERRUPT Offsets @@ -432,6 +449,11 @@ Author: #define DISPATCH_LEVEL 0x2 #define CLOCK2_LEVEL 0x1C #define HIGH_LEVEL 0x1F + +// +// Quantum Decrements +// +#define CLOCK_QUANTUM_DECREMENT 0x3 #endif // diff --git a/reactos/include/ndk/i386/ketypes.h b/reactos/include/ndk/i386/ketypes.h index 7fd015215f6..286eb8801da 100644 --- a/reactos/include/ndk/i386/ketypes.h +++ b/reactos/include/ndk/i386/ketypes.h @@ -407,7 +407,6 @@ typedef struct _KPRCB #endif ULONG SpareCounter0; #if (NTDDI_VERSION < NTDDI_LONGHORN) - ULONG KeContextSwitches; ULONG KeDcacheFlushCount; ULONG KeExceptionDispatchCount; ULONG KeFirstLevelTbFills; diff --git a/reactos/ntoskrnl/ex/sysinfo.c b/reactos/ntoskrnl/ex/sysinfo.c index 21d7b968b80..5cced43ab6c 100644 --- a/reactos/ntoskrnl/ex/sysinfo.c +++ b/reactos/ntoskrnl/ex/sysinfo.c @@ -1054,7 +1054,7 @@ QSI_DEF(SystemInterruptInformation) Prcb = ((PKPCR)KPCR_BASE)->Prcb; for (i = 0; i < KeNumberProcessors; i++) { - sii->ContextSwitches = Prcb->KeContextSwitches; + //sii->ContextSwitches = Prcb->KeContextSwitches; sii->DpcCount = 0; /* FIXME */ sii->DpcRate = 0; /* FIXME */ sii->TimeIncrement = ti; diff --git a/reactos/ntoskrnl/ke/i386/clock.S b/reactos/ntoskrnl/ke/i386/clock.S index ee90fd31408..6c7b7afefce 100644 --- a/reactos/ntoskrnl/ke/i386/clock.S +++ b/reactos/ntoskrnl/ke/i386/clock.S @@ -20,6 +20,141 @@ /* FUNCTIONS ******************************************************************/ +.globl _KeUpdateRunTime2@0 +.func KeUpdateRunTime2@0 +_KeUpdateRunTime2@0: + + /* Get KPCR */ + mov eax, [fs:KPCR_SELF] + + /* 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 dword ptr[eax+KPCR_PRCB_DPC_ROUTINE_ACTIVE], 0 + jz BelowDispatch + + /* At dispatch, increase DPC time */ + inc dword ptr [eax+KPCR_PRCB_DPC_TIME] + 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 +.endfunc + .globl _KeUpdateSystemTime2@0 .func KeUpdateSystemTime2@0 _KeUpdateSystemTime2@0: