您的位置:首页 > 其它

windows内核原理分析之DPC函数的执行(2)

2015-06-04 15:08 1096 查看

windows内核原理分析之DPC函数的执行(2)

需要执行DPC函数时,就通过KeInsertQueueDpc()提出DPC请求,就是把具体的KDPC结构挂入PRCB中的DPC请求队列,这常常是由中断服务程序完成的。

BOOLEAN NTAPI
KeInsertQueueDpc(IN PKDPC Dpc,
IN PVOID SystemArgument1, IN PVOID SystemArgument2)
{
......
ASSERT_DPC(Dpc);

/* Check IRQL and Raise it to HIGH_LEVEL */
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
CurrentPrcb = KeGetCurrentPrcb();    //获取当前所在CPU的PRCB
/* Check if the DPC has more then the maximum number of CPUs */
if (Dpc->Number >= MAXIMUM_PROCESSORS)
{
/* Then substract the maximum and get that PRCB. */
Cpu = Dpc->Number - MAXIMUM_PROCESSORS;
Prcb = KiProcessorBlock[Cpu];
}
else
{
/* Use the current one */
Prcb = CurrentPrcb;
Cpu = Prcb->Number;
}

/* ROS Sanity Check */
ASSERT(Prcb == CurrentPrcb);
/* Check if this is a threaded DPC and threaded DPCs are enabled */
if ((Dpc->Type == ThreadedDpcObject) && (Prcb->ThreadDpcEnable))
{
/* Then use the threaded data */
DpcData = &Prcb->DpcData[DPC_THREADED];
}
else
{
/* Otherwise, use the regular data */
DpcData = &Prcb->DpcData[DPC_NORMAL];
}
/* Acquire the DPC lock */
KiAcquireSpinLock(&DpcData->DpcLock);
/* Get the DPC Data */
if (!InterlockedCompareExchangePointer(&Dpc->DpcData, DpcData, NULL))
{
/* Now we can play with the DPC safely */
Dpc->SystemArgument1SystemArgument1 = SystemArgument1;
Dpc->SystemArgument2SystemArgument2 = SystemArgument2;
DpcData->DpcQueueDepth++;
DpcData->DpcCount++;
DpcConfigured = TRUE;
/* Check if this is a high importance DPC */
if (Dpc->Importance == HighImportance)
{
/* Pre-empty other DPCs */
InsertHeadList(&DpcData->DpcListHead, &Dpc->DpcListEntry);
}
else
{
/* Add it at the end */
InsertTailList(&DpcData->DpcListHead, &Dpc->DpcListEntry);
}
/* Check if this is the DPC on the threaded list */
if (&Prcb->DpcData[DPC_THREADED] == DpcData)
{
/* Make sure a threaded DPC isn't already active */
if (!(Prcb->DpcThreadActive) && !(Prcb->DpcThreadRequested))
{
/* FIXME: Setup Threaded DPC */
DPRINT1("Threaded DPC not supported\n");
while (TRUE);
}
}  //end if (&Prcb->DpcData[DPC_THREADED] == DpcData)
else
{
/* Make sure a DPC isn't executing already */
if (!(Prcb->DpcRoutineActive) && !(Prcb->
DpcInterruptRequested))
{
/* Check if this is the same CPU */
if (Prcb != CurrentPrcb)
{
/* Check if the DPC is of high importance or above the
* maximum depth. If it is, then make sure that the CPU
* isn't idle, or that it's sleeping. */
if (((Dpc->Importance == HighImportance) ||
(DpcData->DpcQueueDepth >=
Prcb->MaximumDpcQueueDepth))
&& (!(AFFINITY_MASK(Cpu) & KiIdleSummary)
|| (Prcb->Sleeping)))
{
/* Set interrupt requested */
Prcb->DpcInterruptRequested = TRUE;
/* Set DPC inserted */
DpcInserted = TRUE;
}
}  //end if (Prcb != CurrentPrcb)
else
{
/* Check if the DPC is of anything but
low importance */
if ((Dpc->Importance != LowImportance) ||
(DpcData->DpcQueueDepth >=
Prcb->MaximumDpcQueueDepth)
|| (Prcb->DpcRequestRate
< Prcb->MinimumDpcRate))
{
/* Set interrupt requested */
Prcb->DpcInterruptRequested = TRUE;
/* Set DPC inserted */
DpcInserted = TRUE;
}
}
}  //end if (!(Prcb->DpcRoutineActive)
&& !(Prcb->DpcInterrupt Requested))
}  //end if (&Prcb->DpcData[DPC_THREADED] == DpcData) else
}  //end if (!InterlockedCompareExchangePointer(
&Dpc->DpcData, DpcData, NULL))
/* Release the lock */
KiReleaseSpinLock(&DpcData->DpcLock);
/* Check if the DPC was inserted */
if (DpcInserted)
{
/* Check if this was SMP */
if (Prcb != CurrentPrcb)
{
/* It was, request and IPI */
KiIpiSendRequest(AFFINITY_MASK(Cpu), IPI_DPC);
}
else
{
/* It wasn't, request an interrupt from HAL
*/  //要求扫描DPC请求队列
HalRequestSoftwareInterrupt(DISPATCH_LEVEL);  //调用HalRequestSoftwareInterrupt函数
}
}
/* Lower IRQL */
KeLowerIrql(OldIrql);  //降低到原来的Irql
return DpcConfigured;
}


这段代码是支持SMP多处理器结构的,所以不同的CPU有不同的PRCB数据结构,但是单CPU的系统只有一个PRCB。

如果将DPC请求挂入了队列,就通过HalRequestSoftwareInterrupt()将PCR中的相应标志位设置成TRUE,表示要求扫描DPC请求队列:

[KeInsertQueueDpc() > HalRequestSoftwareInterrupt()]

VOID FASTCALL HalRequestSoftwareInterrupt(IN KIRQL Request)
{
switch (Request)
{
case APC_LEVEL:
((PKIPCR)KeGetPcr())->HalReserved[HAL_APC_REQUEST] = TRUE;
break;
case DISPATCH_LEVEL:
((PKIPCR)KeGetPcr())->HalReserved[HAL_DPC_REQUEST] = TRUE;
break;
default:
KEBUGCHECK(0);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: