## Printer Device Driver

[prev][next][parent][TOC]

### Implementation

The GenPLib Memory-Management package was created to provide consistency and to simplify the growth and management of heaps.

This package was one of the first developed for driver use. When writing a driver "from scratch" or modifying a driver to use GenPLib, begin with this package because many of the other GenPLib packages require memory allocated in the unique format of the memory-management package.

Previously, all drivers had to manage their own memory heaps, often using memory allocation packages exported from other parts of the OS/2 system-for example, the INCL_WINHEAP functions from PM WIN or the Subsystem Allocation routines in the PM Graphics Rendering Engine (GRE). It was never clear what routines should be used in a presentation driver or where they should be used (especially for portability). Many of these packages did not allow the caller to grow their heaps, provided no controls for memory leakage, and had no validation or recovery when a driver terminated unexpectedly.

A typical raster printer driver creates two types of heaps: a shared heap during Dynamic Link Library (DLL) initialization processing, and a per-DC heap when the PM GRE enables the driver during the FILL_PHYSICAL (02 Hex) subfunction. These heaps are freed during corresponding DLL termination and DISABLE_PHYSICAL calls to the driver.

In addition, a per-process heap is also created for the OS2_PM_DRV_DEVMODE entry point in a printer presentation driver. This entry point causes the driver to display its printer and job properties dialogs to the user or to retrieve printer and job property information for a specific output device/ destination.

A typical driver initially allocates a 256KB shared global heap and a 100KB per-DC heap and elects to use the memory package's default heap growth size and threshold for larger allocations (achieved by passing in 0L for parameters 2 and 3 for GplMemoryDeleteInstance).

In case of unexpected driver termination, a driver should register a per- process exception handler for each of the major presentation driver entry points. This exception handler can contain cleanup code that frees any per- process heaps created using GplMemoryCreateInstance in case any code problems cause an exception to occur.

One major benefit of the GenPLib memory code is the ability to detect memory leaks (memory a driver allocates but never frees). Whenever a call to GplMemoryDeleteInstance is made, all memory allocated from the heap is freed so that no leaks can occur. If the debug version of the GenPLib library is used, while GplMemoryDeleteInstance is cleaning up memory areas that a developer forgot to free, it will inform the developer on a debugging terminal which line of code allocated the memory that was not freed. This is possible because the memory-management package records the function address (and other information) from where GplMemoryAlloc is called.

An OS/2 presentation driver must consider the memory constraints of the user and other programs in the system. In the past, drivers allocated large heaps, hoping the memory an application needed would never overrun the amount initially allocated and cause an exception. Under the paging architecture of OS/2 Warp, however, all the heap memory is often committed during heap creation.

All this memory could be forced in and never used by an application (for example, an application queries the driver for the devices it supports and performs no output). In this case, the driver's memory pages would not be touched, so OS/2 would slowly page it out and give it back to the applications that had it in the first place. As a result, a good deal of swapping could occur for active addressable memory, especially on low-RAM systems. The alternative was to force the driver to manage its own heap growth and consolidate multiple heaps.

Using the GenPLib Memory-Management package, the heap is identified to the driver as a generic handle to a memory control block (HMCB), not as an address into memory. This handle is supplied by GplMemoryCreateInstance and is used to identify the heap for all subsequent memory allocations and frees.

Therefore, a reasonable initial heap can be created that is just large enough to allow the driver to enable and respond to basic queries. As applications use the driver to render graphics (or other memory-intensive operations), the memory package detects when a given GplMemoryAlloc call will overflow the current heap and grows it by a default or specified size. The caller does not ever need to know that the heap has grown because it continues to use the same HMCB, while the memory package chains these heaps together.