Under previous versions of OS/2, an application addressed memory using the segmented memory model, which was translated to physical memory addresses by the operating system using a local descriptor table (LDT), with one LDT per process. Under OS/2 Version 2.0, 16:16 references (see Flat Memory Model) are managed by a technique called LDT tiling, which provides compatibility for 16-bit applications and provides a mechanism for 32-bit applications to utilize 16-bit libraries.
A tiled LDT contains up to 8192 descriptors, where the segment base address in each descriptor is a multiple of 64KB, and each descriptor therefore points to a 64KB region of memory. Contiguous descriptors map into a contiguous linear address space, thereby using a potential maximum of 512MB, and allowing a 16-bit application to address the 512MB of the process address space in the compatibility region. Figure "Mapping 16:16 Memory References" shows the way in which memory addresses within the tiled LDT are mapped into the process address space.
The addresses within the process address space may be referenced by applications or modules using the 16:16 addressing scheme, in a similar manner to previous versions of OS/2. However, the same physical memory locations may also be accessed by 32-bit applications and modules using the 0:32 addressing scheme. Both the LDT entries used by the 16:16 scheme and the page table entries used by the 0:32 scheme may translate to the same memory locations. This translation enables 32-bit applications to make use of 16-bit modules and resources, and allows 32-bit and 16-bit applications to coexist and communicate with one another.
LDTs are managed in a different way from previous versions of OS/2. Each LDT is allocated as a sparse object until descriptors are inserted upon loading an application. Descriptors for shared memory objects are inserted downwards commencing at the top of the LDT, whereas private memory object descriptors are inserted upwards commencing at the bottom of the LDT. This order reflects the management of the linear address space by the operating system. Therefore the minimum LDT size is 8KB, using one page for the shared descriptors and one page for the private descriptors. Note that each code or data selector reserves a full 64KB of linear address space to be able to handle an eventual reallocation of segments to the maximum size of 64KB. See Figure "Mapping 16:16 Memory References".
The following memory objects use LDT descriptors:
This use of descriptors is effectively equivalent to the implementation used in the previous versions of OS/2. It must be noted, however, that a memory object greater than 64KB may not be handled in an orderly manner by a 16-bit application.
A memory object allocated in the compatibility region has both a 16:16 address (far16) and a 0:32 address (near32), allowing access by applications using either addressing scheme. The two types of addresses are related by the following arithmetic functions:
The term near32 refers to the fact that all 0:32 calls are of type near (based on offset only). The term far16 refers to the fact that 16:16 calls are based on the segment selector and offset used in combination. Bit shift right is shown as >>, and bit shift left is shown as <<.
32-bit executable modules can therefore create 16:16 aliases for memory objects in the compatibility region and conversely, 16-bit modules may create 0:32 bit aliases. As these conversions are arithmetically based, a high performance address conversion layer may be implemented, assuring automatic address conversion between 16:16 and 0:32 memory objects. See Thunking.