The MmLockPagableCodeSection routine locks a section of driver code, containing a set of driver routines marked with a special compiler directive, into system space.
void MmLockPagableCodeSection( Address );
Specifies a symbolic address. This address is typically the name of a driver function within a section of driver code that has been marked with something like #pragma alloc_text (PAGExxxx, driverfunction). All functions in the PAGExxxx section are then guaranteed to be locked down when this function returns.
MmLockPagableCodeSection returns an opaque value that the operating system uses to identify this section of the driver code. This opaque value can be passed subsequently to MmLockPagableSectionByHandle (if the driver unlocks and then later relocks the section) or to MmUnlockPagableImageSection.
The MmLockPagableCodeSection routine and MmUnlockPagableImageSection (the routine that performs the opposite action) support drivers that can do the following:
- Defer loading a subset of driver routines into resident memory until incoming I/O requests for the driver's devices make it necessary for these routines to process IRPs.
- Make the same subset of driver routines available for paging out when they have completed the processing of I/O requests and no additional requests for the driver's devices are currently expected.
- The driver has code paths that might not be needed while the system is running, but, if they are needed, the driver's code must be resident because it runs in an arbitrary thread context or at IRQL >= DISPATCH_LEVEL.
- The driver can determine exactly when the pageable routines should be loaded and when they can be paged out again.
As other examples, the system-supplied serial and parallel drivers have DispatchCreate and DispatchClose routines that are called when a particular port is opened for exclusive I/O and when the handle for an opened port is released, respectively. Yet, serial and parallel I/O requests are sporadic, determined by which applications the end user is currently running and which application options the end user is currently exercising. In these circumstances, the system serial and parallel drivers reduce the sizes of their loaded images by marking many routines as belonging to a pageable code section that the DispatchCreate routine makes resident only when the first port is opened for I/O.
Note that each of the preceding system drivers satisfies both criteria for having pageable sections: the driver has code paths that might not be needed while the system is running, and the driver can determine exactly when its pageable section should be loaded and can be paged out again.
Because it is an expensive operation to lock down a section, if a driver locks down a pageable code section in more than one place, use MmLockPagableCodeSection for the first request. Make subsequent lock requests by calling MmLockPagableSectionByHandle passing the handle returned by MmLockPagableCodeSection. Locking by handle significantly improves driver performance because the memory manager uses the opaque return value to quickly locate the relevant section rather than searching a loaded module list. A locked down section is unlocked by calling MmUnlockPagableImageSection.
Each driver routine within a pageable code section must be marked with the following compiler directive:
#pragma alloc_text(PAGExxxx, DriverRoutine)
A single call to MmLockPagableCodeSection in, for example, a driver's DispatchCreate routine, causes the entire section, containing every driver routine marked with the same PAGExxxx identifier, to be locked in system space.
Certain types of driver routines cannot be made part of any driver's pageable section, including the following:
- Never make an ISR pageable. It is possible for a device driver to receive a spurious interrupt even if its device is not in use, particularly if the interrupt vector could be shared. In general, even if a driver can explicitly disable interrupts on its device, an ISR should not be made pageable.
- Never make a DPC routine pageable if the driver cannot control when the DPC is queued, such as any DpcForIsr or CustomDpc routine that might be queued from an ISR. In general, driver routines that run at IRQL >= DISPATCH_LEVEL and that can be called in an arbitrary thread context or in response to a random external event should not be made pageable.
- Never make the DispatchRead or DispatchWrite routine pageable in any driver that might be part of the system paging I/O path. The driver of a disk that might contain the system page file must have DispatchRead and DispatchWrite routines that are resident while the system is running, as must all drivers layered above such a disk driver.
The memory manager maintains an internal lock count on any driver's pageable section. Calls to MmLockPagableCodeSection increment this count and the reciprocal MmUnlockPagableImageSection decrements the count. A driver's pageable section is not available to be paged out unless this count is zero.
For more information about creating pageable code sections, see Making Drivers Pageable.
|Minimum supported client||Available starting with Windows 2000.|
|Header||wdm.h (include Wdm.h, Ntddk.h, Ntifs.h)|