home *** CD-ROM | disk | FTP | other *** search
- Unit STI_VM;
- {$S-,R-,V-,B-,D-}
- interface
-
- Const
- ALL_OK = 0; {no errors }
- BAD_VM_ID = -1; {the id is bad, allocated or no }
- PAGE_SIZE_TOO_BIG = -2; {the page size is too large }
- PAGE_SIZE_TOO_SMALL = -3; {the page size is too small }
- CACHE_SIZE_TOO_BIG = -4; {the cache size is too alrge }
- CACHE_SIZE_TOO_SMALL = -5; {the cache is too small }
- FILE_CREATE_ERROR = -6; {couldn't create the swap file }
- OUT_OF_MEMORY = -7; {out of convebtional memory }
- BAD_PAGE_NUMBER = -8; {there are no pages of this # }
-
- MAX_VM_FILES = 10; {maximum number of files }
- MEM_PAGES = 4096; {maximum number of resident page}
- MAX_PAGE_SIZE = 65535; {maximum page size }
- MAX_PAGES = 65535; {maximum number of pages }
-
-
-
- function STI_VM_Flush_Cache(ID : Byte) : shortint;
- function STI_VM_Open(ID : byte; Swap : string; Page_Size, Cache : word) : shortint;
- function STI_VM_ReOpen(ID : byte; Swap : string) : shortint;
- function STI_VM_Allocate(ID : byte; Var Point) : longint;
- function STI_VM_Demand(ID : byte; Var Point; PageNo : word) : shortint;
- function STI_VM_Rollback(ID : byte; Var Point; PageNo : word) : shortint;
- function STI_VM_Close(ID : byte; EraseFile : boolean) : shortint;
- function STI_VM_Hit_Rate : real;
- procedure STI_VM_Init; {initialise the virtual memory }
- procedure STI_VM_Log_Cache(B : boolean);
-
-
- implementation
-
- Type
- One_Page = record {one page }
- Access : word;
- Data : pointer; {data of the page }
- PageID : word; {page ID }
- end;
-
- One_Set = array[1..MEM_PAGES] of One_Page;{one page buffer }
-
- One_SYS = record
- File_Name : string; {swap file name }
- FileP : file; {file pointer }
- Page_Size : word; {size of the page }
- No_Pages : word; {number of cached pages }
- Tot_pages : word; {total number of pages }
- Used : boolean; {is this system used }
- Cache : ^One_Set; {cache for this system }
- end;
- All_SYS = array[1..MAX_VM_FILES] of One_SYS; {the complete buffer }
-
- Var
- Pages : All_SYS; {this is it folks }
- Log : Boolean;
- Tries,
- Hits : real;
-
- {---------------------------------------------------------------------------}
-
- function Lowest_Access(ID : byte) : word;
-
- var
- Loop,
- Temp1,
- Temp2 : word;
-
- begin
- Temp1 := 65535;
- Temp2 := 1;
- for Loop := 1 to Pages[ID].No_Pages do
- begin
- if Pages[ID].Cache^[Loop].Access < Temp1 then
- begin
- Temp1 := Pages[ID].Cache^[Loop].Access;
- Temp2 := Loop;
- end;
- end;
- Lowest_Access := Temp2;
- end;
-
- {---------------------------------------------------------------------------}
-
- procedure Write_Out(ID : byte; VirtualPage,LogicalPage : word);
-
- begin
- seek(Pages[ID].FileP,1 + ((VirtualPage-1) * (Pages[ID].Page_Size div 128)));
- blockwrite(Pages[ID].FileP,Pages[ID].Cache^[LogicalPage].Data^,Pages[ID].Page_Size div 128);
- end;
-
- {---------------------------------------------------------------------------}
-
- procedure Read_In(ID : byte; VirtualPage,LogicalPage : word);
-
- begin
- seek(Pages[ID].FileP,1 + ((VirtualPage-1) * (Pages[ID].Page_Size div 128)));
- blockread(Pages[ID].FileP,Pages[ID].Cache^[LogicalPage].Data^,Pages[ID].Page_Size div 128);
- end;
-
- {---------------------------------------------------------------------------}
-
- function STI_VM_Flush_Cache(ID : Byte) : shortint;
-
- Var
- Loop : word;
-
- begin
- if not(Pages[ID].Used) then {check if this system is used }
- begin
- STI_VM_Flush_Cache := BAD_VM_ID; {yes return a bad ID error }
- Exit; {and get out of here }
- end;
- for loop := 1 to Pages[ID].No_Pages do {loop & write them to disk }
- begin
- if Pages[ID].Cache^[Loop].PageID > 0 then
- Write_Out(ID,Pages[ID].Cache^[Loop].PageID,loop);
- end;
- end;
-
- {---------------------------------------------------------------------------}
-
- function STI_VM_Open(ID : byte; Swap : string; Page_Size, Cache : word) : shortint;
-
- Var
- Loop : word;
- Dummy : string;
- Header : String;
-
- begin
- if Page_Size > 128 then
- begin
- if (Page_Size mod 128) > 0 then
- Page_Size := Page_Size + (128 - (Page_Size mod 128));
- end
- else
- Page_Size := 128;
- if Pages[ID].Used then {check if this system is used }
- begin
- STI_VM_Open := BAD_VM_ID; {yes return a bad ID error }
- Exit; {and get out of here }
- end;
- if Page_Size > MAX_PAGE_SIZE then {check if page size is ok }
- begin
- STI_VM_Open := PAGE_SIZE_TOO_BIG; {no return a bad page size err}
- Exit; {and get out of here }
- end;
- if Page_Size < 1 then {check if page size is ok }
- begin
- STI_VM_Open := PAGE_SIZE_TOO_SMALL; {no return a bad page size err}
- Exit; {and get out of here }
- end;
- if Cache > MEM_PAGES then {check if cache size is ok }
- begin
- STI_VM_Open := CACHE_SIZE_TOO_BIG; {no return a cache size err }
- Exit; {and get out of here }
- end;
- if Cache < 1 then {check if cache size is ok }
- begin
- STI_VM_Open := CACHE_SIZE_TOO_SMALL; {no return a cache size err }
- Exit; {and get out of here }
- end;
- if MaxAvail < (Cache * Page_Size) then {check if enough memory }
- begin
- STI_VM_Open := OUT_OF_MEMORY; {no return a memory error }
- Exit; {and get out of here }
- end;
- {from here everything SHOULD be}
- {ok, so do minimal checking }
-
- Pages[ID].File_Name := Swap; {let the file name = this }
- assign(Pages[ID].FileP,Swap); {initialise the file name }
- {$I-} {turn off I/O checking }
- rewrite(Pages[ID].FileP); {try to create the file }
- if IOResult <> 0 then {check if file make is ok }
- begin
- STI_VM_Open := FILE_CREATE_ERROR; {no return a bad file make err}
- {$I+}
- Exit; {and get out of here }
- end;
- {$I+}
- Pages[ID].Used := TRUE; {this is used }
- Pages[ID].No_Pages := Cache; {the number of cached pages }
- Pages[ID].Page_Size := Page_Size; {set the page size }
- getmem(Pages[ID].Cache,Cache*sizeof(One_Page));
- for Loop := 1 to Cache do {loop over the pages }
- begin
- Pages[ID].Cache^[Loop].PageID := 0; {default assignment }
- getmem(Pages[ID].Cache^[Loop].Data,Page_Size); {get the memory }
- end;
- STI_VM_Open := ALL_OK; {everthing is fine here folks }
- FillChar(Header[1],128,#32);
- Dummy := '';
- Dummy := Dummy + char(hi(Pages[ID].Page_Size));
- Dummy := Dummy + char(lo(Pages[ID].Page_Size));
- Dummy := Dummy + char(hi(Pages[ID].No_Pages));
- Dummy := Dummy + char(lo(Pages[ID].No_Pages));
- Dummy := Dummy + char(hi(Pages[ID].Tot_Pages));
- Dummy := Dummy + char(lo(Pages[ID].Tot_Pages));
- Header := 'Virtual Memory Management System.'+#13#10+'Copyright (C) 1990 By Software Technology International' +
- #26+Dummy + Header;
- seek(Pages[ID].FileP,0);
- blockwrite(Pages[ID].FileP,Header,1);
- end;
-
- {---------------------------------------------------------------------------}
-
- function STI_VM_ReOpen(ID : byte; Swap : string) : shortint;
-
- Var
- Temp1,
- Temp2,
- Temp3,
- Temp4,
- Loop : word;
- Dummy : string[8];
- Header : String;
-
- begin
- if Pages[ID].Used then {check if this system is used }
- begin
- STI_VM_ReOpen := BAD_VM_ID; {yes return a bad ID error }
- Exit; {and get out of here }
- end;
- Pages[ID].File_Name := Swap; {let the file name = this }
- assign(Pages[ID].FileP,Swap); {initialise the file name }
- {$I-} {turn off I/O checking }
- reset(Pages[ID].FileP); {try to create the file }
- if IOResult <> 0 then {check if file make is ok }
- begin
- STI_VM_ReOpen := FILE_CREATE_ERROR; {no return a bad file make err}
- {$I+}
- Exit; {and get out of here }
- end;
- {$I+}
-
- seek(Pages[ID].FileP,0);
- blockread(Pages[ID].FileP,Header,1);
- Temp1 := (ord(Header[94]) * 256) + ord(Header[95]); {cache}
- Temp2 := (ord(Header[92]) * 256) + ord(Header[93]); {page size}
- Temp3 := (ord(Header[96]) * 256) + ord(Header[97]); {tot pages}
- Temp4 := (ord(Header[98]) * 256) + ord(Header[99]); {replace}
-
- if MaxAvail < (Temp1 * Temp2) then {check if enough memory }
- begin
- STI_VM_ReOpen := OUT_OF_MEMORY; {no return a memory error }
- Exit; {and get out of here }
- end;
- {from here everything SHOULD be}
- {ok, so do minimal checking }
-
- Pages[ID].Used := TRUE; {this is used }
- Pages[ID].No_Pages := Temp1; {the number of cached pages }
- Pages[ID].Page_Size := Temp2; {set the page size }
- Pages[ID].Tot_Pages := Temp3;
- getmem(Pages[ID].Cache,Temp1*sizeof(One_Page));
- for Loop := 1 to Temp1 do {loop over the pages }
- begin
- Pages[ID].Cache^[Loop].PageID := 0; {default assignment }
- getmem(Pages[ID].Cache^[Loop].Data,Temp2); {get the memory }
- end;
- STI_VM_ReOpen := ALL_OK; {everthing is fine here folks }
- end;
-
- {---------------------------------------------------------------------------}
-
- function STI_VM_Allocate(ID : byte; Var Point) : longint;
-
- Var
- Temp : word;
- ThisP : pointer absolute Point;
-
- begin
- if not(Pages[ID].Used) then {is this a valid system }
- begin
- STI_VM_Allocate := BAD_VM_ID; {no, return an error and escape }
- Exit;
- end;
- Temp := Lowest_Access(ID);
- if Pages[ID].Cache^[Temp].PageID = 0 then
- begin
- inc(Pages[ID].Tot_Pages);
- Pages[ID].Cache^[Temp].PageID := Pages[ID].Tot_Pages;
- Pages[ID].Cache^[Temp].Access := 65535;
- FillChar(Pages[ID].Cache^[Temp].Data^,Pages[ID].Page_Size,#32);
- ThisP := Pages[ID].Cache^[Temp].Data;
- STI_VM_Allocate := Pages[ID].Tot_Pages;
- end
- else
- begin
- Write_Out(ID,Pages[ID].Cache^[Temp].PageID,Temp);
- inc(Pages[ID].Tot_Pages);
- Pages[ID].Cache^[Temp].PageID := Pages[ID].Tot_Pages;
- Pages[ID].Cache^[Temp].Access := 65535;
- FillChar(Pages[ID].Cache^[Temp].Data^,Pages[ID].Page_Size,#32);
- ThisP := Pages[ID].Cache^[Temp].Data;
- STI_VM_Allocate := Pages[ID].Tot_Pages;
- end;
- end;
-
- {---------------------------------------------------------------------------}
-
- function STI_VM_Demand(ID : byte; Var Point; PageNo : word) : shortint;
-
- Var
- Found : boolean;
- Loop,
- temp : word;
- ThisP : pointer absolute Point;
-
- begin
- if not(Pages[ID].Used) then {is this a valid system }
- begin
- STI_VM_Demand := BAD_VM_ID; {no, return an error and escape }
- Exit;
- end;
- if Pages[ID].Tot_Pages < PageNo then {is this a valid page number }
- begin
- STI_VM_Demand := BAD_PAGE_NUMBER; {no, return an error and escape }
- Exit;
- end;
- Found := FALSE;
- if Log then
- Tries := Tries + 1;
- for Loop := 1 to Pages[ID].No_Pages do
- begin
- if Pages[ID].Cache^[Loop].PageID = PageNo then
- begin
- if Log then
- Hits := Hits + 1;
- ThisP := Pages[ID].Cache^[Loop].Data;
- Found := TRUE;
- if Pages[ID].Cache^[Loop].Access < 65535 then
- Inc(Pages[ID].Cache^[Loop].Access);
- end else
- if Pages[ID].Cache^[Loop].Access > 0 then
- Dec(Pages[ID].Cache^[Loop].Access);
- end;
- if Found then
- begin
- STI_VM_Demand := ALL_OK;
- Exit;
- end;
- Temp := Lowest_Access(ID);
- if Pages[ID].Cache^[Temp].PageID = 0 then
- begin
- Read_In(ID,PageNo,Temp);
- Pages[ID].Cache^[Temp].PageID := PageNo;
- Pages[ID].Cache^[Temp].Access := 65535;
- ThisP := Pages[ID].Cache^[Temp].Data;
- STI_VM_Demand := ALL_OK;
- end
- else
- begin
- Write_Out(ID,Pages[ID].Cache^[Temp].PageID,Temp);
- Read_In(ID,PageNo,Temp);
- Pages[ID].Cache^[Temp].PageID := PageNo;
- Pages[ID].Cache^[Temp].Access := 65535;
- ThisP := Pages[ID].Cache^[Temp].Data;
- STI_VM_Demand := ALL_OK;
- end;
- end;
-
- {---------------------------------------------------------------------------}
-
- function STI_VM_Rollback(ID : byte; Var Point; PageNo : word) : shortint;
-
- Var
- Logic : word;
- temp : word;
- ThisP : pointer absolute Point;
-
- begin
- if not(Pages[ID].Used) then {is this a valid system }
- begin
- STI_VM_Rollback := BAD_VM_ID; {no, return an error and escape }
- Exit;
- end;
- if Pages[ID].Tot_Pages < PageNo then {is this a valid page number }
- begin
- STI_VM_Rollback := BAD_PAGE_NUMBER; {no, return an error and escape }
- Exit;
- end;
- Logic := 0;
- for Temp := 1 to Pages[ID].No_Pages do
- begin
- if Pages[ID].Cache^[Temp].PageID = PageNo then
- Logic := Temp;
- end;
- if Logic = 0 then {is this a valid page number }
- begin
- STI_VM_Rollback := BAD_PAGE_NUMBER; {no, return an error and escape }
- Exit;
- end;
- Temp := Lowest_Access(ID);
- if Pages[ID].Tot_Pages < Logic then {no page to roll back }
- begin
- STI_VM_RollBack := All_OK;
- Exit;
- end
- else
- begin
- Read_In(ID,PageNo,Logic);
- STI_VM_Rollback := ALL_OK;
- end;
- end;
-
- {---------------------------------------------------------------------------}
-
- function STI_VM_Close(ID : byte; EraseFile : boolean) : shortint;
-
- Var
- loop : word;
- dummys : shortint;
- dummy : string;
- header : string;
-
- begin
- if not(Pages[ID].Used) then {is this a valid system }
- begin
- STI_VM_Close := BAD_VM_ID; {no, return an error and escape }
- Exit;
- end;
- dummys := STI_VM_Flush_Cache(ID);
- FillChar(Header[1],128,#32);
- Dummy := '';
- Dummy := Dummy + char(hi(Pages[ID].Page_Size));
- Dummy := Dummy + char(lo(Pages[ID].Page_Size));
- Dummy := Dummy + char(hi(Pages[ID].No_Pages));
- Dummy := Dummy + char(lo(Pages[ID].No_Pages));
- Dummy := Dummy + char(hi(Pages[ID].Tot_Pages));
- Dummy := Dummy + char(lo(Pages[ID].Tot_Pages));
- Header := 'Virtual Memory Management System.'+#13#10+'Copyright (C) 1990 By Software Technology International' +
- #26 + Dummy + Header;
- seek(Pages[ID].FileP,0);
- blockwrite(Pages[ID].FileP,Header,1);
- Close(Pages[ID].FileP);
- if EraseFile then
- Erase(Pages[ID].FileP);
- Pages[ID].File_Name := ''; {null the swap file name }
- Pages[ID].Used := FALSE; {set to unused }
- Pages[ID].Tot_Pages := 0; {number of pages in the system }
- for loop := 1 to Pages[ID].No_Pages do {loop on memeory resident pages }
- begin
- freemem(Pages[ID].Cache^[loop].Data,Pages[ID].Page_Size);
- Pages[ID].Cache^[loop].Data := NIL; {null the pointer }
- Pages[ID].Cache^[loop].PageID := 0; {null the page ID }
- Pages[ID].Cache^[loop].Access := 0; {null the access counter }
- end;
- freemem(Pages[ID].Cache,Pages[ID].No_Pages*sizeof(One_Page));
- Pages[ID].No_Pages := 0; {no pages cached }
- Pages[ID].Page_Size := 128; {default page size }
- STI_VM_Close := ALL_OK;
- end;
-
- {---------------------------------------------------------------------------}
-
- function STI_VM_Hit_Rate : real;
-
- begin
- STI_VM_Hit_Rate := (Hits / Tries) * 100;
- end;
-
- {---------------------------------------------------------------------------}
-
- procedure STI_VM_Log_Cache(B : boolean);
-
- begin
- Log := B;
- Hits := 0;
- Tries := 0;
- end;
-
- {---------------------------------------------------------------------------}
-
- procedure STI_VM_Init; {initialise the virtual memory }
-
- Var
- loop1, {general loop variables }
- loop2 : word;
-
- begin
- Log := FALSE;
- Hits := 0;
- Tries := 0;
- for loop1 := 1 to MAX_VM_FILES do {loop over all the systems }
- begin
- Pages[loop1].File_Name := ''; {null the swap file name }
- Pages[loop1].Used := FALSE; {set to unused }
- Pages[loop1].Tot_Pages := 0; {number of pages in the system }
- Pages[loop1].No_Pages := 0; {no pages cached }
- Pages[loop1].Page_Size := 128; {defaultpage size }
- Pages[loop1].Cache := NIL; {null the pointer }
- end;
- end;
-
- {---------------------------------------------------------------------------}
-
- begin
- STI_VM_Init;
- end.
-
-
-
-