mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
[NTOS]: Optimize new context switching code to avoid wasted cycles.
svn path=/trunk/; revision=49523
This commit is contained in:
parent
44eef5b073
commit
e8c269c0c4
6 changed files with 24 additions and 89 deletions
|
@ -298,8 +298,8 @@ KeReadStateThread(IN PKTHREAD Thread);
|
|||
BOOLEAN
|
||||
FASTCALL
|
||||
KiSwapContext(
|
||||
IN PKTHREAD CurrentThread,
|
||||
IN PKTHREAD NewThread
|
||||
IN KIRQL WaitIrql,
|
||||
IN PKTHREAD CurrentThread
|
||||
);
|
||||
|
||||
VOID
|
||||
|
|
|
@ -534,7 +534,7 @@ KiQuantumEnd(VOID)
|
|||
Thread->WaitIrql = APC_LEVEL;
|
||||
|
||||
/* Swap threads */
|
||||
KiSwapContext(Thread, NextThread);
|
||||
KiSwapContext(APC_LEVEL, Thread);
|
||||
|
||||
/* Lower IRQL back to DISPATCH_LEVEL */
|
||||
KeLowerIrql(DISPATCH_LEVEL);
|
||||
|
|
|
@ -13,70 +13,20 @@
|
|||
#include <ndk/asm.h>
|
||||
.intel_syntax noprefix
|
||||
|
||||
#define Ready 1
|
||||
#define Running 2
|
||||
#define WrDispatchInt 0x1F
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
/*++
|
||||
* KiSwapContextInternal
|
||||
*
|
||||
* The KiSwapContextInternal routine switches context to another thread.
|
||||
*
|
||||
* Params:
|
||||
* ESI - Pointer to the KTHREAD to which the caller wishes to
|
||||
* switch to.
|
||||
* EDI - Pointer to the KTHREAD to which the caller wishes to
|
||||
* switch from.
|
||||
*
|
||||
* Returns:
|
||||
* None.
|
||||
*
|
||||
* Remarks:
|
||||
* Absolutely all registers except ESP can be trampled here for maximum code flexibility.
|
||||
*
|
||||
*--*/
|
||||
.globl @KiSwapContextInternal@0
|
||||
.func @KiSwapContextInternal@0, @KiSwapContextInternal@0
|
||||
@KiSwapContextInternal@0:
|
||||
/* Set APC Bypass Disable and old thread pointer */
|
||||
mov edx, edi
|
||||
or dl, cl
|
||||
|
||||
/* Build switch frame */
|
||||
sub esp, 2 * 4
|
||||
mov ecx, esp
|
||||
call @KiSwapContextEntry@8
|
||||
mov ecx, 0xB00BFACA
|
||||
jmp $
|
||||
jmp @KiSwapContextEntry@8
|
||||
.endfunc
|
||||
|
||||
/*++
|
||||
* KiSwapContext
|
||||
*
|
||||
* The KiSwapContext routine switches context to another thread.
|
||||
*
|
||||
* Params:
|
||||
* TargetThread - Pointer to the KTHREAD to which the caller wishes to
|
||||
* switch to.
|
||||
*
|
||||
* Returns:
|
||||
* The WaitStatus of the Target Thread.
|
||||
*
|
||||
* Remarks:
|
||||
* This is a wrapper around KiSwapContextInternal which will save all the
|
||||
* non-volatile registers so that the Internal function can use all of
|
||||
* them. It will also save the old current thread and set the new one.
|
||||
*
|
||||
* The calling thread does not return after KiSwapContextInternal until
|
||||
* another thread switches to IT.
|
||||
*
|
||||
*--*/
|
||||
.globl @KiSwapContext@8
|
||||
.func @KiSwapContext@8, @KiSwapContext@8
|
||||
@KiSwapContext@8:
|
||||
|
||||
/* Save 4 registers */
|
||||
sub esp, 4 * 4
|
||||
|
||||
|
@ -86,17 +36,8 @@
|
|||
mov [esp+4], edi
|
||||
mov [esp+0], ebp
|
||||
|
||||
/* Get the current KPCR */
|
||||
mov ebx, fs:[KPCR_SELF]
|
||||
|
||||
/* Get the Current Thread */
|
||||
mov edi, ecx
|
||||
|
||||
/* Get the New Thread */
|
||||
mov esi, edx
|
||||
|
||||
/* Get the wait IRQL */
|
||||
movzx ecx, byte ptr [edi+KTHREAD_WAIT_IRQL]
|
||||
or dl, cl
|
||||
|
||||
/* Do the swap with the registers correctly setup */
|
||||
call @KiSwapContextInternal@0
|
||||
|
@ -112,10 +53,21 @@
|
|||
ret
|
||||
.endfunc
|
||||
|
||||
.globl @KiSwitchThreads@8
|
||||
.func @KiSwitchThreads@8, @KiSwitchThreads@8
|
||||
@KiSwitchThreads@8:
|
||||
/* Load the new kernel stack and switch OS to new thread */
|
||||
mov esp, edx
|
||||
call @KiSwapContextExit@8
|
||||
|
||||
/* Now we're on the new thread. Return to the caller to restore registers */
|
||||
add esp, 2 * 4
|
||||
ret
|
||||
.endfunc
|
||||
|
||||
.globl @KiRetireDpcListInDpcStack@8
|
||||
.func @KiRetireDpcListInDpcStack@8, @KiRetireDpcListInDpcStack@8
|
||||
@KiRetireDpcListInDpcStack@8:
|
||||
|
||||
/* Switch stacks and retire DPCs */
|
||||
mov eax, esp
|
||||
mov esp, edx
|
||||
|
@ -140,20 +92,6 @@ _Ki386SetupAndExitToV86Mode@4:
|
|||
jmp $
|
||||
.endfunc
|
||||
|
||||
.globl @KiSwitchThreads@8
|
||||
.func @KiSwitchThreads@8, @KiSwitchThreads@8
|
||||
@KiSwitchThreads@8:
|
||||
|
||||
/* Load the new kernel stack and switch OS to new thread */
|
||||
mov esp, [edx+KTHREAD_KERNEL_STACK]
|
||||
mov edx, esp
|
||||
call @KiSwapContextExit@8
|
||||
|
||||
/* Now we're on the new thread. Return to the caller to restore registers */
|
||||
add esp, 2 * 4
|
||||
ret
|
||||
.endfunc
|
||||
|
||||
.globl @Ki386BiosCallReturnAddress@4
|
||||
@Ki386BiosCallReturnAddress@4:
|
||||
|
||||
|
|
|
@ -309,7 +309,7 @@ KiIdleLoop(VOID)
|
|||
NewThread->State = Running;
|
||||
|
||||
/* Switch away from the idle thread */
|
||||
KiSwapContext(OldThread, NewThread);
|
||||
KiSwapContext(APC_LEVEL, OldThread);
|
||||
|
||||
/* We are back in the idle thread -- disable interrupts again */
|
||||
_enable();
|
||||
|
@ -416,9 +416,6 @@ KiSwapContextEntry(IN PKSWITCHFRAME SwitchFrame,
|
|||
PKTHREAD OldThread, NewThread;
|
||||
ULONG Cr0, NewCr0;
|
||||
|
||||
/* Switch threads, check for APC disable */
|
||||
ASSERT(OldThreadAndApcFlag &~ 1);
|
||||
|
||||
/* Save APC bypass disable */
|
||||
SwitchFrame->ApcBypassDisable = OldThreadAndApcFlag & 3;
|
||||
SwitchFrame->ExceptionList = Pcr->NtTib.ExceptionList;
|
||||
|
@ -451,7 +448,7 @@ KiSwapContextEntry(IN PKSWITCHFRAME SwitchFrame,
|
|||
|
||||
/* Now enable interrupts and do the switch */
|
||||
_enable();
|
||||
KiSwitchThreads(OldThread, NewThread);
|
||||
KiSwitchThreads(OldThread, NewThread->KernelStack);
|
||||
}
|
||||
|
||||
VOID
|
||||
|
@ -509,8 +506,8 @@ KiDispatchInterrupt(VOID)
|
|||
/* Make the old thread ready */
|
||||
KxQueueReadyThread(OldThread, Prcb);
|
||||
|
||||
/* Swap to the new thread. FIXME: APC Bypass */
|
||||
KiSwapContext(OldThread, NewThread);
|
||||
/* Swap to the new thread */
|
||||
KiSwapContext(APC_LEVEL, OldThread);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -387,7 +387,7 @@ KiSwapThread(IN PKTHREAD CurrentThread,
|
|||
WaitIrql = CurrentThread->WaitIrql;
|
||||
|
||||
/* Swap contexts */
|
||||
ApcState = KiSwapContext(CurrentThread, NextThread);
|
||||
ApcState = KiSwapContext(WaitIrql, CurrentThread);
|
||||
|
||||
/* Get the wait status */
|
||||
WaitStatus = CurrentThread->WaitStatus;
|
||||
|
@ -754,7 +754,7 @@ NtYieldExecution(VOID)
|
|||
ASSERT(OldIrql <= DISPATCH_LEVEL);
|
||||
|
||||
/* Swap to new thread */
|
||||
KiSwapContext(Thread, NextThread);
|
||||
KiSwapContext(APC_LEVEL, Thread);
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -249,7 +249,7 @@ KiExitDispatcher(IN KIRQL OldIrql)
|
|||
Thread->WaitIrql = OldIrql;
|
||||
|
||||
/* Swap threads and check if APCs were pending */
|
||||
PendingApc = KiSwapContext(Thread, NextThread);
|
||||
PendingApc = KiSwapContext(OldIrql, Thread);
|
||||
if (PendingApc)
|
||||
{
|
||||
/* Lower only to APC */
|
||||
|
|
Loading…
Reference in a new issue