MBCache.mesa
Edited by Sandman on 6-Aug-81 15:39:33
Edited by Lewis on 17-Sep-81 11:50:33
Edited by Levin on April 5, 1983 2:13 pm
DIRECTORY
Environment USING [wordsPerPage],
Inline USING [LongCOPY, LongDivMod, LongMult],
MB USING [Handle, Zero],
MBStorage USING [FreeWords, Words],
MBVM USING [Base];
MBCache: PROGRAM
IMPORTS Inline, MB, MBStorage
EXPORTS MB, MBVM =
BEGIN
pageSize: CARDINAL = Environment.wordsPerPage;
increment: CARDINAL = pageSize/SIZE[CSElement];
csArray: CSArray;
CSArray: TYPE = LONG DESCRIPTOR FOR ARRAY OF CSElement;
CSElement: TYPE = RECORD [
lp: LONG POINTER,
page: CARDINAL
];
data: MB.Handle ← NIL;
csElements: CARDINAL;
cachePage: CARDINAL;
cacheLP: LONG POINTER;
InitCache: PUBLIC PROC [h: MB.Handle] = {
data ← h;
csArray ← DESCRIPTOR[MBStorage.Words[increment*SIZE[CSElement]], increment];
csArray[0] ← [page: 0, lp: InitPage[]];
csArray[1] ← [page: LAST[CARDINAL], lp: NIL];
csElements ← 2;
cachePage ← LAST[CARDINAL];
cacheLP ← NIL;
};
FinishCache: PUBLIC PROC = {
FOR i: CARDINAL IN [0..csElements) DO MBStorage.FreeWords[csArray[i].lp] ENDLOOP;
MBStorage.FreeWords[BASE[csArray]];
data ← NIL;
};
GetPage: PUBLIC PROC [page: MBVM.Base] RETURNS [LONG POINTER] = {
i, j, h: CARDINAL;
IF page = cachePage THEN RETURN[cacheLP];
IF page = 0 THEN {cachePage ← page; RETURN[cacheLP ← csArray[0].lp]};
i ← 0; j ← csElements-1;
UNTIL i + 1 = j DO
h ← (i+j)/2;
SELECT csArray[h].page FROM
< page => i ← h;
> page => j ← h;
ENDCASE => { -- found at h
cachePage ← page;
cacheLP ← csArray[h].lp;
RETURN[cacheLP]
};
ENDLOOP;
IF csElements = LENGTH[csArray] THEN ExpandArray[];
FOR k: CARDINAL DECREASING IN [i+1..csElements) DO
csArray[k+1] ← csArray[k];
ENDLOOP;
cacheLP ← InitPage[];
cachePage ← page;
csArray[i+1] ← [lp: cacheLP, page: cachePage];
csElements ← csElements+1;
RETURN[cacheLP]
};
ExpandArray: PROC = {
newLength: CARDINAL = LENGTH[csArray] + increment;
newArray: CSArray ←
DESCRIPTOR[MBStorage.Words[newLength*SIZE[CSElement]], newLength];
Inline.LongCOPY[
from: BASE[csArray], to: BASE[newArray], nwords: LENGTH[csArray]*SIZE[CSElement]];
MBStorage.FreeWords[BASE[csArray]];
csArray ← newArray;
};
InitPage: PROC RETURNS [lp: LONG POINTER] = {
lp ← MBStorage.Words[pageSize];
MB.Zero[lp, pageSize];
};
Read: PUBLIC PROC [p: POINTER] RETURNS [UNSPECIFIED] = {
RETURN[LongRead[Inline.LongMult[data.mdsBase, pageSize] + LOOPHOLE[p, CARDINAL]]]};
Write: PUBLIC PROC [p: POINTER, v: UNSPECIFIED] = {
LongWrite[Inline.LongMult[data.mdsBase, pageSize] + LOOPHOLE[p, CARDINAL], v]};
CopyRead: PUBLIC PROC [from, to: POINTER, nwords: CARDINAL] = {
FOR i: CARDINAL IN [0..nwords) DO (to+i)^ ← Read[from+i] ENDLOOP};
CopyWrite: PUBLIC PROC [from, to: POINTER, nwords: CARDINAL] = {
FOR i: CARDINAL IN [0..nwords) DO Write[to+i, (from+i)^] ENDLOOP};
LongRead: PUBLIC PROC [p: LONG UNSPECIFIED] RETURNS [UNSPECIFIED] = {
memPage: MBVM.Base;
offset: CARDINAL;
[quotient: memPage, remainder: offset] ← Inline.LongDivMod[LOOPHOLE[p], pageSize];
RETURN[(GetPage[memPage]+offset)^]
};
LongWrite: PUBLIC PROC [p: LONG UNSPECIFIED, v: UNSPECIFIED] = {
memPage: MBVM.Base;
offset: CARDINAL;
[quotient: memPage, remainder: offset] ← Inline.LongDivMod[LOOPHOLE[p], pageSize];
(GetPage[memPage]+offset)^ ← v;
};
LongCopyRead: PUBLIC PROC [
from: LONG POINTER, to: LONG POINTER, nwords: CARDINAL] = {
FOR i: CARDINAL IN [0..nwords) DO (to+i)^ ← LongRead[from+i] ENDLOOP};
LongCopyWrite: PUBLIC PROC [
from: LONG POINTER, to: LONG POINTER, nwords: CARDINAL] = {
FOR i: CARDINAL IN [0..nwords) DO LongWrite[to+i, (from+i)^] ENDLOOP};
END.