-- RTStorageAccountingImpl.Mesa
-- last edited May 27, 1982 4:18 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
  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.