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 _KIRQ_TRAPFRAME;
struct _KPCR;
struct _KPRCB;
struct _KEXCEPTION_FRAME;
#define IPI_REQUEST_FUNCTIONCALL 0
@ -192,7 +193,7 @@ extern LARGE_INTEGER SystemBootTime;
VOID KeInitExceptions(VOID);
VOID KeInitInterrupts(VOID);
VOID KeInitTimer(VOID);
VOID KeInitDpc(struct _KPCR* Pcr);
VOID KeInitDpc(struct _KPRCB* Prcb);
VOID KeInitDispatcher(VOID);
VOID KeInitializeDispatcher(VOID);
VOID KiInitializeSystemClock(VOID);

View file

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

View file

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