mirror of
https://github.com/reactos/reactos.git
synced 2024-11-20 06:15:26 +00:00
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:
parent
b2a42182ef
commit
fd962e2f04
3 changed files with 347 additions and 307 deletions
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 ();
|
||||
|
|
Loading…
Reference in a new issue