MmLockPagableCodeSection

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.

Parameters

AddressWithinSection

Is a symbolic address, usually the entry point of a driver routine, within the pageable section of driver code.

Return Value

MmLockPagableCodeSection returns a handle for the locked-down section of driver code. The handle must be passed subsequently to MmLockPagableSectionByHandle or to MmUnlockPagableImageSection.

Comments

This routine and its reciprocal, MmUnlockPagableImageSection, 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 device(s) 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 device(s) are currently expected

MmLockPagableCodeSection, MmLockPagableSectionByHandle and MmUnlockPagableImageSection are intended for use by device and intermediate drivers that have the following characteristics:

·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 and/or at raised IRQL.

·The driver can determine exactly when the pageable-routines should be loaded and when they can be paged out again.

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:

·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 explictly 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 raised IRQL 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.

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.

See Also

MmUnlockPagableImageSection, MmPageEntireDriver, MmResetDriverPaging, MmLockPagableDataSection, MmLockPagableSectionByHandle