Understanding Scheduling, Thread Context, and IRQL -- 5
I/O operation, the thread context might contain the user-mode address space and
security rights of the process that requested the I/O. However, if the calling process
was performing an operation on behalf of another user or application, the thread
context might contain the user-mode address space and security rights of a
different process. In other words, the user-mode address space might contain
information that pertains to the process that requested the I/O, or it might instead
contain information that pertains to a different process.
The dispatch routines of file system drivers (FSDs), file system (FS) filter drivers,
and other highest-level drivers normally receive I/O requests in the context of the
thread that initiated the request. These routines can access data in the user-mode
address space of the requesting process, provided that they validate pointers and
protect themselves against user-mode errors.
Most other routines in FSDs, FS filters, and highest-level drivers—and most
routines in lower-level drivers—are called in an arbitrary thread context. Although
the highest-level drivers receive I/O requests in the context of the requesting thread,
they often forward those requests to their lower level drivers on different threads.
Consequently, you can make no assumptions about the contents of the user-mode
address space at the time such routines are called.
For example, when a user-mode application requests a synchronous I/O operation,
the highest-level driver’s I/O dispatch routine is called in the context of the thread
that requested the operation. The dispatch routine queues the I/O request for
processing by lower-level drivers. The requesting thread then enters a wait state
until the I/O is complete. A different thread de-queues the request, which is handled
by lower-level drivers that run in the context of whatever thread happens to be
executing at the time they are called.
A few driver routines run in the context of a system thread. System threads have
the address space of the system process and the security rights of the operating
system itself. Work items queued with the IoXxxWorkItem routines run in a system
thread context, and so do all DriverEntry and AddDevice routines. No user-mode
requests arrive in a system thread context.
The section "Standard Driver Routines, IRQL, and Thread Context,” later in this
paper, lists the thread context in which each standard driver routine is called.
Driver Threads
Although a driver can create a new, driver-dedicated thread by calling
PsCreateSystemThread, drivers rarely do so. Switching thread context is a
relatively time-consuming operation that can degrade driver performance if it occurs
often. Therefore, drivers should create dedicated threads only to perform continually
repeated or long-term activities, such as polling a device or managing multiple data
streams, as a network driver might do.
To perform a short-term, finite task, a driver should not create its own thread;
instead, it can temporarily “borrow” a system thread by queuing a work item. The
system maintains a pool of dedicated threads that all drivers share. When a driver
queues a work item, the system dispatches it to one of these threads for execution.
Drivers use work items to run code in the kernel address space and security context
or to call functions that are available only at IRQL PASSIVE_LEVEL. For example,
a driver’s IoCompletion routine (which can run at IRQL DISPATCH_LEVEL) should
use a work item to call a routine that runs at IRQL PASSIVE_LEVEL.
To queue a work item, a driver allocates an object of type IO_WORKITEM and calls
the IoQueueWorkItem routine, specifying the callback routine to perform the task
© 2004 Microsoft Corporation. All rights reserved.