- Part 2 of 2: Implement KiDispatchInterrupt in assembly since it's 1) Perf-critical 2) Requires us to switch the stack to the DPC stack, which is unsafe (and impossible, unless inlining) in C.

svn path=/trunk/; revision=23889
This commit is contained in:
Alex Ionescu 2006-09-02 19:53:24 +00:00
parent 0f9c7bdf03
commit 252a2d1598
3 changed files with 80 additions and 52 deletions

View file

@ -148,6 +148,7 @@ Author:
#define KPCR_SET_MEMBER 0x48
#define KPCR_NUMBER 0x51
#define KPCR_CURRENT_THREAD 0x124
#define KPCR_PRCB_NEXT_THREAD 0x128
#define KPCR_PRCB_IDLE_THREAD 0x12C
#define KPCR_PROCESSOR_NUMBER 0x130
#define KPCR_PRCB_SET_MEMBER 0x134
@ -165,12 +166,15 @@ Author:
#define KPCR_SYSTEM_CALLS 0x6B8
#define KPCR_PRCB_DPC_QUEUE_DEPTH 0xA4C
#define KPCR_PRCB_DPC_COUNT 0xA50
#define KPCR_PRCB_DPC_STACK 0xA68
#define KPCR_PRCB_MAXIMUM_DPC_QUEUE_DEPTH 0xA6C
#define KPCR_PRCB_DPC_REQUEST_RATE 0xA70
#define KPCR_PRCB_DPC_INTERRUPT_REQUESTED 0xA78
#define KPCR_PRCB_DPC_ROUTINE_ACTIVE 0xA7A
#define KPCR_PRCB_DPC_LAST_COUNT 0xA80
#define KPCR_PRCB_TIMER_REQUEST 0xA88
#define KPCR_PRCB_QUANTUM_END 0xAA1
#define KPCR_PRCB_DEFERRED_READY_LIST_HEAD 0xC10
//
// KINTERRUPT Offsets

View file

@ -441,9 +441,22 @@ KeFlushQueuedDpcs(VOID)
{
PAGED_CODE();
/* Request an interrupt if needed */
DPRINT1("%s - FIXME!!!\n", __FUNCTION__);
if (KeGetCurrentPrcb()->DpcData[0].DpcQueueDepth) HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
/* Check if this is an UP machine */
if (KeActiveProcessors == 1)
{
/* Check if there are DPCs on either queues */
if ((KeGetCurrentPrcb()->DpcData[DPC_NORMAL].DpcQueueDepth) ||
(KeGetCurrentPrcb()->DpcData[DPC_THREADED].DpcQueueDepth))
{
/* Request an interrupt */
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
}
}
else
{
/* FIXME: SMP support required */
ASSERT(FALSE);
}
}
/*
@ -483,53 +496,4 @@ KeSetTargetProcessorDpc(IN PKDPC Dpc,
Dpc->Number = Number + MAXIMUM_PROCESSORS;
}
/*
* @implemented
*/
VOID
NTAPI
KiDispatchInterrupt(VOID)
{
PKIPCR Pcr = (PKIPCR)KeGetPcr();
PVOID ExceptionList;
/* Disable interrupts */
Ke386DisableInterrupts();
/* Check if we have to deliver DPCs, timers, or deferred threads */
if ((Pcr->PrcbData.DpcData[DPC_NORMAL].DpcQueueDepth) ||
(Pcr->PrcbData.TimerRequest) ||
(Pcr->PrcbData.DeferredReadyListHead.Next))
{
/* Save the exception list and clear it */
ExceptionList = Pcr->NtTib.ExceptionList;
Pcr->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
/* FIXME: Switch to DPC Stack */
/* Deliver DPCs */
KiRetireDpcList(Pcr->Prcb);
/* FIXME: Restore stack */
/* Restore exception list */
Pcr->NtTib.ExceptionList = ExceptionList;
}
/* Re-enable interrupts */
Ke386EnableInterrupts();
/* Check if we have quantum end */
if (Pcr->PrcbData.QuantumEnd)
{
/* Process it */
Pcr->PrcbData.QuantumEnd = FALSE;
KiQuantumEnd();
}
else if (Pcr->PrcbData.NextThread)
{
/* FIXME: Schedule new thread */
}
}
/* EOF */

View file

@ -56,6 +56,7 @@ GENERATE_IDT_STUBS /* INT 30-FF: UNEXPECTED INTERRUPTS */
.globl _NtRaiseException@12
.globl _NtContinue@8
.globl _KiCoprocessorError@0
.globl _KiDispatchInterrupt@0
/* Interrupt template entrypoints */
.globl _KiInterruptTemplate
@ -1558,6 +1559,65 @@ _KiUnexpectedInterrupt:
/* INTERRUPT HANDLERS ********************************************************/
.func KiDispatchInterrupt@0
_KiDispatchInterrupt@0:
/* Get the PCR and disable interrupts */
mov ebx, [fs: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]
call @KiRetireDpcList@4
/* Restore stack and exception list */
pop esp
pop dword ptr [ebx]
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
jz Return
/* FIXME: Schedule new thread */
int 3
Return:
/* All done */
ret
QuantumEnd:
/* Disable quantum end and process it */
mov byte ptr [ebx+KPCR_PRCB_QUANTUM_END], 0
call _KiQuantumEnd@0
ret
.endfunc
.func KiInterruptTemplate
_KiInterruptTemplate: