home *** CD-ROM | disk | FTP | other *** search
- $S-,R-,V-,I-,B-,F+,O-,A-}
-
- {*********************************************************}
- {* VMMNGR.PAS 1.00 *}
- {*********************************************************}
-
- unit Vmmngr;
- {-Virtual memory manager}
-
- interface
-
- uses
- Dos,
- OpRoot;
-
- procedure DynArrayStream(SPtr : IdStreamPtr);
- {-Register all types needed for streams containing DynArrays}
-
- const
-
- MaxHeapAlloc = 65521; {Maximum allocation on Turbo Pascal heap}
- DefIncr = 128; {Default value for minimum freelist size incr.}
- DefFreeEntries = 2048; {Default value for number of freelist entries}
- DefQueueEntries = 512; {Default size for Lru queue}
- EmsPage = 16384; {Size of an Ems page}
- NoEms = $FFFF;
- MaxEmsBlock = $FFFF;
- DefDskToKeep = 1048576; {Disk space to keep free - 1meg}
- VmmMark = $FFFF;
-
- {option codes}
- vmDeleteSwap = $0001; {Delete swap file when Done}
- vmUseDsk = $0002; {No more allocation on disk}
- vmUseEms = $0004; {No more allocation in Ems}
- DefVmmOptions : Word = vmUseEms+vmUseDsk+vmDeleteSwap;
- BadVmmOptions : Word = 0;
-
- {masks used to decode VMM descriptors}
- vmInRam = $01; {Dereferenced block is in Ram area}
- vmInEms = $02; {Dereferenced block is in Ems}
- vmOnDsk = $04; {Dereferenced block is on Disk}
- vmLocked = $08; {Dereferenced block is locked in Ram area}
- vmLocation = $07; {Used to isolate location bits}
-
- OutOfHandles = $FFFF;
-
- {--------- object type codes (for streams) ---------}
-
- otDynArray = 53;
- otVMMgr = 54;
-
- {--------- object version codes (for streams) ---------}
-
- veDynArray = 00;
- veVMMgr = 00;
-
- {--------- object error codes ---------}
-
- ecOutOfRamEntries = 08600; {No more entries in RamFreeList}
- ecOutOfEmsEntries = 08601; {No more entries in EmsFreeList}
- ecOutOfDskEntries = 08602; {No more entries in DskFreeList}
- ecOutOfDescEntries = 08603; {No more entries in Descriptor table}
- ecNoResources = 08604; {No resources for virtual memory}
-
- type
-
- {----------- dynamic arrays -------------}
- {-Needed for virtual heap management}
-
- DynArrayPtr = ^DynArray;
- DynArray =
- object(Root)
- daElemSize : Word; {Size of one array element}
- daArraySize : Word; {Actual size of array}
- daInc : Word; {Minimum increment when growing (number of elem.)}
- daMaxIndex : Word; {Maximum number of elements minus 1}
- daValidElems : Word; {Number of valid elements in array}
- daStatus : Word; {Error codes are loaded here}
- daBase : pointer; {Pointer to the array structure}
-
- constructor Init(MaxElements, ElementSize, Incr : Word);
- {-Initialize array}
- destructor Done; virtual;
- {-Destroy array}
- function GetStatus : Word;
- {-Return and reset array status}
- function PeekStatus : Word;
- {-Return array status}
- procedure Error(Code : Word);
- {-Set array Status}
- {...}
- procedure SetElem(Index : Word; var Elem);
- {-Set an array element to a given value; Increase size if necessary}
- procedure GetElem(Index : Word; var Elem);
- {-Return the indexth element}
- function GetElemSize : Word;
- {-Return size of an element}
- {...}
- function GetArraySize : Word;
- {-Return actual size of array}
- function GetMaxIndex : Word;
- {-Return maximum index allowed}
- function GetValidElems : Word;
- {-Return number of valid elements}
- procedure Shrink(ElemNb : Word);
- {-Shrink array size and discard exceding elements}
- procedure Clear;
- {-Reset array to minimum size and discard all elements}
- {...}
- constructor Load(var S : IdStream);
- {-Load a dynamic array from a stream}
- procedure Store(var S : IdStream);
- {-Store a dynamic array in a stream}
- end;
-
- {----------- VMM StaticQueue -------------}
-
- {Add some functionalities to StaticQueue to manage the LRU blocks}
- VmmStaticQueuePtr = ^VmmStaticQueue;
- VmmStaticQueue =
- object(StaticQueue)
- procedure Remove(var Element);
- {-Remove first element found equal to Element from the queue}
- function IsEmpty : Boolean;
- {-Return true if queue is empty}
- end;
-
- {----------- freelists -------------}
-
- FreeRecord =
- record
- OrgPtr : Pointer;
- EndPtr : Pointer;
- end;
- FreeRecordPtr = ^FreeRecord;
-
- {
- In RamFreeLists OrgPtr and EndPtr should be considered as normal pointers.
- In EmsFreeLists the segment part contains the Ems handle and the offset part
- the offset in the 4 pages Ems frame.
- In DskFreeLists OrgPtr and EndPtr should be considered as LongInt pointers
- to the swap file.
- This issue is processed transparently by the virtual methods implemented for
- each kind of freelist.
- }
-
- AbstractFreeListPtr = ^AbstractFreeList;
- AbstractFreeList =
- object(DynArray)
- constructor Init(MaxElements, Incr : Word);
- {-Initialize a dynamic array of FreeRecords}
- function GetFreeEntrySize(Index : Word) : LongInt; virtual;
- {-Return size of a free block}
- {....}
- function SizeToEndPtr(OrgPtr : Pointer;
- BlkSize : LongInt) : Pointer; virtual;
- {-Given OrgPtr and block size, return new entry's EndPtr}
- function SizeToOrgPtr(EndPtr : Pointer;
- BlkSize : LongInt) : Pointer; virtual;
- {-Given EndPtr and block size, return new entry's OrgPtr}
- function PtrIsEqual(P1, P2 : Pointer) : Boolean; virtual;
- {-Return true if pointers can be merged to form a new freelist entry}
- {....}
- function GetFreeEntry(BlkSize : Word) : Pointer;
- {-Search free list for a free block, return a pointer to it}
- function AddFreeEntry(ThisOrgP : Pointer; BlkSize : LongInt) : LongInt;
- {-Insert a new free block in the FreeList or merge it with an }
- { existing one - return size of entry in FreeList}
- procedure RemoveFreeEntry(Index : Word);
- {-Remove entry from the list and shrink list size}
- function MaxFree : Longint;
- {-Return size of largest free entry}
- {....}
- procedure QuickSort(L, R : Word);
- {-Actual sort procedure called by Sort}
- function Sort : Boolean;
- {-Sort the free list in block size order}
- end;
-
- VmmRamFreeListPtr = ^VmmRamFreeList;
- VmmRamFreeList =
- object(AbstractFreeList)
- function GetFreeEntrySize(Index : Word) : LongInt; virtual;
- {-Return size of a free block}
- function SizeToEndPtr(OrgPtr : Pointer;
- BlkSize : LongInt) : Pointer; virtual;
- {-Given OrgPtr and block size, return new entry's EndPtr}
- function SizeToOrgPtr(EndPtr : Pointer;
- BlkSize : LongInt) : Pointer; virtual;
- {-Given EndPtr and block size, return new entry's OrgPtr}
- function PtrIsEqual(P1, P2 : Pointer) : Boolean; virtual;
- {-Return true if pointers can be merged to form a new freelist entry}
- end;
-
- VmmEmsFreeListPtr = ^VmmEmsFreeList;
- VmmEmsFreeList =
- object(AbstractFreeList)
- function AddFreeEntry(ThisOrgP : Pointer; BlkSize : Word) : LongInt;
- {-Insert a new free block in the FreeList or merge it with an }
- { existing one - return size of entry in FreeList}
- function GetFreeEntrySize(Index : Word) : LongInt; virtual;
- {-Return size of a free block}
- function SizeToEndPtr(OrgPtr : Pointer;
- BlkSize : LongInt) : Pointer; virtual;
- {-Given OrgPtr and block size, return new entry's EndPtr}
- function SizeToOrgPtr(EndPtr : Pointer;
- BlkSize : LongInt) : Pointer; virtual;
- {-Given EndPtr and block size, return new entry's OrgPtr}
- function PtrIsEqual(P1, P2 : Pointer) : Boolean; virtual;
- {-Return true if pointers can be merged to form a new freelist entry}
- end;
-
- VmmDskFreeListPtr = ^VmmDskFreeList;
- VmmDskFreeList =
- object(AbstractFreeList)
- function GetFreeEntrySize(Index : Word) : LongInt; virtual;
- {-Return size of a free block}
- function SizeToEndPtr(OrgPtr : Pointer;
- BlkSize : LongInt) : Pointer; virtual;
- {-Given OrgPtr and block size, return new entry's EndPtr}
- function SizeToOrgPtr(EndPtr : Pointer;
- BlkSize : LongInt) : Pointer; virtual;
- {-Given EndPtr and block size, return new entry's OrgPtr}
- function PtrIsEqual(P1, P2 : Pointer) : Boolean; virtual;
- {-Return true if pointers can be merged to form a new freelist entry}
- end;
-
- {--------- descriptor table ------------}
-
- VmmDescriptorTablePtr = ^VmmDescriptorTable;
- VmmDescriptorTable =
- object(DynArray)
- destructor Done; virtual;
- {-Deallocate all Ems handles hold in descriptor table}
- end;
-
- type
-
- {--------- miscellaneous types for vmm ------------}
-
- VmmPtrRec = {Useful to access segment and offset parts of}
- record { a pointer by typecasting}
- Ofs : Word;
- Seg : Word;
- end;
-
- VmmDescriptor = {Describe one element of the VMM descriptor table}
- record
- Location : Byte; {bit 0 : in Ram; bit 1 : in Ems; bit 2 : on disk}
- {bit 3 : locked/unlocked; bits 4-7 : reserved/unused}
- Size : Word; {Size of block}
- case integer of
- 1 : (RamPtr : Pointer); {Block in Ram : use normal pointer}
- 2 : (Offset : Word; {Block in Ems : use Ems handle and offset}
- Handle : Word); { in Ems page frame}
- 3 : (DskPtr : LongInt); {Block is on disk : use long offset in}
- { swap file}
- 4 : (Ptr : Pointer;) {Used when generic pointers are needed}
- end;
-
- VmmHandle = Word;
- VmPtr = Pointer; {Segment part always contains a VmmHandle and}
- { offset part is always $FFFF - used as a test mark}
-
- VmmRamArea = array [0..MaxHeapAlloc] of byte;
- VmmRamAreaPtr = ^VmmRamArea;
-
- GetMemFunc = function(var P; Size : LongInt) : Boolean;
- FreeMemProc = procedure(var P; Size : LongInt);
-
- {--------- Virtual memory manager object description ----------}
-
- type
-
- VMMPtr = ^VMM;
- VMM =
- object(root)
- {....Data....}
- vmRamFreeList : VmmRamFreeList; {Manage blocks in Ram}
- vmEmsFreeList : VmmEmsFreeList; {Manage blocks in Ems}
- vmDskFreeList : VmmDskFreeList; {Manage blocks on Disk}
- vmDescTable : VmmDescriptorTable; {VmmHandles translation table}
- vmLruQueue : VmmStaticQueue; {Manage LRU blocks}
- {----------------------------Ram stuff}
- vmRamArea : VmmRamAreaPtr; {Pointer to RAM area}
- vmRamAreaSize : LongInt; {Size of RAM area}
- {----------------------------Ems stuff}
- vmEmsToKeep : Word; {Number of Ems pages to keep free}
- vmEmsBaseSeg : Word; {Base segment of Ems frame}
- {----------------------------Disk stuff}
- vmDskToKeep : LongInt; {Space to keep free on disk}
- vmEofPtr : LongInt; {Pointer to end of swap file}
- vmSwapFName : PathStr; {Name of swap file}
- vmF : File; {Swap file}
- {----------------------------}
- vmOptions : Word; {Option flags}
- vmStatus : Word; {VMMgr status}
- {....Methods....}
- constructor Init(SwapFName : PathStr);
- {-Create a new virtual memory manager with default options}
- constructor InitCustom(RamSize : LongInt;
- Incr, MaxVmmEntries,
- MaxFreeEntries, VmmQueueEntries,
- EmsPagesToKeep : Word;
- DskToKeep : LongInt;
- SwapFName : PathStr);
- {-Create a new virtual memory manager with custom options}
- destructor Done; virtual;
- {-Destroy a VMM}
- function PeekStatus : Word;
- {-Return VMM status}
- function GetStatus : Word;
- {-Return and reset VMM status}
- procedure Error(Code : Word);
- {-Set VMM Status}
- {...}
- procedure LinkToDerefHandler;
- {-Instruct the dereference interrupt handler to refer to THIS manager}
- {...}
- procedure GetMemV(var Pt; BlkSize : Word);
- {-Allocate a memory block and return a Vmm "pointer" in Pt}
- procedure FreeMemV(var Pt);
- {-Free a block and set Pt to nil}
- function Lock(var Pt; Lockit : Boolean) : Boolean;
- {-Lock or Unlock a VMM block in Ram}
- function GetSize(var Pt) : Word;
- {-Return size of block pointed to by Pt}
- function ClearRamArea : Boolean;
- {-Page out all blocks unless they are locked}
- {...}
- function RamMaxAvail : LongInt;
- {-Return size of the largest block available in Ram}
- function EmsMaxAvail : LongInt;
- {-Return amount of memory available in Ems}
- function DskMaxAvail : LongInt;
- {-Return amount of space available on Disk}
- {...}
- procedure vmOptionsOn(OptionFlags : Word);
- {-Activate multiple options}
- procedure vmOptionsOff(OptionFlags : Word);
- {-Deactivate multiple options}
- function vmOptionsAreOn(OptionFlags : Word) : Boolean;
- {-Return true if all specified options are on}
- {+++ Internal methods +++}
- function PageOut(SizeNeeded : LongInt) : Boolean;
- {-Page out until "SizeNeeded" bytes become available in the Ram area}
- function GetHandle : Word;
- {-Return a valid VMM handle}
- end;
-
- {--------- Dereference function inline definition ---------}
-
- function VmmDrf(P : Pointer) : Pointer;
- {-Call the dereference handler}
- inline(
- $5B/ {pop bx ;BX = Offset part of P}
- $58/ {pop ax ;AX = Segment part of P}
- $CD/$66); {int 66h ;Call INT 66}
- {the pointer will be returned in DX:AX}
-
- var
- UserGetMem : GetMemFunc; {User-defined routines for standard memory}
- UserFreeMem : FreeMemProc;{ allocation and deallocation}
-
- {======================================================================}
-
- implementation
-
- uses
- OpInline,
- OpSort,
- OpEms;
-
- {--------- Virtual memory manager globals ----------}
- var
- VmmActiveMgr : VMMPtr; {Pointer to the active virtual memory manager}
- { Set by LinkToDerefHandler}
- VmmEmsInstalled : Boolean; {True if EMM driver is installed}
- VmmSaveIntUsed : Pointer; {Used to save previous value of int vector}
- VmmExitSave : Pointer; {Used to save ExitProc}
- VmmInstances : DynArray; {Keeps track of any instance of VMMgr}
- const
- VmmIntUsed = $66; {Use Int 66h to dereference VMM pointers}
- VmmRamAreaSizeGlb : LongInt = 0; {Cumulates all Ram area sizes}
-
- {
- Interrupt $66 is one of the user-definable interrupts described by IBM. If
- this interrupt conflicts with your environment, you may change VmIntUsed to
- use a different interrupt. User-definable interrupts range from $60 to $66.
- ($67 is used for EMS, so it should be avoided here.)
- ┌─────────────────────────────────────────────────────────────────────────┐
- │If you change the interrupt, be sure to modify the VmmDrf inline function│
- │as well. │
- └─────────────────────────────────────────────────────────────────────────┘
- }
-
- {$I VMM.IN1} {Inline macros}
- {$I VMM.IN2} {Data objects needed by VMMgr}
- {$I VMM.IN3} {Virtual memory manager public routines}
- {$I VMM.IN4} {Virtual memory manager internal routines}
-
- procedure VmmExit;
- {-Reset the interrupt vector used by VMM to its previous value}
- begin
- ExitProc := VmmExitSave;
- SetIntVec(VmmIntUsed, VmmSaveIntUsed);
- end;
-
- begin
- {Initialize the dereference interrupt handler}
- VmmExitSave := ExitProc;
- ExitProc := @VmmExit;
- GetIntVec(VmmIntUsed, VmmSaveIntUsed);
- SetIntVec(VmmIntUSed, @DerefHandler);
- VmmEmsInstalled := EmsInstalled;
- {Default memory management routines on TP heap are VmmGetMem and VmmFreeMem}
- UserGetMem := VmmGetMem;
- UserFreeMem := VmmFreeMem;
- if not VmmInstances.Init(255, SizeOf(Pointer), 1) then;
- end.