roger_chen35
驱动牛犊
驱动牛犊
  • 注册日期2002-11-19
  • 最后登录2004-04-29
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:1707回复:0

关于KeEnterCriticalRegion and APC

楼主#
更多 发布于:2004-04-02 08:30
请教各位大侠两个问题

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 ArmForWaken");

//
// 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);
}
游客

返回顶部