7.3.4 Managing Interlocked Queues with a Driver-Created Thread

Like the system floppy controller driver mentioned in Chapter 2, an NT driver with a device-dedicated thread, rather than a StartIo routine, usually manages its own queueing of IRPs in an interlocked queue. Such a driver’s thread pulls IRPs from its interlocked queue when there is work to be done on the device.

In general, such a driver must manage synchronization with its thread to any resources shared between the thread and other driver routines. Such a driver also must have some way to notify its driver-created thread that IRPs are queued. Usually, such a thread waits on a dispatcher object, stored in the device extension, until the driver’s Dispatch routines set the dispatcher object to the Signaled state after inserting an IRP into the interlocked queue.

When such a device driver’s Dispatch routines are called, each checks the parameters in the I/O stack location of the input IRP and, if they are valid, queues the request for further processing. For each IRP queued to a driver-dedicated thread, the Dispatch routine should set up whatever context its thread needs to process that IRP before it calls ExInterlockedInsert..List. The driver’s I/O stack location in each IRP gives the driver’s thread access to the device extension of the target device object, where the driver can share context information with its thread, as the thread removes each IRP from the queue.

Any driver-created thread runs at IRQL PASSIVE_LEVEL and at a base runtime priority previously set when the driver called PsCreateSystemThread. Such a thread’s call to ExInterlockedRemoveHeadList temporarily raises the IRQL to DISPATCH_LEVEL on the current processor while the IRP is being removed from the driver’s internal queue, and the original IRQL is restored to PASSIVE_LEVEL on return from this call.

    Any driver thread (or driver-supplied worker-thread callback) must manage the IRQLs at which it runs carefully. For example, consider the following:

For more information about managing IRQLs, and about the design tradeoffs of a using a driver thread for a slow device, see Chapter 16. For specific information about the required IRQL(s) for calling any particular support routine, see the Kernel-mode Driver Reference.