IRQL

Managing Hardware Priorities

The IRQL at which a driver routine executes determines which kernel-mode driver support routines it can call. For example, some driver support routines require that the caller be running at IRQL = DISPATCH_LEVEL. Others cannot be called safely if the caller is running at any IRQL higher than PASSIVE_LEVEL.

Following is a list of IRQLs at which the most commonly implemented standard driver routines are called. The IRQLs are listed from lowest to highest priority.

PASSIVE_LEVEL

Interrupts Masked Off — None.

Driver Routines Called at PASSIVE_LEVEL — DriverEntryAddDeviceReinitializeUnload routines, most dispatch routines, driver-created threads, worker-thread callbacks.

APC_LEVEL

Interrupts Masked Off — APC_LEVEL interrupts are masked off.

Driver Routines Called at APC_LEVEL — Some dispatch routines (see Dispatch Routines and IRQLs).

DISPATCH_LEVEL

Interrupts Masked Off — DISPATCH_LEVEL and APC_LEVEL interrupts are masked off. Device, clock, and power failure interrupts can occur.

Driver Routines Called at DISPATCH_LEVEL — StartIoAdapterControlAdapterListControlControllerControl,IoTimerCancel (while holding the cancel spin lock), DpcForIsrCustomTimerDpcCustomDpc routines.

DIRQL

Interrupts Masked Off — All interrupts at IRQL<= DIRQL of driver's interrupt object. Device interrupts with a higher DIRQL value can occur, along with clock and power failure interrupts.

Driver Routines Called at DIRQL — InterruptServiceSynchCritSection routines.

The only difference between APC_LEVEL and PASSIVE_LEVEL is that a process executing at APC_LEVEL cannot get APC interrupts. But both IRQLs imply a thread context and both imply that the code can be paged out.

Lowest-level drivers process IRPs while running at one of three IRQLs:

  • PASSIVE_LEVEL, with no interrupts masked off on the processor, in the driver's Dispatch routine(s)

    DriverEntryAddDeviceReinitialize, and Unload routines also are run at PASSIVE_LEVEL, as are any driver-created system threads.

  • DISPATCH_LEVEL, with DISPATCH_LEVEL and APC_LEVEL interrupts masked off on the processor, in the StartIoroutine

    AdapterControlAdapterListControlControllerControlIoTimerCancel (while it holds the cancel spin lock), andCustomTimerDpc routines also are run at DISPATCH_LEVEL, as are DpcForIsr and CustomDpc routines.

  • Device IRQL (DIRQL), with all interrupts at less than or equal to the SynchronizeIrql of the driver's interrupt object(s) masked off on the processor, in the ISR and SynchCritSection routines

Most higher-level drivers process IRPs while running at either of two IRQLs:

  • PASSIVE_LEVEL, with no interrupts masked off on the processor, in the driver's dispatch routines

    DriverEntryReinitializeAddDevice, and Unload routines also are run at PASSIVE_LEVEL, as are any driver-created system threads or worker-thread callback routines or file system drivers.

  • DISPATCH_LEVEL, with DISPATCH_LEVEL and APC_LEVEL interrupts masked off on the processor, in the driver'sIoCompletion routine(s)

    IoTimerCancel, and CustomTimerDpc routines also are run at DISPATCH_LEVEL.

In some circumstances, intermediate and lowest-level drivers of mass-storage devices are called at IRQL APC_LEVEL. In particular, this can occur at a page fault for which a file system driver sends an IRP_MJ_READ request to lower drivers.

Most standard driver routines are run at an IRQL that allows them simply to call the appropriate support routines. For example, a device driver must call AllocateAdapterChannel while running at IRQL DISPATCH_LEVEL. Since most device drivers call these routines from a StartIo routine, usually they are running at DISPATCH_LEVEL already.

Note that a device driver that has no StartIo routine because it sets up and manages its own queues of IRPs is not necessarily running at DISPATCH_LEVEL IRQL when it should call AllocateAdapterChannel. Such a driver must nest its call to AllocateAdapterChannel between calls to KeRaiseIrql and KeLowerIrql so that it runs at the required IRQL when it calls AllocateAdapterChannel and restores the original IRQL when the calling routine regains control.

When calling driver support routines, be aware of the following.

  • Calling KeRaiseIrql with an input NewIrql value that is less than the current IRQL causes a fatal error. CallingKeLowerIrql except to restore the original IRQL (that is, after a call to KeRaiseIrql) also causes a fatal error.

  • While running at IRQL >= DISPATCH_LEVEL, calling KeWaitForSingleObject or KeWaitForMultipleObjects for kernel-defined dispatcher objects to wait for a nonzero interval causes a fatal error.

  • The only driver routines that can safely wait for events, semaphores, mutexes, or timers to be set to the signaled state are those that run in a nonarbitrary thread context at IRQL PASSIVE_LEVEL, such as driver-created threads, theDriverEntry and Reinitialize routines, or dispatch routines for inherently synchronous I/O operations (such as most device I/O control requests).

  • Even while running at IRQL PASSIVE_LEVEL, pageable driver code must not call KeSetEventKeReleaseSemaphore, orKeReleaseMutex with the input Wait parameter set to TRUE. Such a call can cause a fatal page fault.

  • Any routine that is running at greater than IRQL APC_LEVEL can neither allocate memory from paged pool nor access memory in paged pool safely. If a routine running at IRQL greater than APC_LEVEL causes a page fault, it is a fatal error.

  • A driver must be running at IRQL DISPATCH_LEVEL when it calls KeAcquireSpinLockAtDpcLevel andKeReleaseSpinLockFromDpcLevel.

    A driver can be running at IRQL <= DISPATCH_LEVEL when it calls KeAcquireSpinLock but it must release that spin lock by calling KeReleaseSpinLock. In other words, it is a programming error to release a spin lock acquired withKeAcquireSpinLock by calling KeReleaseSpinLockFromDpcLevel.

    A driver must not call KeAcquireSpinLockAtDpcLevelKeReleaseSpinLockFromDpcLevelKeAcquireSpinLock, orKeReleaseSpinLock while running at IRQL > DISPATCH_LEVEL.

  • Calling a support routine that uses a spin lock, such as an ExInterlockedXxx routine, raises IRQL on the current processor either to DISPATCH_LEVEL or to DIRQL if the caller is not already running at a raised IRQL.

  • Driver code that runs at IRQL > PASSIVE_LEVEL should execute as quickly as possible. The higher the IRQL at which a routine runs, the more important it is for good overall performance to tune that routine to execute as quickly as possible. For example, any driver that calls KeRaiseIrql should make the reciprocal call to KeLowerIrql as soon as it can.

For more information about determining priorities, see the Scheduling, Thread Context, and IRQL white paper that is available on the Microsoft Windows Hardware Developer Central (WHDC) website.


Dispatch Routines and IRQLs



Most drivers' dispatch routines are called in an arbitrary thread context at IRQL = PASSIVE_LEVEL, with the following exceptions:

  • Any highest-level driver's dispatch routines are called in the context of the thread that originated the I/O request, which is commonly a user-mode application thread.

    In other words, the dispatch routines of file system drivers and other highest-level drivers are called in a nonarbitrary thread context at IRQL = PASSIVE_LEVEL.

  • The DispatchReadDispatchWrite, and DispatchDeviceControl routines of lowest-level device drivers, and of intermediate drivers layered above them in the system paging path, can be called at IRQL = APC_LEVEL and in an arbitrary thread context.

    The DispatchRead and/or DispatchWrite routines, and any other routine that also processes read and/or write requests in such a lowest-level device or intermediate driver, must be resident at all times. These driver routines can neither be pageable nor be part of a driver's pageable-image section; they must not access any pageable memory. Furthermore, they should not be dependent on any blocking calls (such as KeWaitForSingleObject with a nonzero time-out).

  • The DispatchPower routine of drivers in the hibernation and/or paging paths can be called at IRQL = DISPATCH_LEVEL. The DispatchPnP routines of such drivers must be prepared to handle PnPIRP_MN_DEVICE_USAGE_NOTIFICATION requests.

  • The DispatchPower routine of drivers that require inrush power at start-up can be called at IRQL = DISPATCH_LEVEL.



The following table summarizes the IRQL and thread context requirements for file system filter driver dispatch routines.

Dispatch routine Caller's IRQL: Caller's thread context:

Cleanup

PASSIVE_LEVEL

Nonarbitrary

Close

APC_LEVEL

Arbitrary

Create

PASSIVE_LEVEL

Nonarbitrary

DeviceControl (except paging I/O)

PASSIVE_LEVEL

Nonarbitrary

DeviceControl (paging I/O path)

APC_LEVEL

Arbitrary

DirectoryControl

APC_LEVEL

Arbitrary

FlushBuffers

PASSIVE_LEVEL

Nonarbitrary

FsControl (except paging I/O)

PASSIVE_LEVEL

Nonarbitrary

FsControl (paging I/O path)

APC_LEVEL

Arbitrary

LockControl

PASSIVE_LEVEL

Nonarbitrary

PnP

PASSIVE_LEVEL

Arbitrary

QueryEa

PASSIVE_LEVEL

Nonarbitrary

QueryInformation

PASSIVE_LEVEL

Nonarbitrary

QueryQuota

PASSIVE_LEVEL

Nonarbitrary

QuerySecurity

PASSIVE_LEVEL

Nonarbitrary

QueryVolumeInfo

PASSIVE_LEVEL

Nonarbitrary

Read (except paging I/O)

PASSIVE_LEVEL

Nonarbitrary

Read (paging I/O path)

APC_LEVEL

Arbitrary

SetEa

PASSIVE_LEVEL

Nonarbitrary

SetInformation

PASSIVE_LEVEL

Nonarbitrary

SetQuota

PASSIVE_LEVEL

Nonarbitrary

SetSecurity

PASSIVE_LEVEL

Nonarbitrary

SetVolumeInfo

PASSIVE_LEVEL

Nonarbitrary

Shutdown

PASSIVE_LEVEL

Arbitrary

Write (except paging I/O)

PASSIVE_LEVEL

Nonarbitrary

Write (paging I/O path)

APC_LEVEL

Arbitrary


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值