-- ZoneIndicesImpl.Mesa
-- last edited May 20, 1982 1:05 pm by Paul Rovner

DIRECTORY
  RTTypesBasic USING[Type],
  RTOS USING[PermanentPageZone],
  RTRefCounts USING[StuffMapSziSz],
  RTZones;

ZoneIndicesImpl: MONITOR    -- protects ziNext and sziNext
  IMPORTS RTOS, RTRefCounts, RTZones
  EXPORTS RTZones
= BEGIN OPEN RTZones;

-- Types
  Type: TYPE = RTTypesBasic.Type;

-- Errors
  TooManyZones: PUBLIC ERROR = CODE;

-- Global variable
  ziNext: ZoneIndex;
  sziNext: SubZoneIndex ← 1;
  nZiMax: ZoneIndex ← nZiMaxInit;
  nSziMax: SubZoneIndex ← nSziMaxInit;
  MapSziSz: PUBLIC TMapSziSz;

-- PUBLIC procedures

  GetZiNext: PUBLIC ENTRY PROCEDURE RETURNS[zi: ZoneIndex] =
    { RETURN[ziNext]};

  GetSZiNext: PUBLIC ENTRY PROCEDURE RETURNS[szi: SubZoneIndex] =
    { RETURN[sziNext]};

  GetnZiMax: PUBLIC ENTRY PROCEDURE RETURNS[zi: ZoneIndex] =
    { RETURN[nZiMax]};

  GetnSziMax: PUBLIC ENTRY PROCEDURE RETURNS[szi: SubZoneIndex] =
    { RETURN[nSziMax]};

  AssignSz: PUBLIC ENTRY PROCEDURE[szi: SubZoneIndex, sz: SubZone] =
    { MapSziSz[szi] ← sz};

	-- called by AllocZoneImpl from its START code.
  SetZiNext: PUBLIC ENTRY PROCEDURE[zi: ZoneIndex] =
    { ziNext ← zi};

  AllocateZi: PUBLIC ENTRY PROCEDURE RETURNS[zi: ZoneIndex] =
    BEGIN ENABLE UNWIND => NULL;
      IF ziNext = nZiMax THEN
        { FOR zi IN [1..nZiMax] DO IF MapZiZn[zi] = NIL THEN RETURN[zi] ENDLOOP;
          ERROR TooManyZones};
      zi ← ziNext;
      ziNext ← ziNext+1;
    END;

  AllocateSzi: PUBLIC ENTRY PROCEDURE RETURNS[szi: SubZoneIndex] =
    BEGIN ENABLE UNWIND => NULL;
      IF sziNext = nSziMax THEN
        { FOR szi IN [1..nSziMax] DO IF MapSziSz[szi] = NIL THEN RETURN[szi] ENDLOOP;
          ERROR TooManyZones};
      szi ← sziNext;
      sziNext ← sziNext+1;
    END;


-- START code

  MapSziSz ← RTOS.PermanentPageZone.NEW[RMapSziSz[nSziMaxInit]];
  RTRefCounts.StuffMapSziSz[MapSziSz];

END.