mirror of
https://github.com/reactos/reactos.git
synced 2024-07-06 20:55:16 +00:00
[NTOS]: KiDispatchInterrupt (the DPC handler) in C, instead of ASM.
svn path=/trunk/; revision=49521
This commit is contained in:
parent
77d20c89bf
commit
b4593924da
|
@ -112,121 +112,18 @@
|
|||
ret
|
||||
.endfunc
|
||||
|
||||
/* DPC INTERRUPT HANDLER ******************************************************/
|
||||
.globl @KiRetireDpcListInDpcStack@8
|
||||
.func @KiRetireDpcListInDpcStack@8, @KiRetireDpcListInDpcStack@8
|
||||
@KiRetireDpcListInDpcStack@8:
|
||||
|
||||
.globl _KiDispatchInterrupt@0
|
||||
.func KiDispatchInterrupt@0
|
||||
_KiDispatchInterrupt@0:
|
||||
|
||||
/* Preserve EBX */
|
||||
push ebx
|
||||
|
||||
/* Get the PCR and disable interrupts */
|
||||
mov ebx, PCR[KPCR_SELF]
|
||||
cli
|
||||
|
||||
/* Check if we have to deliver DPCs, timers, or deferred threads */
|
||||
mov eax, [ebx+KPCR_PRCB_DPC_QUEUE_DEPTH]
|
||||
or eax, [ebx+KPCR_PRCB_TIMER_REQUEST]
|
||||
or eax, [ebx+KPCR_PRCB_DEFERRED_READY_LIST_HEAD]
|
||||
jz CheckQuantum
|
||||
|
||||
/* Save stack pointer and exception list, then clear it */
|
||||
push ebp
|
||||
push dword ptr [ebx+KPCR_EXCEPTION_LIST]
|
||||
mov dword ptr [ebx+KPCR_EXCEPTION_LIST], -1
|
||||
|
||||
/* Save the stack and switch to the DPC Stack */
|
||||
mov edx, esp
|
||||
mov esp, [ebx+KPCR_PRCB_DPC_STACK]
|
||||
push edx
|
||||
|
||||
/* Deliver DPCs */
|
||||
mov ecx, [ebx+KPCR_PRCB]
|
||||
/* Switch stacks and retire DPCs */
|
||||
mov eax, esp
|
||||
mov esp, edx
|
||||
push eax
|
||||
call @KiRetireDpcList@4
|
||||
|
||||
/* Restore stack and exception list */
|
||||
/* Return on original stack */
|
||||
pop esp
|
||||
pop dword ptr [ebx+KPCR_EXCEPTION_LIST]
|
||||
pop ebp
|
||||
|
||||
CheckQuantum:
|
||||
|
||||
/* Re-enable interrupts */
|
||||
sti
|
||||
|
||||
/* Check if we have quantum end */
|
||||
cmp byte ptr [ebx+KPCR_PRCB_QUANTUM_END], 0
|
||||
jnz QuantumEnd
|
||||
|
||||
/* Check if we have a thread to swap to */
|
||||
cmp byte ptr [ebx+KPCR_PRCB_NEXT_THREAD], 0
|
||||
je Return
|
||||
|
||||
/* Make space on the stack to save registers */
|
||||
sub esp, 3 * 4
|
||||
mov [esp+8], esi
|
||||
mov [esp+4], edi
|
||||
mov [esp+0], ebp
|
||||
|
||||
/* Get the current thread */
|
||||
mov edi, [ebx+KPCR_CURRENT_THREAD]
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/* Raise to synch level */
|
||||
call _KeRaiseIrqlToSynchLevel@0
|
||||
|
||||
/* Set context swap busy */
|
||||
mov byte ptr [edi+KTHREAD_SWAP_BUSY], 1
|
||||
|
||||
/* Acquire the PRCB Lock */
|
||||
lock bts dword ptr [ebx+KPCR_PRCB_PRCB_LOCK], 0
|
||||
jnb GetNext
|
||||
lea ecx, [ebx+KPCR_PRCB_PRCB_LOCK]
|
||||
call @KefAcquireSpinLockAtDpcLevel@4
|
||||
#endif
|
||||
|
||||
GetNext:
|
||||
/* Get the next thread and clear it */
|
||||
mov esi, [ebx+KPCR_PRCB_NEXT_THREAD]
|
||||
and dword ptr [ebx+KPCR_PRCB_NEXT_THREAD], 0
|
||||
|
||||
/* Set us as the current running thread */
|
||||
mov [ebx+KPCR_CURRENT_THREAD], esi
|
||||
mov byte ptr [esi+KTHREAD_STATE_], Running
|
||||
mov byte ptr [edi+KTHREAD_WAIT_REASON], WrDispatchInt
|
||||
|
||||
/* Put thread in ECX and get the PRCB in EDX */
|
||||
mov ecx, edi
|
||||
lea edx, [ebx+KPCR_PRCB_DATA]
|
||||
call @KiQueueReadyThread@8
|
||||
|
||||
/* Set APC_LEVEL and do the swap */
|
||||
mov cl, APC_LEVEL
|
||||
call @KiSwapContextInternal@0
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/* Lower IRQL back to dispatch */
|
||||
mov cl, DISPATCH_LEVEL
|
||||
call @KfLowerIrql@4
|
||||
#endif
|
||||
|
||||
/* Restore registers */
|
||||
mov ebp, [esp+0]
|
||||
mov edi, [esp+4]
|
||||
mov esi, [esp+8]
|
||||
add esp, 3*4
|
||||
|
||||
Return:
|
||||
/* All done */
|
||||
pop ebx
|
||||
ret
|
||||
|
||||
QuantumEnd:
|
||||
/* Disable quantum end and process it */
|
||||
mov byte ptr [ebx+KPCR_PRCB_QUANTUM_END], 0
|
||||
call _KiQuantumEnd@0
|
||||
pop ebx
|
||||
ret
|
||||
.endfunc
|
||||
|
||||
|
|
|
@ -49,6 +49,13 @@ KiSwitchThreads(
|
|||
IN PKTHREAD NewThread
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
KiRetireDpcListInDpcStack(
|
||||
IN PKPRCB Prcb,
|
||||
IN PVOID DpcStack
|
||||
);
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
VOID
|
||||
|
@ -447,4 +454,65 @@ KiSwapContextEntry(IN PKSWITCHFRAME SwitchFrame,
|
|||
KiSwitchThreads(OldThread, NewThread);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KiDispatchInterrupt(VOID)
|
||||
{
|
||||
PKIPCR Pcr = (PKIPCR)KeGetPcr();
|
||||
PKPRCB Prcb = &Pcr->PrcbData;
|
||||
PVOID OldHandler;
|
||||
PKTHREAD NewThread, OldThread;
|
||||
|
||||
/* Disable interrupts */
|
||||
_disable();
|
||||
|
||||
/* Check for pending timers, pending DPCs, or pending ready threads */
|
||||
if ((Prcb->DpcData[0].DpcQueueDepth) ||
|
||||
(Prcb->TimerRequest) ||
|
||||
(Prcb->DeferredReadyListHead.Next))
|
||||
{
|
||||
/* Switch to safe execution context */
|
||||
OldHandler = Pcr->NtTib.ExceptionList;
|
||||
Pcr->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
|
||||
|
||||
/* Retire DPCs while under the DPC stack */
|
||||
KiRetireDpcListInDpcStack(Prcb, Prcb->DpcStack);
|
||||
|
||||
/* Restore context */
|
||||
Pcr->NtTib.ExceptionList = OldHandler;
|
||||
}
|
||||
|
||||
/* Re-enable interrupts */
|
||||
_enable();
|
||||
|
||||
/* Check for quantum end */
|
||||
if (Prcb->QuantumEnd)
|
||||
{
|
||||
/* Handle quantum end */
|
||||
Prcb->QuantumEnd = FALSE;
|
||||
KiQuantumEnd();
|
||||
}
|
||||
else if (Prcb->NextThread)
|
||||
{
|
||||
/* Capture current thread data */
|
||||
OldThread = Prcb->CurrentThread;
|
||||
NewThread = Prcb->NextThread;
|
||||
|
||||
/* Set new thread data */
|
||||
Prcb->NextThread = NULL;
|
||||
Prcb->CurrentThread = NewThread;
|
||||
|
||||
/* The thread is now running */
|
||||
NewThread->State = Running;
|
||||
OldThread->WaitReason = WrDispatchInt;
|
||||
|
||||
/* Make the old thread ready */
|
||||
KxQueueReadyThread(OldThread, Prcb);
|
||||
|
||||
/* Swap to the new thread. FIXME: APC Bypass */
|
||||
KiSwapContext(OldThread, NewThread);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* EOF */
|
||||
|
|
Loading…
Reference in a new issue