INF: Using GlobalNotify to Implement Real Mode Virtual Memory

ID Number: Q74796

3.00

WINDOWS

Summary:

In the Microsoft Windows graphical environment, the GlobalNotify

function works with memory allocated using the GMEM_NOTIFY and

GMEM_DISCARDABLE flags as follows:

1. The memory is allocated.

2. Windows runs low on memory, so it discards the least-recently used

(LRU) block of discardable memory.

3. If the block to be discarded was allocated with the GMEM_NOTIFY

flag set, Windows calls the appropriate notification procedure.

4. The notification procedure gives permission to discard the memory.

This article discusses these four steps and some related issues.

More Information:

The notification procedure must be in a fixed code dynamic-link

library (DLL). This ensures that the memory containing the

notification procedure will not be discarded. Although the application

allocated the memory, the application (except for the notification

procedure) is not in memory because memory is low.

The application has two methods available to instruct the notification

procedure regarding a particular block of memory:

1. Store disposition instructions at the beginning of the block of

memory. For example, if the notification should save 1000 bytes of

the block in the TEMP.VM file when the block is discarded, reserve

a fixed number of bytes at the beginning of the memory block for a

header. The header could contain the name of the file (TEMP.VM) and

the number of bytes to store.

2. Assign the job of allocating the memory to the DLL. Then, when the

notification routine is called, the DLL has the data on where to

save the contents of the memory block. This can be accomplished by

implementing the MyGlobalAlloc and MyGlobalLock functions in the

DLL.

MyGlobalAlloc allocates an appropriately sized block of discardable

memory with the notify bit set, and stores the handle returned into

a handle table (stored in the DLL's data segment). MyGlobalLock

locks the appropriate block of memory and returns a pointer to the

memory to the calling application.

The following issues must be addressed in the notification routine:

1. Open the file, save the data, and close the file upon receiving the

notification. Applications should not leave file handles open

between messages. Using a file handle that is already open can

cause disastrous results because the current program segment prefix

(PSP) may not belong to the application, and the application might

use the wrong file handle.

2. Do not call any functions that might move memory, such as

GlobalAlloc, GlobalReAlloc, or LocalAlloc, in the notification

function. If the notification procedure calls the SendMessage

function, be sure it does not start a chain reaction that could

move memory. Using PostMessage is a safer alternative.

3. The GlobalLock function fails if the memory has been discarded;

therefore, the DLL should have a MyGlobalLock function that follows

this algorithm:

if (GMEM_DISCARDED & GlobalFlags(hMem))

{

hMem = GlobalReAlloc(hMem, lSize,

GMEM_DISCARDABLE | GMEM_NOTIFY | GMEM_MOVEABLE);

// Reload the data here.

}

lpMem = GlobalLock(hMem);

A typical notification routine in the DLL might resemble the

following:

BOOL FAR PASCAL NotifyProc(HANDLE hMemToDiscard)

{

BOOL bValid;

bValid = CheckForKnownMemory(hMemToDiscard);

return bValid;

}

The CheckForKnownMemory function compares the handle specified with

the function's list of known handles. If the function recognizes

the handle, the function saves the contents of the memory block to

disk and returns TRUE; otherwise, the function returns FALSE.

This function is initialized by adding the following line to the

application's WinMain function:

GlobalNotify(NotifyProc);

Calling the MakeProcInstance function to create a procedure

instance address is not necessary because the function is in a DLL.

The NotifyProc function must be in a fixed code DLL and must be

exported. The CheckForKnownMemory function should be in the same

code segment as NotifyProc for minimal movement of memory.

Additional reference words: 3.00