mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +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
|
BOOLEAN
|
||||||
FASTCALL
|
FASTCALL
|
||||||
KiSwapContext(
|
KiSwapContext(
|
||||||
IN PKTHREAD CurrentThread,
|
IN KIRQL WaitIrql,
|
||||||
IN PKTHREAD NewThread
|
IN PKTHREAD CurrentThread
|
||||||
);
|
);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
|
|
@ -534,7 +534,7 @@ KiQuantumEnd(VOID)
|
||||||
Thread->WaitIrql = APC_LEVEL;
|
Thread->WaitIrql = APC_LEVEL;
|
||||||
|
|
||||||
/* Swap threads */
|
/* Swap threads */
|
||||||
KiSwapContext(Thread, NextThread);
|
KiSwapContext(APC_LEVEL, Thread);
|
||||||
|
|
||||||
/* Lower IRQL back to DISPATCH_LEVEL */
|
/* Lower IRQL back to DISPATCH_LEVEL */
|
||||||
KeLowerIrql(DISPATCH_LEVEL);
|
KeLowerIrql(DISPATCH_LEVEL);
|
||||||
|
|
|
@ -13,70 +13,20 @@
|
||||||
#include <ndk/asm.h>
|
#include <ndk/asm.h>
|
||||||
.intel_syntax noprefix
|
.intel_syntax noprefix
|
||||||
|
|
||||||
#define Ready 1
|
|
||||||
#define Running 2
|
|
||||||
#define WrDispatchInt 0x1F
|
|
||||||
|
|
||||||
/* FUNCTIONS ****************************************************************/
|
/* 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
|
.globl @KiSwapContextInternal@0
|
||||||
.func @KiSwapContextInternal@0, @KiSwapContextInternal@0
|
.func @KiSwapContextInternal@0, @KiSwapContextInternal@0
|
||||||
@KiSwapContextInternal@0:
|
@KiSwapContextInternal@0:
|
||||||
/* Set APC Bypass Disable and old thread pointer */
|
|
||||||
mov edx, edi
|
|
||||||
or dl, cl
|
|
||||||
|
|
||||||
/* Build switch frame */
|
/* Build switch frame */
|
||||||
sub esp, 2 * 4
|
sub esp, 2 * 4
|
||||||
mov ecx, esp
|
mov ecx, esp
|
||||||
call @KiSwapContextEntry@8
|
jmp @KiSwapContextEntry@8
|
||||||
mov ecx, 0xB00BFACA
|
|
||||||
jmp $
|
|
||||||
.endfunc
|
.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
|
.globl @KiSwapContext@8
|
||||||
.func @KiSwapContext@8, @KiSwapContext@8
|
.func @KiSwapContext@8, @KiSwapContext@8
|
||||||
@KiSwapContext@8:
|
@KiSwapContext@8:
|
||||||
|
|
||||||
/* Save 4 registers */
|
/* Save 4 registers */
|
||||||
sub esp, 4 * 4
|
sub esp, 4 * 4
|
||||||
|
|
||||||
|
@ -86,17 +36,8 @@
|
||||||
mov [esp+4], edi
|
mov [esp+4], edi
|
||||||
mov [esp+0], ebp
|
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 */
|
/* Get the wait IRQL */
|
||||||
movzx ecx, byte ptr [edi+KTHREAD_WAIT_IRQL]
|
or dl, cl
|
||||||
|
|
||||||
/* Do the swap with the registers correctly setup */
|
/* Do the swap with the registers correctly setup */
|
||||||
call @KiSwapContextInternal@0
|
call @KiSwapContextInternal@0
|
||||||
|
@ -112,10 +53,21 @@
|
||||||
ret
|
ret
|
||||||
.endfunc
|
.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
|
.globl @KiRetireDpcListInDpcStack@8
|
||||||
.func @KiRetireDpcListInDpcStack@8, @KiRetireDpcListInDpcStack@8
|
.func @KiRetireDpcListInDpcStack@8, @KiRetireDpcListInDpcStack@8
|
||||||
@KiRetireDpcListInDpcStack@8:
|
@KiRetireDpcListInDpcStack@8:
|
||||||
|
|
||||||
/* Switch stacks and retire DPCs */
|
/* Switch stacks and retire DPCs */
|
||||||
mov eax, esp
|
mov eax, esp
|
||||||
mov esp, edx
|
mov esp, edx
|
||||||
|
@ -140,20 +92,6 @@ _Ki386SetupAndExitToV86Mode@4:
|
||||||
jmp $
|
jmp $
|
||||||
.endfunc
|
.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
|
.globl @Ki386BiosCallReturnAddress@4
|
||||||
@Ki386BiosCallReturnAddress@4:
|
@Ki386BiosCallReturnAddress@4:
|
||||||
|
|
||||||
|
|
|
@ -309,7 +309,7 @@ KiIdleLoop(VOID)
|
||||||
NewThread->State = Running;
|
NewThread->State = Running;
|
||||||
|
|
||||||
/* Switch away from the idle thread */
|
/* Switch away from the idle thread */
|
||||||
KiSwapContext(OldThread, NewThread);
|
KiSwapContext(APC_LEVEL, OldThread);
|
||||||
|
|
||||||
/* We are back in the idle thread -- disable interrupts again */
|
/* We are back in the idle thread -- disable interrupts again */
|
||||||
_enable();
|
_enable();
|
||||||
|
@ -416,9 +416,6 @@ KiSwapContextEntry(IN PKSWITCHFRAME SwitchFrame,
|
||||||
PKTHREAD OldThread, NewThread;
|
PKTHREAD OldThread, NewThread;
|
||||||
ULONG Cr0, NewCr0;
|
ULONG Cr0, NewCr0;
|
||||||
|
|
||||||
/* Switch threads, check for APC disable */
|
|
||||||
ASSERT(OldThreadAndApcFlag &~ 1);
|
|
||||||
|
|
||||||
/* Save APC bypass disable */
|
/* Save APC bypass disable */
|
||||||
SwitchFrame->ApcBypassDisable = OldThreadAndApcFlag & 3;
|
SwitchFrame->ApcBypassDisable = OldThreadAndApcFlag & 3;
|
||||||
SwitchFrame->ExceptionList = Pcr->NtTib.ExceptionList;
|
SwitchFrame->ExceptionList = Pcr->NtTib.ExceptionList;
|
||||||
|
@ -451,7 +448,7 @@ KiSwapContextEntry(IN PKSWITCHFRAME SwitchFrame,
|
||||||
|
|
||||||
/* Now enable interrupts and do the switch */
|
/* Now enable interrupts and do the switch */
|
||||||
_enable();
|
_enable();
|
||||||
KiSwitchThreads(OldThread, NewThread);
|
KiSwitchThreads(OldThread, NewThread->KernelStack);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
@ -509,8 +506,8 @@ KiDispatchInterrupt(VOID)
|
||||||
/* Make the old thread ready */
|
/* Make the old thread ready */
|
||||||
KxQueueReadyThread(OldThread, Prcb);
|
KxQueueReadyThread(OldThread, Prcb);
|
||||||
|
|
||||||
/* Swap to the new thread. FIXME: APC Bypass */
|
/* Swap to the new thread */
|
||||||
KiSwapContext(OldThread, NewThread);
|
KiSwapContext(APC_LEVEL, OldThread);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -387,7 +387,7 @@ KiSwapThread(IN PKTHREAD CurrentThread,
|
||||||
WaitIrql = CurrentThread->WaitIrql;
|
WaitIrql = CurrentThread->WaitIrql;
|
||||||
|
|
||||||
/* Swap contexts */
|
/* Swap contexts */
|
||||||
ApcState = KiSwapContext(CurrentThread, NextThread);
|
ApcState = KiSwapContext(WaitIrql, CurrentThread);
|
||||||
|
|
||||||
/* Get the wait status */
|
/* Get the wait status */
|
||||||
WaitStatus = CurrentThread->WaitStatus;
|
WaitStatus = CurrentThread->WaitStatus;
|
||||||
|
@ -754,7 +754,7 @@ NtYieldExecution(VOID)
|
||||||
ASSERT(OldIrql <= DISPATCH_LEVEL);
|
ASSERT(OldIrql <= DISPATCH_LEVEL);
|
||||||
|
|
||||||
/* Swap to new thread */
|
/* Swap to new thread */
|
||||||
KiSwapContext(Thread, NextThread);
|
KiSwapContext(APC_LEVEL, Thread);
|
||||||
Status = STATUS_SUCCESS;
|
Status = STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -249,7 +249,7 @@ KiExitDispatcher(IN KIRQL OldIrql)
|
||||||
Thread->WaitIrql = OldIrql;
|
Thread->WaitIrql = OldIrql;
|
||||||
|
|
||||||
/* Swap threads and check if APCs were pending */
|
/* Swap threads and check if APCs were pending */
|
||||||
PendingApc = KiSwapContext(Thread, NextThread);
|
PendingApc = KiSwapContext(OldIrql, Thread);
|
||||||
if (PendingApc)
|
if (PendingApc)
|
||||||
{
|
{
|
||||||
/* Lower only to APC */
|
/* Lower only to APC */
|
||||||
|
|
Loading…
Reference in a new issue