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.