home *** CD-ROM | disk | FTP | other *** search
- ________________________
- Virtual Memory Allocation
- Page 3
-
-
- Virtual Memory Allocation
-
- I.Purpose:
- To allow DOS programs access to extended and Upper Memory
- Blocks(UMBs) for allocation purposes. The virtual memory
- allocation(VMA) functions will allow a DOS executable to
- allocate blocks and pages of extended memory and UMBs.
- However, all physical manipulation must take place in a
- swaparea located in conventional memory.
-
- II. Associated Data Types and manifest constants:
- A._vmhnd_t
- 1.Handle to a virtual memory block, usually received
- from _vmalloc() and _vrealloc(). This data type is
- used by all functions that access virtual memory.
- 2. This handle should only be used as an identifier to
- a virtual memory block. This is not a valid address.
- 3. The data type for a _vmhnd_t is an unsigned long.
- However, there is a limit of 64K for the size of the
- block pointed to by a _vmhnd_t.
-
- B._VM_EMS, _VM_XMS, _VM_DISK, _VM_ALLSWAP
- 1.Predefined constants, defined in vmalloc.h that
- specify the type of swap memory to be used.
- a. the final constant is the binary OR of the first
- three.
-
- C._VM_ALLDOS
- 1.If passed as the second parameter to _vheapinit,
- tells the Virtual Memory Manager (VMM) to allocate
- largest contiguous chunk of available DOS memory for
- the swaparea.
-
- D._VM_NULL
- 1.Returned by _vmalloc and _vrealloc. Equivalent to
- NULL for malloc().
-
- E._VM_CLEAN, _VM_DIRTY
- 1.Tells _vload or _vunlock what to do with a
- particular block of virtually allocated memory
- a. _VM_CLEAN will discard the contents, losing any
- changes.
- b. _VM_DIRTY will save all changes to auxiliary
- memory when swapping occurs.
-
- III. Usage Sequence
- A.Before any virtual memory can be allocated the VMM must
- first be initialized via _vheapinit().
- 1.This function is used to specify the type of memory
- to use for a swaparea, and how many paragraphs are
- needed for the swaparea.
-
- 2.The second and third parameters, dosmin and dosmax,
- represent the number of paragraphs(16 bytes) that will
- be available for usage by the VMM.
-
- B._vmalloc() and _vrealloc() can now be called to
- allocate memory from the virtual memory pool.
- 1.Even though _vmalloc takes an unsigned long
- parameter, the maximum size that can be allocated for a
- single block is 64K.
-
- 2.If _vrealloc is called with _VM_NULL the function
- will behave as if a _vmalloc call was used.
-
- 3.When a block is allocated the pertinent page of the
- Virtual Page Table(VPT) is swapped into the swaparea
- and the appropriate entries are made.
-
- 4.Important note: See Section IV.B
-
- C.The handle received from _vmalloc(or _vmrealloc) is now
- used with the _vlock or _vload function to return an
- valid far pointer to the block of virtual memory. Only
- after a call to either of these functions is made will
- there exist a valid pointer to an address that can be
- manipulated.
-
- D.Any blocks loaded but unlocked could be swapped out at
- any time if space is needed in the swaparea by the
- virtual memory manager.
-
- E.Once a block has been locked it will remain in
- conventional memory until unlocked. To free a block after
- locking, call _vunlock for every lock performed on the
- block and then call _vfree().
-
- F.Whenever a _vlock() or _vload() is called there will be
- at least two pages of virtual memory swapped in; the page
- of the VPT and its related page of virtual memory.
-
- G. Finally, when all virtual memory operations have
- been completed or if an abnormal error occurs while
- working with the VMM a call to _vheapterm() must be
- called. If this is not done various system memory
- resources may not be available to subsequent programs.
-
- IV. Important structures of the VMM and related issues
- A. Sizes for the virtual memory environment
- 1. 1 Paragraph = 16 bytes
- 2. 1 Page = 128 Paragraphs = 2048 bytes
-
- B. Granularity of memory allocations
- 1. If size(in bytes) <=1909 then size + 6 bytes are
- allocated. The extra 6 bytes are used by the VMM.
- 2. If size(in bytes) >1915 then [(((size
- +6)/2048)+1)]*2048 bytes are allocated.
- 3. The _vmsize() function will return the exact amount
- of memory allocated to a valid handle.
- a. This function gives the user an accurate picture
- of the memory he/she was given for every call to
- _vmalloc().
-
- C. Location of allocated blocks after a call to
- _vmalloc() or _vrealloc
- 1. When memory is requested by a call to _vmalloc this
- memory is allocated and stored in the virtual memory
- area as a contiguous block. It will not reside in
- physical memory until a call to _vlock() or _vload() is
- made.
-
- D. Location of allocated blocks after a call to _vload()
- or _vlock()
- 1. Only when blocks are loaded or locked are they
- brought into the swaparea, located in physical memory.
- If several blocks are brought into the swaparea and
- then one or two are freed out of order, there is a high
- probability that the swaparea will become fragmented
- into many small chunks of available space. This means
- that it is NOT a good idea to lock more than one block
- at a time. This behavior is similar to what happens to
- the near heap when _nmalloc() and _nfree() calls are
- made out of order.
-
- E. _vheapinit() parameters
- 1. The dosmax and dosmin parameters are based on
- paragraphs, NOT bytes. If a person calls _vheapinit
- with 2048 as the dosmin, he/she is actually requesting
- 32,768 bytes.
-
- F. Virtual page tables and descriptors
- 1. Virtual Page Descriptor(VPD)
- A 16-byte structure that contains information for a
- virtual memory page. Each page used by the VMM has a
- VPD associated with it.
-
- 2. Root Page Table(RPT)
- A table used by the VMM for tracking page
- allocations and addresses thereof. Always found
- above 640K
-
- 3. Virtual Page Table(VPT)
- Also used by the VMM to track all virtual pages
- allocated on initialization. Portions of this table
- will reside in conventional memroy when needed.
-
- V.Important notes and articles
- A.386MAX, version 6.01d(shipped with C7) will not allow
- usage of extended memory by _vmalloc.
- This was a bug with Qualitas and has been fixed in the
- latest revision, version 6.02a. Refer to the Microsoft
- Knowledgebase, article #Q94121.
-
- B.When _VM_DISK is the swaparea, a call to _vfree will
- not free up the disk area. As a result the TMP file will
- continue to grow and eventually fill the entire disk.
- However, memory is still freed and will be swapped out as
- usual. Refer to the Microsoft Knowledgebase, article
- #Q92926.
-
- C.Multiple calls to the pair _vheapinit and _vheapterm
- could corrupt memory and cause unexpected system failure
- or compromise system integrity. Refer to the Microsoft
- Knowledgebase, article #Q92930.
-
- VI. Sample code
- The code below demonstrates the danger of not taking into
- account this unseen allocation granularity.
- The user is attempting to set up the minimum area of
- swaparea that will allow him to lock two 4K blocks. From his
- calculations(4096 * 2) / 16 + some additional paragraphs the
- user determines that 550 paragraphs should be sufficient.
- When he compiles and runs the program it fails to lock the
- second block and dies. What the user has missed is that when
- he allocates 4096 bytes the VMM is actually allocating an
- extra 2K that is never noticed. When he locks/loads this
- block of memory he thinks he has around 4K left for the next
- lock/load when in actuality he has somewhere around 3K left.
- Therefore the next lock fails and the program exits for no
- apparent reason. If he had made a call to _vmsize() he would
- have seen that 6138 bytes were actually attached to handle1.
- The calculation for an adequate swaparea would be (((4K + 6)
- / 2 K) + 1) * 2 K or ~6148. Since he is
- locking two blocks this value needs to be multiplied by 2
- and then some extra paragraphs added for the VPT portions
- that will be swapped in and the PD's that will be residing
- in the first portion of the swaparea.
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <vmemory.h>
-
- void main()
- {
- _vmhnd_t handle1, handle2;
- int _far * buf1;
- int _far * buf2;
-
- //if the dosmax value is equal to 775 or greater the
- program is able to allocate and lock
- // two 4K blocks
-
- if ( !_vheapinit( 0, 550, _VM_XMS | _VM_EMS ) )
- {
- printf( "Could not initialize virtual memory
- manager.\n" );
- exit( -1 );
- }
-
- printf( "Requesting 4096 bytes of virtual memory.\n" );
- if ( (handle1 = _vmalloc( 4096 )) == _VM_NULL )
- {
- printf("\n can't alloc heap1");
- _vheapterm();
- exit( -1 );
- }
- if (( buf1 = (int __far *)_vlock( handle1)) == NULL )
- {
- _vheapterm();
- printf("\n can't lock heap1");
- exit( -1 );
- }
- printf( "Requesting 4096 bytes of virtual memory.\n" );
- if ( (handle2 = _vmalloc( 4096 )) == _VM_NULL )
- {
- printf("\n can't alloc heap2");
- _vheapterm();
- exit( -1 );
- }
- if (( buf2 = (int __far *)_vlock( handle2)) == NULL )
- {
- _vheapterm();
- printf("\n can't lock heap2");
- exit( -1 );
- }
-
- printf("\n checkpoint\n");
- _vunlock( handle1, _VM_CLEAN );
- _vunlock( handle2, _VM_CLEAN );
- _vfree( handle1 );
- _vfree( handle2 );
-
- _vheapterm();
- }
-
-