INF: Global Lock Count Changes in Windows 3.x

ID Number: Q61285

3.00 3.10

WINDOWS

Summary:

The global lock count mechanism has been changed in the Windows

version 3.x protected modes (that is, standard mode and enhanced

mode). The GlobalLock function only affects the lock count of

discardable objects and the default data segment (DGROUP); movable

objects are not affected. Thus, repeated calling of the

GlobalLock and GlobalFlags functions on a GMEM_MOVEABLE object

does not show any changes to its lock count.

More Information:

The following are reasons and explanations concerning this design

change:

1. In real mode, the GlobalLock function fixes the segment:offset

of a global memory object. It also increases the lock count, as

reported by the GlobalFlags function.

2. In protected mode, the far pointer returned by the GlobalLock

function is a selector:offset, not a segment:offset. Because the

selector value does not change, the GlobalLock function does

not actually fix the memory object in the physical address space.

Thus, the GlobalLock function in protected mode does not change

the lock count, unless the object is discardable or is a default

data segment.

In the case of a discardable object, the lock count is meaningful,

because Windows needs to know when the object can be discarded

(which is when its lock count is zero).

3. However, some applications have used the GlobalLock lock count

as a "reference count" [that is, as an indication of how many times

the GlobalLock function was called]. If the lock count for an

object goes to zero, these applications might consider the object a

candidate for being manually discarded, perhaps after copying the

data to disk.

Unfortunately, this use of the GlobalLock function as a reference

count keeper does not work in protected mode. Applications that

symmetrically pair calls to the GlobalLock function with calls to

the GlobalUnlock function do not need to know the lock count, and

therefore, are unaffected by this change in behavior.

4. How does an application keep track of reference counts now, given

that the GlobalLock approach does not work for nondiscardable

objects in protected mode? The application should really keep track

of reference counts itself, which should not be hard to do because

the application in need of this functionality will have a table of

global handles anyway.

However, if the application cannot be modified to maintain its own

reference counts, then there is a new Windows function, called

GlobalFixthat will accomplish this functionality. The

GlobalFix function performs the following functionality:

a. It fixes the object in the protected mode linear space.

b. It increments the "lock count", as returned by the

GlobalFlags function.

5. The following includes more information about the GlobalFlags

function. In real mode, it returns the GlobalLock lock count.

In protected mode, if the object is discardable, the GlobalFlags

function also returns the GlobalLock lock count. In protected

mode, if the object is nondiscardable, the GlobalFlags function

returns the GlobalFix reference count. In other words, the

GlobalFlags function always returns the lock/fix count. However,

in protected mode, the GlobalLock and GlobalUnLock functions

do not affect the count, only the GlobalFix and GlobalUnFix

functions do.

Note: In real mode, the GlobalFlags lock count actually indicates

the sum of GlobalLock's and GlobalFix'es. Therefore, if the

programmer is calling GlobalLock's and GlobalFix'es in pairs,

then the GlobalFlags lock count actually is twice the logical

reference count, if in real mode.

6. If the application needs to keep track of reference counts, and the

programmer wants Windows to do the work for them, then the

programmer must accompany every call to the GlobalLock function

with a call to the GlobalFix function. This way the programmer

will be able to depend on the validity of the GlobalFlags'

lock/reference count. However, using the GlobalFix function just

to keep track of the reference count is overkill, if that is all

the programmer wants it to do. Remember, the GlobalFix function

also fixes the object in the protected mode linear address space.

The price the programmer pays for having Windows keep track of the

reference count (by using the GlobalFix function) is the following:

a. Every time the GlobalLock or GlobalUnLock function is called,

the programmer must also call either the GlobalFix or

GlobalUnFix function.

And, much worse:

b. The programmer establishes sandbars in the linear address space.

An application should either keep track of reference counts on its

own or always pair GlobalLock calls with matching

GlobalUnlock calls; the use of the GlobalFix function should

be avoided.

Very few applications should need to fix global objects in linear

space; therefore, few applications should need to use the

GlobalFix function.

7. If the programmer needs to unconditionally unlock and free a global

memory object of any type, then code similar to the following can

be used:

/* 1. Make it discardable if necessary. */

if (GlobalFlags shows that it is nondiscardable)

GlobalRealloc (GMEM_MODIFY it to be discardable);

/* 2. Remove any lock counts that might be on it. */

while (GlobalUnlock != 0) /* keep unlocking it */

;

/* 3. Free it. */

GlobalFree()

Additional reference words: 3.00 3.10 3.x