Alex Ionescu <ionucu@videotron.ca>

- Fixed formatting mess in ke/dpc.c (which I had made when I wrote it due to MSVC).
- Add more comments where needed.
- Properly Initialize a Threaded DPC.

Thomas Weidenmueller <w3seek@reactos.com>
- Use Prcb directly in KeInitDpc.

svn path=/trunk/; revision=13975
This commit is contained in:
Thomas Bluemel 2005-03-12 19:45:37 +00:00
parent b2a42182ef
commit fd962e2f04
3 changed files with 347 additions and 307 deletions

View file

@ -41,6 +41,7 @@ VOID KeSetGdtSelector(ULONG Entry, ULONG Value1, ULONG Value2);
struct _KTHREAD; struct _KTHREAD;
struct _KIRQ_TRAPFRAME; struct _KIRQ_TRAPFRAME;
struct _KPCR; struct _KPCR;
struct _KPRCB;
struct _KEXCEPTION_FRAME; struct _KEXCEPTION_FRAME;
#define IPI_REQUEST_FUNCTIONCALL 0 #define IPI_REQUEST_FUNCTIONCALL 0
@ -192,7 +193,7 @@ extern LARGE_INTEGER SystemBootTime;
VOID KeInitExceptions(VOID); VOID KeInitExceptions(VOID);
VOID KeInitInterrupts(VOID); VOID KeInitInterrupts(VOID);
VOID KeInitTimer(VOID); VOID KeInitTimer(VOID);
VOID KeInitDpc(struct _KPCR* Pcr); VOID KeInitDpc(struct _KPRCB* Prcb);
VOID KeInitDispatcher(VOID); VOID KeInitDispatcher(VOID);
VOID KeInitializeDispatcher(VOID); VOID KeInitializeDispatcher(VOID);
VOID KiInitializeSystemClock(VOID); VOID KiInitializeSystemClock(VOID);

View file

@ -24,22 +24,22 @@
/* TYPES *******************************************************************/ /* TYPES *******************************************************************/
#define MAX_QUANTUM 0x7F #define MAX_QUANTUM 0x7F
/* GLOBALS ******************************************************************/
/* FUNCTIONS ****************************************************************/ /* FUNCTIONS ****************************************************************/
VOID INIT_FUNCTION
KeInitDpc(PKPCR Pcr)
/* /*
* FUNCTION: Initialize DPC handling * FUNCTION: Initialize DPC handling
*/ */
VOID
INIT_FUNCTION
KeInitDpc(PKPRCB Prcb)
{ {
InitializeListHead(&Pcr->PrcbData.DpcData[0].DpcListHead); InitializeListHead(&Prcb->DpcData[0].DpcListHead);
KeInitializeEvent(Pcr->PrcbData.DpcEvent, 0, 0); KeInitializeEvent(Prcb->DpcEvent, 0, 0);
KeInitializeSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock); KeInitializeSpinLock(&Prcb->DpcData[0].DpcLock);
Pcr->PrcbData.MaximumDpcQueueDepth = 4; Prcb->MaximumDpcQueueDepth = 4;
Pcr->PrcbData.MinimumDpcRate = 3; Prcb->MinimumDpcRate = 3;
Pcr->PrcbData.DpcData[0].DpcQueueDepth = 0; Prcb->DpcData[0].DpcQueueDepth = 0;
} }
/* /*
@ -47,9 +47,9 @@ KeInitDpc(PKPCR Pcr)
*/ */
VOID VOID
STDCALL STDCALL
KeInitializeThreadedDpc(PKDPC Dpc, KeInitializeThreadedDpc(PKDPC Dpc,
PKDEFERRED_ROUTINE DeferredRoutine, PKDEFERRED_ROUTINE DeferredRoutine,
PVOID DeferredContext) PVOID DeferredContext)
/* /*
* FUNCTION: * FUNCTION:
* Initalizes a Threaded DPC and registers the DeferredRoutine for it. * Initalizes a Threaded DPC and registers the DeferredRoutine for it.
@ -60,24 +60,18 @@ KeInitializeThreadedDpc(PKDPC Dpc,
* NOTE: Callers can be running at any IRQL. * NOTE: Callers can be running at any IRQL.
*/ */
{ {
DPRINT("Threaded DPC Initializing: %x with Routine: %x\n", Dpc, DeferredRoutine); DPRINT("Threaded DPC Initializing: %x with Routine: %x\n", Dpc, DeferredRoutine);
//Dpc->Type = KThreadedDpc; Dpc->Type = ThreadedDpcObject;
Dpc->Number= 0; Dpc->Number= 0;
Dpc->Importance= MediumImportance; Dpc->Importance= MediumImportance;
Dpc->DeferredRoutine = DeferredRoutine; Dpc->DeferredRoutine = DeferredRoutine;
Dpc->DeferredContext = DeferredContext; Dpc->DeferredContext = DeferredContext;
Dpc->DpcData = NULL; Dpc->DpcData = NULL;
} }
/* /*
* @implemented * @implemented
*/ *
VOID
STDCALL
KeInitializeDpc (PKDPC Dpc,
PKDEFERRED_ROUTINE DeferredRoutine,
PVOID DeferredContext)
/*
* FUNCTION: * FUNCTION:
* Initalizes a DPC and registers the DeferredRoutine for it. * Initalizes a DPC and registers the DeferredRoutine for it.
* ARGUMENTS: * ARGUMENTS:
@ -86,24 +80,24 @@ KeInitializeDpc (PKDPC Dpc,
* DeferredContext = Parameter to be passed to the callback routine. * DeferredContext = Parameter to be passed to the callback routine.
* NOTE: Callers can be running at any IRQL. * NOTE: Callers can be running at any IRQL.
*/ */
VOID
STDCALL
KeInitializeDpc(PKDPC Dpc,
PKDEFERRED_ROUTINE DeferredRoutine,
PVOID DeferredContext)
{ {
DPRINT("DPC Initializing: %x with Routine: %x\n", Dpc, DeferredRoutine); DPRINT("DPC Initializing: %x with Routine: %x\n", Dpc, DeferredRoutine);
Dpc->Type = DpcObject; Dpc->Type = DpcObject;
Dpc->Number= 0; Dpc->Number= 0;
Dpc->Importance= MediumImportance; Dpc->Importance= MediumImportance;
Dpc->DeferredRoutine = DeferredRoutine; Dpc->DeferredRoutine = DeferredRoutine;
Dpc->DeferredContext = DeferredContext; Dpc->DeferredContext = DeferredContext;
Dpc->DpcData = NULL; Dpc->DpcData = NULL;
} }
/* /*
* @implemented * @implemented
*/ *
BOOLEAN STDCALL
KeInsertQueueDpc (PKDPC Dpc,
PVOID SystemArgument1,
PVOID SystemArgument2)
/*
* FUNCTION: * FUNCTION:
* Queues a DPC for execution when the IRQL of a processor * Queues a DPC for execution when the IRQL of a processor
* drops below DISPATCH_LEVEL * drops below DISPATCH_LEVEL
@ -155,124 +149,141 @@ KeInsertQueueDpc (PKDPC Dpc,
* is greater that the target depth or the minimum DPC rate is less than the * is greater that the target depth or the minimum DPC rate is less than the
* target rate. * target rate.
*/ */
BOOLEAN
STDCALL
KeInsertQueueDpc(PKDPC Dpc,
PVOID SystemArgument1,
PVOID SystemArgument2)
{ {
KIRQL OldIrql; KIRQL OldIrql;
PKPCR Pcr; PKPRCB Prcb;
DPRINT("KeInsertQueueDpc(DPC %x, SystemArgument1 %x, SystemArgument2 %x)\n", DPRINT("KeInsertQueueDpc(DPC %x, SystemArgument1 %x, SystemArgument2 %x)\n",
Dpc, SystemArgument1, SystemArgument2); Dpc, SystemArgument1, SystemArgument2);
/* Check IRQL and Raise it to HIGH_LEVEL */ /* Check IRQL and Raise it to HIGH_LEVEL */
ASSERT(KeGetCurrentIrql()>=DISPATCH_LEVEL); ASSERT(KeGetCurrentIrql()>=DISPATCH_LEVEL);
KeRaiseIrql(HIGH_LEVEL, &OldIrql); KeRaiseIrql(HIGH_LEVEL, &OldIrql);
/* Check if this is a Thread DPC, which we don't support (yet) */ /* Check if this is a Thread DPC, which we don't support (yet) */
//if (Dpc->Type == KThreadedDpc) { if (Dpc->Type == ThreadedDpcObject) {
// return FALSE; return FALSE;
// KeLowerIrql(OldIrql); KeLowerIrql(OldIrql);
//} }
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/* Get the right PCR for this CPU */ /* Get the right PCR for this CPU */
if (Dpc->Number >= MAXIMUM_PROCESSORS) { if (Dpc->Number >= MAXIMUM_PROCESSORS) {
ASSERT (Dpc->Number - MAXIMUM_PROCESSORS < KeNumberProcessors);
Pcr = (PKPCR)(KPCR_BASE + (Dpc->Number - MAXIMUM_PROCESSORS) * PAGE_SIZE); ASSERT (Dpc->Number - MAXIMUM_PROCESSORS < KeNumberProcessors);
} else { Prcb = ((PKPCR)((ULONG_PTR)KPCR_BASE + ((Dpc->Number - MAXIMUM_PROCESSORS) * PAGE_SIZE)))->Prcb;
ASSERT (Dpc->Number < KeNumberProcessors);
Pcr = KeGetCurrentKPCR(); } else {
Dpc->Number = KeGetCurrentProcessorNumber();
} ASSERT (Dpc->Number < KeNumberProcessors);
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock); Prcb = KeGetCurrentPrcb();
Dpc->Number = KeGetCurrentProcessorNumber();
}
KiAcquireSpinLock(&Prcb->DpcData[0].DpcLock);
#else #else
Pcr = (PKPCR)KPCR_BASE; Prcb = ((PKPCR)KPCR_BASE)->Prcb;
#endif #endif
/* Get the DPC Data */ /* Get the DPC Data */
if (InterlockedCompareExchangeUL(&Dpc->DpcData, &Pcr->PrcbData.DpcData[0].DpcLock, 0)) { if (InterlockedCompareExchangeUL(&Dpc->DpcData, &Prcb->DpcData[0].DpcLock, 0)) {
DPRINT("DPC Already Inserted");
DPRINT("DPC Already Inserted");
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock); KiReleaseSpinLock(&Prcb->DpcData[0].DpcLock);
#endif #endif
KeLowerIrql(OldIrql); KeLowerIrql(OldIrql);
return(FALSE); return(FALSE);
} }
/* Make sure the lists are free if the Queue is 0 */ /* Make sure the lists are free if the Queue is 0 */
if (Pcr->PrcbData.DpcData[0].DpcQueueDepth == 0) { if (Prcb->DpcData[0].DpcQueueDepth == 0) {
ASSERT(IsListEmpty(&Pcr->PrcbData.DpcData[0].DpcListHead));
} else { ASSERT(IsListEmpty(&Prcb->DpcData[0].DpcListHead));
ASSERT(!IsListEmpty(&Pcr->PrcbData.DpcData[0].DpcListHead)); } else {
}
ASSERT(!IsListEmpty(&Prcb->DpcData[0].DpcListHead));
}
/* Now we can play with the DPC safely */ /* Now we can play with the DPC safely */
Dpc->SystemArgument1=SystemArgument1; Dpc->SystemArgument1=SystemArgument1;
Dpc->SystemArgument2=SystemArgument2; Dpc->SystemArgument2=SystemArgument2;
Pcr->PrcbData.DpcData[0].DpcQueueDepth++; Prcb->DpcData[0].DpcQueueDepth++;
Pcr->PrcbData.DpcData[0].DpcCount++; Prcb->DpcData[0].DpcCount++;
/* Insert the DPC into the list. HighImportance DPCs go at the beginning */ /* Insert the DPC into the list. HighImportance DPCs go at the beginning */
if (Dpc->Importance == HighImportance) { if (Dpc->Importance == HighImportance) {
InsertHeadList(&Pcr->PrcbData.DpcData[0].DpcListHead, &Dpc->DpcListEntry);
} else { InsertHeadList(&Prcb->DpcData[0].DpcListHead, &Dpc->DpcListEntry);
InsertTailList(&Pcr->PrcbData.DpcData[0].DpcListHead, &Dpc->DpcListEntry); } else {
}
DPRINT("New DPC Added. Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink); InsertTailList(&Prcb->DpcData[0].DpcListHead, &Dpc->DpcListEntry);
}
DPRINT("New DPC Added. Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink);
/* Make sure a DPC isn't executing already and respect rules outlined above. */ /* Make sure a DPC isn't executing already and respect rules outlined above. */
if ((!Pcr->PrcbData.DpcRoutineActive) && (!Pcr->PrcbData.DpcInterruptRequested)) { if ((!Prcb->DpcRoutineActive) && (!Prcb->DpcInterruptRequested)) {
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
/* Check if this is the same CPU */ /* Check if this is the same CPU */
if (Pcr != KeGetCurrentKPCR()) { if (Prcb != KeGetCurrentPrcb()) {
/* Send IPI if High Importance */
if ((Dpc->Importance == HighImportance) || /* Send IPI if High Importance */
(Pcr->PrcbData.DpcData[0].DpcQueueDepth >= Pcr->PrcbData.MaximumDpcQueueDepth)) { if ((Dpc->Importance == HighImportance) ||
if (Dpc->Number >= MAXIMUM_PROCESSORS) { (Prcb->DpcData[0].DpcQueueDepth >= Prcb->MaximumDpcQueueDepth)) {
KiIpiSendRequest(1 << (Dpc->Number - MAXIMUM_PROCESSORS), IPI_REQUEST_DPC);
} else { if (Dpc->Number >= MAXIMUM_PROCESSORS) {
KiIpiSendRequest(1 << Dpc->Number, IPI_REQUEST_DPC);
} KiIpiSendRequest(1 << (Dpc->Number - MAXIMUM_PROCESSORS), IPI_REQUEST_DPC);
} else {
KiIpiSendRequest(1 << Dpc->Number, IPI_REQUEST_DPC);
}
} }
} else { } else {
/* Request an Interrupt only if the DPC isn't low priority */
if ((Dpc->Importance != LowImportance) || /* Request an Interrupt only if the DPC isn't low priority */
(Pcr->PrcbData.DpcData[0].DpcQueueDepth >= Pcr->PrcbData.MaximumDpcQueueDepth) || if ((Dpc->Importance != LowImportance) ||
(Pcr->PrcbData.DpcRequestRate < Pcr->PrcbData.MinimumDpcRate)) { (Prcb->DpcData[0].DpcQueueDepth >= Prcb->MaximumDpcQueueDepth) ||
(Prcb->DpcRequestRate < Prcb->MinimumDpcRate)) {
/* Request Interrupt */
HalRequestSoftwareInterrupt(DISPATCH_LEVEL); /* Request Interrupt */
Pcr->PrcbData.DpcInterruptRequested = TRUE; HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
} Prcb->DpcInterruptRequested = TRUE;
} }
}
#else #else
DPRINT("Requesting Interrupt. Importance: %x. QueueDepth: %x. MaxQueue: %x . RequestRate: %x. MinRate:%x \n", Dpc->Importance, Pcr->PrcbData.DpcData[0].DpcQueueDepth, Pcr->PrcbData.MaximumDpcQueueDepth, Pcr->PrcbData.DpcRequestRate, Pcr->PrcbData.MinimumDpcRate); DPRINT("Requesting Interrupt. Importance: %x. QueueDepth: %x. MaxQueue: %x . RequestRate: %x. MinRate:%x \n", Dpc->Importance, Prcb->DpcData[0].DpcQueueDepth, Prcb->MaximumDpcQueueDepth, Prcb->DpcRequestRate, Prcb->MinimumDpcRate);
/* Request an Interrupt only if the DPC isn't low priority */
if ((Dpc->Importance != LowImportance) || /* Request an Interrupt only if the DPC isn't low priority */
(Pcr->PrcbData.DpcData[0].DpcQueueDepth >= Pcr->PrcbData.MaximumDpcQueueDepth) || if ((Dpc->Importance != LowImportance) ||
(Pcr->PrcbData.DpcRequestRate < Pcr->PrcbData.MinimumDpcRate)) { (Prcb->DpcData[0].DpcQueueDepth >= Prcb->MaximumDpcQueueDepth) ||
(Prcb->DpcRequestRate < Prcb->MinimumDpcRate)) {
/* Request Interrupt */
DPRINT("Requesting Interrupt\n"); /* Request Interrupt */
HalRequestSoftwareInterrupt(DISPATCH_LEVEL); DPRINT("Requesting Interrupt\n");
Pcr->PrcbData.DpcInterruptRequested = TRUE; HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
} Prcb->DpcInterruptRequested = TRUE;
}
#endif #endif
} }
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock); KiReleaseSpinLock(&Prcb->DpcData[0].DpcLock);
#endif #endif
/* Lower IRQL */ /* Lower IRQL */
KeLowerIrql(OldIrql); KeLowerIrql(OldIrql);
return(TRUE); return(TRUE);
} }
/* /*
* @implemented * @implemented
*/ *
BOOLEAN STDCALL
KeRemoveQueueDpc (PKDPC Dpc)
/*
* FUNCTION: * FUNCTION:
* Removes DPC object from the system dpc queue * Removes DPC object from the system dpc queue
* ARGUMENTS: * ARGUMENTS:
@ -281,33 +292,36 @@ KeRemoveQueueDpc (PKDPC Dpc)
* TRUE if the DPC was in the queue * TRUE if the DPC was in the queue
* FALSE otherwise * FALSE otherwise
*/ */
BOOLEAN
STDCALL
KeRemoveQueueDpc(PKDPC Dpc)
{ {
BOOLEAN WasInQueue; BOOLEAN WasInQueue;
KIRQL OldIrql; KIRQL OldIrql;
/* Raise IRQL */ /* Raise IRQL */
DPRINT("Removing DPC: %x\n", Dpc); DPRINT("Removing DPC: %x\n", Dpc);
KeRaiseIrql(HIGH_LEVEL, &OldIrql); KeRaiseIrql(HIGH_LEVEL, &OldIrql);
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
KiAcquireSpinLock(&((PKDPC_DATA)Dpc->DpcData)->DpcLock); KiAcquireSpinLock(&((PKDPC_DATA)Dpc->DpcData)->DpcLock);
#endif #endif
/* First make sure the DPC lock isn't being held */ /* First make sure the DPC lock isn't being held */
WasInQueue = Dpc->DpcData ? TRUE : FALSE; WasInQueue = Dpc->DpcData ? TRUE : FALSE;
if (Dpc->DpcData) { if (Dpc->DpcData) {
/* Remove the DPC */ /* Remove the DPC */
((PKDPC_DATA)Dpc->DpcData)->DpcQueueDepth--; ((PKDPC_DATA)Dpc->DpcData)->DpcQueueDepth--;
RemoveEntryList(&Dpc->DpcListEntry); RemoveEntryList(&Dpc->DpcListEntry);
} }
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
KiReleaseSpinLock(&((PKDPC_DATA)Dpc->DpcData)->DpcLock); KiReleaseSpinLock(&((PKDPC_DATA)Dpc->DpcData)->DpcLock);
#endif #endif
/* Return if the DPC was in the queue or not */ /* Return if the DPC was in the queue or not */
KeLowerIrql(OldIrql); KeLowerIrql(OldIrql);
return WasInQueue; return WasInQueue;
} }
/* /*
@ -323,7 +337,8 @@ KeFlushQueuedDpcs(VOID)
* Called when deleting a Driver. * Called when deleting a Driver.
*/ */
{ {
if (KeGetCurrentKPCR()->PrcbData.DpcData[0].DpcQueueDepth) HalRequestSoftwareInterrupt(DISPATCH_LEVEL); /* Request an interrupt if needed */
if (KeGetCurrentPrcb()->DpcData[0].DpcQueueDepth) HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
} }
/* /*
@ -332,10 +347,11 @@ KeFlushQueuedDpcs(VOID)
BOOLEAN BOOLEAN
STDCALL STDCALL
KeIsExecutingDpc( KeIsExecutingDpc(
VOID VOID
) )
{ {
return KeGetCurrentKPCR()->PrcbData.DpcRoutineActive; /* Return if the Dpc Routine is active */
return KeGetCurrentPrcb()->DpcRoutineActive;
} }
/* /*
@ -349,39 +365,41 @@ KeIsExecutingDpc(
*/ */
VOID VOID
STDCALL STDCALL
KeSetImportanceDpc (IN PKDPC Dpc, KeSetImportanceDpc (IN PKDPC Dpc,
IN KDPC_IMPORTANCE Importance) IN KDPC_IMPORTANCE Importance)
{ {
Dpc->Importance = Importance; /* Set the DPC Importance */
Dpc->Importance = Importance;
} }
/* /*
* @implemented
*
* FUNCTION: Specifies on which processor the DPC will run * FUNCTION: Specifies on which processor the DPC will run
* ARGUMENTS: * ARGUMENTS:
* Dpc = Initalizes DPC * Dpc = Initalizes DPC
* Number = Processor number * Number = Processor number
* RETURNS: None * RETURNS: None
*
* @implemented
*/ */
VOID STDCALL VOID
KeSetTargetProcessorDpc (IN PKDPC Dpc, STDCALL
IN CCHAR Number) KeSetTargetProcessorDpc(IN PKDPC Dpc,
IN CCHAR Number)
{ {
if (Number >= MAXIMUM_PROCESSORS) /* Check how many CPUs are on the system */
{ if (Number >= MAXIMUM_PROCESSORS) {
Dpc->Number = 0;
} /* No CPU Number */
else Dpc->Number = 0;
{
ASSERT(Number < KeNumberProcessors); } else {
Dpc->Number = Number + MAXIMUM_PROCESSORS;
} /* Set the Number Specified */
ASSERT(Number < KeNumberProcessors);
Dpc->Number = Number + MAXIMUM_PROCESSORS;
}
} }
VOID
STDCALL
KiQuantumEnd(VOID)
/* /*
* FUNCTION: * FUNCTION:
* Called when a quantum end occurs to check if priority should be changed * Called when a quantum end occurs to check if priority should be changed
@ -389,152 +407,173 @@ KiQuantumEnd(VOID)
* NOTES: * NOTES:
* Called when deleting a Driver. * Called when deleting a Driver.
*/ */
VOID
STDCALL
KiQuantumEnd(VOID)
{ {
PKPRCB Prcb; PKPRCB Prcb;
PKTHREAD CurrentThread; PKTHREAD CurrentThread;
KIRQL OldIrql; KIRQL OldIrql;
PKPROCESS Process; PKPROCESS Process;
KPRIORITY OldPriority; KPRIORITY OldPriority;
KPRIORITY NewPriority; KPRIORITY NewPriority;
/* Lock dispatcher, get current thread */ /* Lock dispatcher, get current thread */
Prcb = &KeGetCurrentKPCR()->PrcbData; Prcb = KeGetCurrentPrcb();
CurrentThread = KeGetCurrentThread(); CurrentThread = KeGetCurrentThread();
OldIrql = KeRaiseIrqlToSynchLevel(); OldIrql = KeRaiseIrqlToSynchLevel();
/* Get the Thread's Process */ /* Get the Thread's Process */
Process = CurrentThread->ApcState.Process; Process = CurrentThread->ApcState.Process;
/* Set DPC Event if requested */ /* Set DPC Event if requested */
if (Prcb->DpcSetEventRequest) { if (Prcb->DpcSetEventRequest) {
KeSetEvent(Prcb->DpcEvent, 0, 0); KeSetEvent(Prcb->DpcEvent, 0, 0);
} }
/* Check if Quantum expired */ /* Check if Quantum expired */
if (CurrentThread->Quantum <= 0) { if (CurrentThread->Quantum <= 0) {
/* Set the new Quantum */ /* Set the new Quantum */
CurrentThread->Quantum = Process->ThreadQuantum; CurrentThread->Quantum = Process->ThreadQuantum;
/* Calculate new priority */ /* Calculate new priority */
OldPriority = CurrentThread->Priority; OldPriority = CurrentThread->Priority;
if (OldPriority < LOW_REALTIME_PRIORITY) { if (OldPriority < LOW_REALTIME_PRIORITY) {
NewPriority = OldPriority - CurrentThread->PriorityDecrement - 1;
if (NewPriority < CurrentThread->BasePriority) { /* Set the New Priority and add the Priority Decrement */
NewPriority = CurrentThread->BasePriority; NewPriority = OldPriority - CurrentThread->PriorityDecrement - 1;
}
CurrentThread->PriorityDecrement = 0; /* Don't go out of bounds */
if (OldPriority != NewPriority) { if (NewPriority < CurrentThread->BasePriority) NewPriority = CurrentThread->BasePriority;
/* Set new Priority */
CurrentThread->Priority = NewPriority; /* Reset the priority decrement */
} else { CurrentThread->PriorityDecrement = 0;
/* Queue new thread if none is already */
if (Prcb->NextThread == NULL) { /* Set a new priority if needed */
/* FIXME: Schedule a New Thread, when ROS will have NT Scheduler */ if (OldPriority != NewPriority) {
} else {
/* Make the current thread non-premeptive if a new thread is queued */ /* Set new Priority */
CurrentThread->Preempted = FALSE; CurrentThread->Priority = NewPriority;
}
} } else {
} else {
/* Set the Quantum back to Maximum */ /* Queue new thread if none is already */
//if (CurrentThread->DisableQuantum) { if (Prcb->NextThread == NULL) {
// CurrentThread->Quantum = MAX_QUANTUM;
//} /* FIXME: Schedule a New Thread, when ROS will have NT Scheduler */
}
} } else {
/* Dispatch the Thread */
KeLowerIrql(DISPATCH_LEVEL); /* Make the current thread non-premeptive if a new thread is queued */
PsDispatchThread(THREAD_STATE_READY); CurrentThread->Preempted = FALSE;
} }
}
} else {
/* Set the Quantum back to Maximum */
//if (CurrentThread->DisableQuantum) {
// CurrentThread->Quantum = MAX_QUANTUM;
//}
}
}
/* Dispatch the Thread */
KeLowerIrql(DISPATCH_LEVEL);
PsDispatchThread(THREAD_STATE_READY);
}
/* /*
* @implemented * @implemented
*/ *
VOID
STDCALL
KiDispatchInterrupt(VOID)
/*
* FUNCTION: * FUNCTION:
* Called whenever a system interrupt is generated at DISPATCH_LEVEL. * Called whenever a system interrupt is generated at DISPATCH_LEVEL.
* It delivers queued DPCs and dispatches a new thread if need be. * It delivers queued DPCs and dispatches a new thread if need be.
*/ */
VOID
STDCALL
KiDispatchInterrupt(VOID)
{ {
PLIST_ENTRY DpcEntry; PLIST_ENTRY DpcEntry;
PKDPC Dpc; PKDPC Dpc;
KIRQL OldIrql; KIRQL OldIrql;
PKPCR Pcr; PKPRCB Prcb;
DPRINT("Dispatching Interrupts\n"); DPRINT("Dispatching Interrupts\n");
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
/* Set DPC Deliver to Active */ /* Set DPC Deliver to Active */
Pcr = KeGetCurrentKPCR(); Prcb = KeGetCurrentPrcb();
if (Pcr->PrcbData.DpcData[0].DpcQueueDepth > 0) { if (Prcb->DpcData[0].DpcQueueDepth > 0) {
/* Raise IRQL */ /* Raise IRQL */
KeRaiseIrql(HIGH_LEVEL, &OldIrql); KeRaiseIrql(HIGH_LEVEL, &OldIrql);
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock); KiAcquireSpinLock(&Prcb->DpcData[0].DpcLock);
#endif #endif
Pcr->PrcbData.DpcRoutineActive = TRUE; Prcb->DpcRoutineActive = TRUE;
DPRINT("&Pcr->PrcbData.DpcData[0].DpcListHead: %x\n", &Pcr->PrcbData.DpcData[0].DpcListHead); DPRINT("&Prcb->DpcData[0].DpcListHead: %x\n", &Prcb->DpcData[0].DpcListHead);
/* Loop while we have entries */ /* Loop while we have entries */
while (!IsListEmpty(&Pcr->PrcbData.DpcData[0].DpcListHead)) { while (!IsListEmpty(&Prcb->DpcData[0].DpcListHead)) {
ASSERT(Pcr->PrcbData.DpcData[0].DpcQueueDepth > 0);
DPRINT("Queue Depth: %x\n", Pcr->PrcbData.DpcData[0].DpcQueueDepth); ASSERT(Prcb->DpcData[0].DpcQueueDepth > 0);
DPRINT("Queue Depth: %x\n", Prcb->DpcData[0].DpcQueueDepth);
/* Get the DPC call it */
DpcEntry = RemoveHeadList(&Pcr->PrcbData.DpcData[0].DpcListHead); /* Get the DPC call it */
Dpc = CONTAINING_RECORD(DpcEntry, KDPC, DpcListEntry); DpcEntry = RemoveHeadList(&Prcb->DpcData[0].DpcListHead);
DPRINT("Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink); Dpc = CONTAINING_RECORD(DpcEntry, KDPC, DpcListEntry);
Dpc->DpcData = NULL; DPRINT("Dpc->DpcListEntry.Flink %x\n", Dpc->DpcListEntry.Flink);
Pcr->PrcbData.DpcData[0].DpcQueueDepth--; Dpc->DpcData = NULL;
Prcb->DpcData[0].DpcQueueDepth--;
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock); KiReleaseSpinLock(&Prcb->DpcData[0].DpcLock);
#endif #endif
/* Disable/Enabled Interrupts and Call the DPC */ /* Disable/Enabled Interrupts and Call the DPC */
KeLowerIrql(OldIrql); KeLowerIrql(OldIrql);
DPRINT("Calling DPC: %x\n", Dpc); DPRINT("Calling DPC: %x\n", Dpc);
Dpc->DeferredRoutine(Dpc, Dpc->DeferredRoutine(Dpc,
Dpc->DeferredContext, Dpc->DeferredContext,
Dpc->SystemArgument1, Dpc->SystemArgument1,
Dpc->SystemArgument2); Dpc->SystemArgument2);
KeRaiseIrql(HIGH_LEVEL, &OldIrql); KeRaiseIrql(HIGH_LEVEL, &OldIrql);
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock); KiAcquireSpinLock(&Prcb->DpcData[0].DpcLock);
/* /*
* If the dpc routine drops the irql below DISPATCH_LEVEL, * If the dpc routine drops the irql below DISPATCH_LEVEL,
* a thread switch can occur and after the next thread switch * a thread switch can occur and after the next thread switch
* the execution may start on an other processor. * the execution may start on an other processor.
*/ */
if (Pcr != KeGetCurrentKPCR()) { if (Prcb != KeGetCurrentPrcb()) {
Pcr->PrcbData.DpcRoutineActive = FALSE;
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock); Prcb->DpcRoutineActive = FALSE;
Pcr = KeGetCurrentKPCR(); KiReleaseSpinLock(&Prcb->DpcData[0].DpcLock);
KiAcquireSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock); Prcb = KeGetCurrentPrcb();
Pcr->PrcbData.DpcRoutineActive = TRUE; KiAcquireSpinLock(&Prcb->DpcData[0].DpcLock);
} Prcb->DpcRoutineActive = TRUE;
}
#endif #endif
} }
/* Clear DPC Flags */ /* Clear DPC Flags */
Pcr->PrcbData.DpcRoutineActive = FALSE; Prcb->DpcRoutineActive = FALSE;
Pcr->PrcbData.DpcInterruptRequested = FALSE; Prcb->DpcInterruptRequested = FALSE;
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
KiReleaseSpinLock(&Pcr->PrcbData.DpcData[0].DpcLock); KiReleaseSpinLock(&Prcb->DpcData[0].DpcLock);
#endif #endif
/* DPC Dispatching Ended, re-enable interrupts */ /* DPC Dispatching Ended, re-enable interrupts */
KeLowerIrql(OldIrql); KeLowerIrql(OldIrql);
} }
DPRINT("Checking for Quantum End\n"); DPRINT("Checking for Quantum End\n");
/* If we have Quantum End, call the function */
if (Pcr->PrcbData.QuantumEnd) { /* If we have Quantum End, call the function */
Pcr->PrcbData.QuantumEnd = FALSE; if (Prcb->QuantumEnd) {
KiQuantumEnd();
} Prcb->QuantumEnd = FALSE;
KiQuantumEnd();
}
} }
/* EOF */ /* EOF */

View file

@ -187,7 +187,7 @@ KeApplicationProcessorInit(VOID)
/* Check FPU/MMX/SSE support. */ /* Check FPU/MMX/SSE support. */
KiCheckFPU(); KiCheckFPU();
KeInitDpc(Pcr); KeInitDpc(Pcr->Prcb);
if (Pcr->PrcbData.FeatureBits & X86_FEATURE_SYSCALL) if (Pcr->PrcbData.FeatureBits & X86_FEATURE_SYSCALL)
{ {
@ -262,7 +262,7 @@ KeInit1(PCHAR CommandLine, PULONG LastKernelAddress)
/* Mark the end of the exception handler list */ /* Mark the end of the exception handler list */
KPCR->Tib.ExceptionList = (PVOID)-1; KPCR->Tib.ExceptionList = (PVOID)-1;
KeInitDpc(KPCR); KeInitDpc(KPCR->Prcb);
KeInitExceptions (); KeInitExceptions ();
KeInitInterrupts (); KeInitInterrupts ();