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); } }
相关文章推荐
- Android Context 上下文 你必须知道的一切
- mac osx安装groovy
- 基数排序——桶排
- java四舍五入保留两位小数方法整理
- angularJS测试并集成到jinkens
- JavaScript 命名函数与匿名函数
- android使用隐藏api的方法(使用被@hide的api)
- C# 将 HTML 转成纯文本
- 微信直接打开App
- 欢迎使用CSDN-markdown编辑器
- <picture>-浏览器内置的响应式标签(翻译)
- 《大话设计模式》--为别人做稼衣--代理模式<Proxy>(7)
- 板子使用教程
- Documentation/fb/framebuffer.txt 翻译
- lua如何截取中英文混合字符串
- Linux C调用C++库
- node包管理相关
- Windows Server 2012 网络负载平衡(NLB)
- 承志医院管理系统项目解析 门诊收费(七)
- Search a 2D Matrix