Author: sir_richard
Date: Mon Nov 8 02:37:17 2010
New Revision: 49521
URL:
http://svn.reactos.org/svn/reactos?rev=49521&view=rev
Log:
[NTOS]: KiDispatchInterrupt (the DPC handler) in C, instead of ASM.
Modified:
trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S
trunk/reactos/ntoskrnl/ke/i386/thrdini.c
Modified: trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/ctxswitch…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S [iso-8859-1] Mon Nov 8 02:37:17 2010
@@ -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
Modified: trunk/reactos/ntoskrnl/ke/i386/thrdini.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/thrdini.c…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/thrdini.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ke/i386/thrdini.c [iso-8859-1] Mon Nov 8 02:37:17 2010
@@ -47,6 +47,13 @@
KiSwitchThreads(
IN PKTHREAD OldThread,
IN PKTHREAD NewThread
+);
+
+VOID
+FASTCALL
+KiRetireDpcListInDpcStack(
+ IN PKPRCB Prcb,
+ IN PVOID DpcStack
);
/* FUNCTIONS *****************************************************************/
@@ -447,4 +454,65 @@
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 */