阅读:1435回复:0
关于KeEnterCriticalRegion and APC
请教各位大侠两个问题
1.什么是 general kernel mode apc and special kernel mode apc ? 2.DDK说 KeEnterCriticalRegion and KeLeaveCriticalRegion 是用来 disable user mode apc and general kernel mode apc 防止 current thread 被 apc suspend , 可是我一直不懂 currend thread 如何被 apc suspend ? 以下是小弟参考 DDK sample code 的 toaster 看到的 sample 就是不了解 KeEnterCriticalRegion and KeLeaveCriticalRegion 中间的机制是什么 BOOLEAN ToasterArmForWake( IN PFDO_DATA FdoData, IN BOOLEAN DeviceStateChange ) /*++ Routine Description: Sends a wait-wake to the bus driver. If the device is already armed for wakeup, this routine returns TRUE. Arguments: FdoData - Points to device extension DeviceStateChange - TRUE if this function is being called by PnP. FALSE if it is coming in via WMI or due to a rearm attempt. Return Value: TRUE of FALSE --*/ { NTSTATUS status; WAKESTATE oldWakeState; POWER_STATE powerState; PAGED_CODE(); ToasterDebugPrint(TRACE, "Entered ArmForWake\n"); // // Grab disable/enable lock. The request for arm/disarm could be // called in the context of an user thread. So to prevent somebody // from suspending the thread while we are holding this PASSIVE_LEVEL // lock, we should call KeEnterCriticalRegion. This call disables normal // kernel APC from being delivered, which is used in suspending a thread. // This step is required to prevent possible deadlocks. // KeEnterCriticalRegion(); KeWaitForSingleObject( &FdoData->WakeDisableEnableLock, Executive, KernelMode, FALSE, NULL ); // // If this is coming in response to a PnP state change, allow current and // future attempts to arm. Until now, all wait-wake arm attempts would be // failed. // if (DeviceStateChange) { FdoData->AllowWakeArming = TRUE; } // // Only arm if we aren't removed/stopped/etc, and the registry allows it. // if (!(FdoData->AllowWakeArming && ToasterGetWaitWakeEnableState(FdoData))) { // // Wake not enabled // status = STATUS_UNSUCCESSFUL; } else { oldWakeState = InterlockedCompareExchange((PULONG) &FdoData->WakeState, WAKESTATE_WAITING, WAKESTATE_DISARMED ); if (oldWakeState != WAKESTATE_DISARMED) { // // Already armed or in the process of arming/rearming. // status = STATUS_SUCCESS; } else { // // Our dispatch handler is now waiting for IRP_MN_WAIT_WAKE. // The state just got moved to WAKESTATE_WAITING. // KeClearEvent(&FdoData->WakeCompletedEvent); // // Since this parameter is not used, let us just set it to // PowerSystemUnspecified. // powerState.SystemState = PowerSystemUnspecified; // // Request the power IRP, STATUS_PENDING is success // status = PoRequestPowerIrp( FdoData->UnderlyingPDO, IRP_MN_WAIT_WAKE, powerState, ToasterWaitWakePoCompletionRoutine, (PVOID)FdoData, NULL ); if (!NT_SUCCESS(status)) { FdoData->WakeState = WAKESTATE_DISARMED; KeSetEvent( &FdoData->WakeCompletedEvent, IO_NO_INCREMENT, FALSE ); } } } // // Unlock enable/disable logic // KeSetEvent( &FdoData->WakeDisableEnableLock, IO_NO_INCREMENT, FALSE ); KeLeaveCriticalRegion(); return (status == STATUS_PENDING); } |
|