PVOID
MmLockPagableCodeSection(
IN PVOID AddressWithinSection
);
MmLockPagableCodeSection locks a section of driver code, containing a set of driver routines marked with a special compiler directive, into system space.
MmLockPagableCodeSection returns a handle for the locked-down section of driver code. The handle must be passed subsequently to MmLockPagableSectionByHandle or to MmUnlockPagableImageSection.
This routine and its reciprocal, MmUnlockPagableImageSection, support drivers that can do the following:
MmLockPagableCodeSection, MmLockPagableSectionByHandle and MmUnlockPagableImageSection are intended for use by device and intermediate drivers that have the following characteristics:
For example, the system-supplied fault-tolerant disk driver supports the creation of mirror sets, stripe sets, and volume sets. Yet, a particular machine can be configured only with a mirror set, only with a stripe set, only with a volume set, or with any combination of these three possible options. In these circumstances, the system ftdisk driver reduces the size of its loaded image by marking routines that explictly support mirror, stripe, and volume sets as belonging to pageable-code sections. During driver initialization, pageable-code section(s) are made resident only if the user has configured the disks to have mirror, stripe, and/or volume sets. If the user repartitions the disks dynamically, the ftdisk driver loads any additional pageable-code sections necessary to support any mirror, stripe, and/or volume sets that the user requests.
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.
Note also that calling MmLockPagableCodeSection and MmUnlockPagableImageSection reduce the size of each driver’s loaded image at a cost to the driver’s and system’s performance. Drivers of performance-critical devices, such as keyboard and mouse drivers, and drivers of devices that are constantly in use, such as disk drivers, generally should not have pageable sections: the loss in performance is simply not worth the temporary reduction in driver image size.
Because it is an expensive operation to lock down a section, if a pageable-code section is locked down in more than place by a driver, 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 handle to find the 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, supported by all Windows NT-compatible compilers:
#pragma alloc_text(PAGExxxx, DriverRoutine), where xxxx is an optional four-character, unique identifier for the caller’s pageable section and DriverRoutine is an entry point to be included within the pageable-code section. For Windows NT-compatible compilers, the keyword PAGE and the driver-determined suffix, which can be up to four characters, are case-sensitive, that is, PAGE must be capitalized.
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:
Note that routines in a pageable section marked with the compiler directive #pragma alloc_text(PAGExxxx, ...)differ from routines marked with the compiler directive #pragma alloc_text(INIT, ...). The routines in the INIT section are not pageable and are discarded as soon as the driver returns from its DriverEntry or its Reinitialize routine, if it has one.
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.
Callers of MmLockPagableCodeSection and MmLockPagableDataSection must take care to use the former for code sections and the latter for data sections. If the incorrect form of MmLockPagableXxxxSection is used, a fatal error will occur on some platforms.
For more information on creating pageable code sections, see The Programmer’s Guide.
Callers of MmLockPagableCodeSection run at IRQL PASSIVE_LEVEL.
MmUnlockPagableImageSection, MmPageEntireDriver, MmResetDriverPaging, MmLockPagableDataSection, MmLockPagableSectionByHandle