-- RTStorageAccountingImpl.Mesa
-- last edited March 1, 1983 4:36 pm by Paul Rovner

DIRECTORY
PSB USING[PsbIndex],
RTOS USING[PermanentPageZone],
RTProcess USING[HandleToPSBI, Handle, InvalidProcess],
RTRefCounts USING[nWordsReclaimed],
RTStorageAccounting USING[defaultCollectionInterval, PSBIMap, CellCount],
SafeStorage USING[],
Space USING [Handle, GetHandle, PageFromLongPointer, GetAttributes,
DeleteSwapUnits, CreateUniformSwapUnits];

RTStorageAccountingImpl: MONITOR -- Protects the storage account books
IMPORTS RTOS, RTProcess, RTRefCounts, Space
EXPORTS RTProcess, RTStorageAccounting, SafeStorage
= BEGIN OPEN RTStorageAccounting;

-- TYPES

-- VARIABLES
nWordsRequested: PUBLIC LONG CARDINAL ← 0;
nWordsAllocated: PUBLIC LONG CARDINAL ← 0; -- >= CollectionInterval implies collect
SUMnWordsAllocated: PUBLIC LONG CARDINAL ← 0;
nObjectsCreated: PUBLIC LONG CARDINAL ← 0;
MapPsbiToWordsAllocated: PUBLIC LONG POINTER TO PSBIMap;

CollectionInterval: PUBLIC LONG INTEGER ← defaultCollectionInterval;
SuspensionThreshold: PUBLIC LONG INTEGER ← ComputeSuspensionThreshold[];

--PROCS

ComputeSuspensionThreshold: PROC RETURNS[LONG INTEGER] =
{RETURN[CollectionInterval+CollectionInterval]};

CellsAllocated: PUBLIC ENTRY PROC[h: RTProcess.Handle] RETURNS[LONG INTEGER] =
{ENABLE UNWIND => NULL;
{psbi: PSB.PsbIndex ← RTProcess.HandleToPSBI[h
! RTProcess.InvalidProcess => GOTO invalidProcess];
RETURN[MapPsbiToWordsAllocated.elements[psbi].total
+ MapPsbiToWordsAllocated.elements[psbi].current];
EXITS invalidProcess => RETURN[0]}
};

NWordsAllocated: PUBLIC ENTRY SAFE PROC RETURNS[LONG CARDINAL] =
TRUSTED {ENABLE UNWIND => NULL;
RETURN[SUMnWordsAllocated + nWordsAllocated]};

NWordsReclaimed: PUBLIC SAFE PROC RETURNS[LONG CARDINAL] =
TRUSTED {RETURN[RTRefCounts.nWordsReclaimed]};

SetCollectionInterval: PUBLIC ENTRY SAFE PROC[newInterval: LONG CARDINAL]
RETURNS[oldInterval: LONG CARDINAL] =
TRUSTED {ENABLE UNWIND => NULL;
oldInterval ← CollectionInterval;
CollectionInterval ← newInterval;
SuspensionThreshold ← ComputeSuspensionThreshold[]};

ResetNWordsAllocated: PUBLIC ENTRY PROC =
{ENABLE UNWIND => NULL;
SUMnWordsAllocated ← SUMnWordsAllocated + nWordsAllocated;
nWordsAllocated ← 0;
FOR i: PSB.PsbIndex IN PSB.PsbIndex
DO MapPsbiToWordsAllocated.elements[i].total
← MapPsbiToWordsAllocated.elements[i].total
+ MapPsbiToWordsAllocated.elements[i].current;
MapPsbiToWordsAllocated.elements[i].current ← 0;
ENDLOOP};

ResetTotalNWordsAllocatedOnly: PUBLIC ENTRY PROC =
{SUMnWordsAllocated ← SUMnWordsAllocated + nWordsAllocated;
nWordsAllocated ← 0};


-- START HERE

MapPsbiToWordsAllocated ← RTOS.PermanentPageZone.NEW[PSBIMap[LAST[PSB.PsbIndex]+1]];

{OPEN Space;
h: Handle ← GetHandle[PageFromLongPointer[MapPsbiToWordsAllocated]];
UNTIL Space.GetAttributes[h].mapped DO h ← Space.GetAttributes[h].parent; ENDLOOP;
DeleteSwapUnits[h];
CreateUniformSwapUnits[size: 1, parent: h]};

FOR i: PSB.PsbIndex IN PSB.PsbIndex
DO MapPsbiToWordsAllocated.elements[i] ← [total: 0, current: 0];
ENDLOOP;

END.