From 58257141b3bf4b224c60b3346f7ccce4b862af87 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Sun, 20 Aug 2006 19:08:57 +0000 Subject: [PATCH] - Some micro-architectural changes and cleanups. svn path=/trunk/; revision=23619 --- reactos/include/ndk/asm.h | 12 ++++- reactos/ntoskrnl/include/internal/ke.h | 7 ++- reactos/ntoskrnl/ke/i386/ctxswitch.S | 71 +++++++------------------- reactos/ntoskrnl/ke/i386/thread.c | 9 +--- reactos/ntoskrnl/ke/kthread.c | 31 ++++++++--- 5 files changed, 59 insertions(+), 71 deletions(-) diff --git a/reactos/include/ndk/asm.h b/reactos/include/ndk/asm.h index e870d5f6c86..27febf3cbfc 100644 --- a/reactos/include/ndk/asm.h +++ b/reactos/include/ndk/asm.h @@ -90,17 +90,20 @@ Author: #define KTHREAD_STACK_LIMIT 0x1C #define KTHREAD_TEB 0x74 #define KTHREAD_KERNEL_STACK 0x20 -#define KTHREAD_NPX_STATE 0x4D #define KTHREAD_STATE 0x4C +#define KTHREAD_NPX_STATE 0x4D #define KTHREAD_ALERTED 0x5E #define KTHREAD_APCSTATE_PROCESS 0x28 + 0x10 #define KTHREAD_PENDING_USER_APC 0x28 + 0x16 #define KTHREAD_PENDING_KERNEL_APC 0x28 + 0x15 #define KTHREAD_CONTEXT_SWITCHES 0x48 #define KTHREAD_WAIT_IRQL 0x4E +#define KTHREAD_NEXT_PROCESSOR 0x40 +#define KTHREAD_SWAP_BUSY 0x5D #define KTHREAD_SERVICE_TABLE 0x118 #define KTHREAD_PREVIOUS_MODE 0xD7 #define KTHREAD_COMBINED_APC_DISABLE 0x70 +#define KTHREAD_SPECIAL_APC_DISABLE 0x72 #define KTHREAD_LARGE_STACK 0x107 #define KTHREAD_TRAP_FRAME 0x110 #define KTHREAD_CALLBACK_STACK 0x114 @@ -113,7 +116,10 @@ Author: #define KPROCESS_DIRECTORY_TABLE_BASE 0x18 #define KPROCESS_LDT_DESCRIPTOR0 0x20 #define KPROCESS_LDT_DESCRIPTOR1 0x24 +#define KPROCESS_INT21_DESCRIPTOR0 0x28 +#define KPROCESS_INT21_DESCRIPTOR1 0x2C #define KPROCESS_IOPM_OFFSET 0x30 +#define KPROCESS_ACTIVE_PROCESSORS 0x34 // // KPCR Offsets @@ -121,12 +127,15 @@ Author: #define KPCR_EXCEPTION_LIST 0x0 #define KPCR_INITIAL_STACK 0x4 #define KPCR_STACK_LIMIT 0x8 +#define KPCR_PERF_GLOBAL_GROUP_MASK 0x8 +#define KPCR_CONTEXT_SWITCHES 0x10 #define KPCR_SET_MEMBER_COPY 0x14 #define KPCR_TEB 0x18 #define KPCR_SELF 0x1C #define KPCR_PRCB 0x20 #define KPCR_IRQL 0x24 #define KPCR_KD_VERSION_BLOCK 0x34 +#define KPCR_IDT 0x38 #define KPCR_GDT 0x3C #define KPCR_TSS 0x40 #define KPCR_SET_MEMBER 0x48 @@ -134,6 +143,7 @@ Author: #define KPCR_CURRENT_THREAD 0x124 #define KPCR_PROCESSOR_NUMBER 0x130 #define KPCR_PRCB_SET_MEMBER 0x134 +#define KPCR_PRCB_CPU_TYPE 0x138 #define KPCR_NPX_THREAD 0x640 #define KPCR_DR6 0x428 #define KPCR_DR7 0x42C diff --git a/reactos/ntoskrnl/include/internal/ke.h b/reactos/ntoskrnl/include/internal/ke.h index 5b72b646b3c..38a318ee6d4 100644 --- a/reactos/ntoskrnl/include/internal/ke.h +++ b/reactos/ntoskrnl/include/internal/ke.h @@ -122,7 +122,7 @@ extern KSPIN_LOCK DispatcherDatabaseLock; /* Thread Scheduler Functions */ /* Readies a Thread for Execution. */ -VOID +BOOLEAN STDCALL KiDispatchThreadNoLock(ULONG NewThreadStatus); @@ -148,7 +148,10 @@ KeSuspendThread(PKTHREAD Thread); NTSTATUS FASTCALL -KiSwapContext(PKTHREAD NewThread); +KiSwapContext( + IN PKTHREAD CurrentThread, + IN PKTHREAD NewThread +); VOID STDCALL diff --git a/reactos/ntoskrnl/ke/i386/ctxswitch.S b/reactos/ntoskrnl/ke/i386/ctxswitch.S index ad0761d1743..f5dce3c9982 100644 --- a/reactos/ntoskrnl/ke/i386/ctxswitch.S +++ b/reactos/ntoskrnl/ke/i386/ctxswitch.S @@ -115,9 +115,6 @@ BadThread: .globl @KiSwapContextInternal@0 @KiSwapContextInternal@0: - /* Get the PCR. It's faster to use ebx+offset then fs:offset */ - mov ebx, [fs:KPCR_SELF] - /* Set the Thread to running */ mov byte ptr [esi+KTHREAD_STATE], Running @@ -140,24 +137,6 @@ BadThread: mov [ebx+KPCR_INITIAL_STACK], eax mov [ebx+KPCR_STACK_LIMIT], ecx -#ifdef CONFIG_SMP - /* Save FPU state if the thread has used it. */ - mov ecx, [edi+KTHREAD_INITIAL_STACK] - sub ecx, NPX_FRAME_LENGTH - mov dword ptr [ebx+KPCR_NPX_THREAD], 0 - test byte ptr [edi+KTHREAD_NPX_STATE], NPX_STATE_DIRTY - jz 3f - cmp dword ptr _KeI386FxsrPresent, 0 - je 1f - fxsave [ecx] - jmp 2f -1: - fnsave [ecx] -2: - mov byte ptr [edi+KTHREAD_NPX_STATE], NPX_STATE_VALID -3: -#endif /* CONFIG_SMP */ - /* Save the stack pointer in this processors TSS */ mov ebp, [ebx+KPCR_TSS] @@ -170,9 +149,6 @@ BadThread: NoAdjust: - /* Save it */ - push [ebp+KTSS_ESP0] - /* Set new ESP0 */ mov [ebp+KTSS_ESP0], eax @@ -250,28 +226,11 @@ SameProcess: /* Increase context switches */ inc dword ptr [esi+KTHREAD_CONTEXT_SWITCHES] - /* Set TS in cr0 to catch FPU code and load the FPU state when needed */ -#ifndef CONFIG_SMP - cmp [ebx+KPCR_NPX_THREAD], esi - je 4f -#endif /* !CONFIG_SMP */ - mov eax, cr0 - or eax, X86_CR0_TS - mov cr0, eax -4: - - /* Restore ESP0 */ - pop [ebp+KTSS_ESP0] - /* Restore exception list */ pop [ebx+KPCR_EXCEPTION_LIST] /* Return */ -#ifdef CONFIG_SMP - mov ecx, offset _DispatcherDatabaseLock - call @KefReleaseSpinLockFromDpcLevel@4 -#endif - ret + ret /*++ * KiSwapContext @@ -294,37 +253,43 @@ SameProcess: * another thread switches to IT. * *--*/ -.globl @KiSwapContext@4 -@KiSwapContext@4: +.globl @KiSwapContext@8 +@KiSwapContext@8: /* Note, we CANNOT touch ebp */ /* Save 4 registers */ sub esp, 4 * 4 - + /* Save all the non-volatile ones */ mov [esp+12], ebx mov [esp+8], esi mov [esp+4], edi mov [esp+0], ebp - + + /* Get the current KPCR */ + mov ebx, fs:[KPCR_SELF] + /* Get the Current Thread */ - mov edi, fs:[KPCR_CURRENT_THREAD] - + mov edi, ecx + /* Get the New Thread */ - mov esi, ecx - + mov esi, edx + + /* Get the wait IRQL */ + movzx ecx, byte ptr [edi+KTHREAD_WAIT_IRQL] + /* Save it as Current thread */ mov fs:[KPCR_CURRENT_THREAD], esi - + /* Do the swap with the registers correctly setup */ call @KiSwapContextInternal@0 - + /* Return the registers */ mov ebp, [esp+0] mov edi, [esp+4] mov esi, [esp+8] mov ebx, [esp+12] - + /* Clean stack */ add esp, 4 * 4 ret diff --git a/reactos/ntoskrnl/ke/i386/thread.c b/reactos/ntoskrnl/ke/i386/thread.c index 117f4319d19..46b63366306 100644 --- a/reactos/ntoskrnl/ke/i386/thread.c +++ b/reactos/ntoskrnl/ke/i386/thread.c @@ -14,7 +14,6 @@ typedef struct _KSHARED_CTXSWITCH_FRAME { - ULONG Esp0; PVOID ExceptionList; PVOID RetEip; } KSHARED_CTXSWITCH_FRAME, *PKSHARED_CTXSWITCH_FRAME; @@ -94,7 +93,6 @@ Ke386InitThreadWithContext(PKTHREAD Thread, /* Setup the Fx Area */ FxSaveArea = &InitFrame->FxSaveArea; - Thread->NpxState = NPX_STATE_INVALID; /* Check if we support FXsr */ if (KeI386FxsrPresent) @@ -108,7 +106,7 @@ Ke386InitThreadWithContext(PKTHREAD Thread, FxSaveFormat->TagWord = 0; FxSaveFormat->ErrorOffset = 0; FxSaveFormat->ErrorSelector = 0; - FxSaveFormat->DataOffset =0; + FxSaveFormat->DataOffset = 0; FxSaveFormat->DataSelector = 0; FxSaveFormat->MXCsr = 0x1F80; } @@ -137,7 +135,7 @@ Ke386InitThreadWithContext(PKTHREAD Thread, CONTEXT_FLOATING_POINT; /* Set the Thread's NPX State */ - Thread->NpxState = NPX_STATE_INVALID; + Thread->NpxState = NPX_STATE_NOT_LOADED; Thread->DispatcherHeader.NpxIrql = PASSIVE_LEVEL; } else @@ -232,9 +230,6 @@ Ke386InitThreadWithContext(PKTHREAD Thread, /* And set up the Context Switch Frame */ CtxSwitchFrame->RetEip = KiThreadStartup; - CtxSwitchFrame->Esp0 = (ULONG_PTR)Thread->InitialStack - - sizeof(FX_SAVE_AREA) - - 0x10; CtxSwitchFrame->ExceptionList = (PVOID)0xFFFFFFFF; /* Save back the new value of the kernel stack. */ diff --git a/reactos/ntoskrnl/ke/kthread.c b/reactos/ntoskrnl/ke/kthread.c index 578f0e898b9..acc0faae720 100644 --- a/reactos/ntoskrnl/ke/kthread.c +++ b/reactos/ntoskrnl/ke/kthread.c @@ -128,7 +128,7 @@ KiScanThreadList(KPRIORITY Priority, return(NULL); } -VOID +BOOLEAN STDCALL KiDispatchThreadNoLock(ULONG NewThreadStatus) { @@ -136,6 +136,7 @@ KiDispatchThreadNoLock(ULONG NewThreadStatus) PKTHREAD Candidate; ULONG Affinity; PKTHREAD CurrentThread = KeGetCurrentThread(); + BOOLEAN ApcState; DPRINT("KiDispatchThreadNoLock() %d/%d/%d/%d\n", KeGetCurrentProcessorNumber(), CurrentThread, NewThreadStatus, CurrentThread->State); @@ -158,7 +159,7 @@ KiDispatchThreadNoLock(ULONG NewThreadStatus) Candidate->State = Running; KeReleaseDispatcherDatabaseLockFromDpcLevel(); - return; + return FALSE; } if (Candidate != NULL) { @@ -186,15 +187,16 @@ KiDispatchThreadNoLock(ULONG NewThreadStatus) MmUpdatePageDir((PEPROCESS)PsGetCurrentProcess(),((PETHREAD)CurrentThread)->ThreadsProcess, sizeof(EPROCESS)); /* Special note for Filip: This will release the Dispatcher DB Lock ;-) -- Alex */ - DPRINT("You are : %x, swapping to: %x\n", OldThread, CurrentThread); - KiSwapContext(CurrentThread); + DPRINT("You are : %x, swapping to: %x.\n", OldThread, CurrentThread); + ApcState = KiSwapContext(OldThread, CurrentThread); DPRINT("You are : %x, swapped from: %x\n", OldThread, CurrentThread); - return; + return ApcState; } } DPRINT1("CRITICAL: No threads are ready (CPU%d)\n", KeGetCurrentProcessorNumber()); KEBUGCHECK(0); + return FALSE; } NTSTATUS @@ -202,13 +204,26 @@ NTAPI KiSwapThread(VOID) { PKTHREAD CurrentThread = KeGetCurrentThread(); + BOOLEAN ApcState; /* Find a new thread to run */ DPRINT("Dispatching Thread as blocked\n"); - KiDispatchThreadNoLock(Waiting); + ApcState = KiDispatchThreadNoLock(Waiting); - /* Lower IRQL back */ - DPRINT("Lowering IRQL \n"); +#if 0 + /* Check if we need to deliver APCs */ + if (ApcState) + { + /* Lower to APC_LEVEL */ + KeLowerIrql(APC_LEVEL); + + /* Deliver APCs */ + KiDeliverApc(KernelMode, NULL, NULL); + ASSERT(CurrentThread->WaitIrql == 0); + } +#endif + + /* Lower IRQL back to what it was */ KfLowerIrql(CurrentThread->WaitIrql); /* Return the wait status */