-- File: DynamicZoneCold.mesa -- Last edited by Levin: 6-Oct-80 8:33:18 DIRECTORY AltoDefs USING [PageSize], DynamicZone USING [PageCount], DynamicZonePrivate USING [ AllocateNode, AllocProcs, DeallocateNode, GetPages, MDSZoneHandle, MDSZoneObject, SegTypeIndex], FSPDefs USING [DestroyZone, MakeNewZone, PruneZone, ZonePointer], SegmentDefs USING [DataSegmentType, HeapDS], Storage USING [FreePages], StringDefs USING [AppendString], SystemDefs USING [HeapZone]; DynamicZoneCold: MONITOR IMPORTS DynamicZonePrivate, FSPDefs, Storage, StringDefs, SystemDefs EXPORTS DynamicZone = BEGIN OPEN DynamicZone, DynamicZonePrivate, FSPDefs, SegmentDefs; -- Global Variables -- sysZone: MDSZone; allocProcs: AllocProcs; availableTypes: PACKED ARRAY SegTypeIndex OF BOOLEAN; rover: SegTypeIndex; -- Miscellaneous Declarations -- ZoneStillInUse: ERROR = CODE; -- Externally Visible Procedures -- InitializeZones: PUBLIC ENTRY PROCEDURE = -- must be called before any other procedures in this interface. BEGIN availableTypes ← ALL[TRUE]; rover ← LAST[SegTypeIndex]; allocProcs ← [AllocateNode, DeallocateNode]; sysZone ← InitZone[SystemDefs.HeapZone[], HeapDS, NIL]; END; FinalizeZones: PUBLIC ENTRY PROCEDURE = -- caled to clean up zone allocator. Note: it is the client's responsibility -- to destroy any zones previously created with CreateZone. BEGIN tempZone: MDSZone = sysZone; FOR segIndex: SegTypeIndex IN SegTypeIndex DO IF ~availableTypes[segIndex] THEN RETURN WITH ERROR ZoneStillInUse; ENDLOOP; tempZone.FREE[@LOOPHOLE[sysZone, MDSZoneHandle]]; END; CreateZone: PUBLIC PROCEDURE [initialPages: PageCount ← 1, id: STRING ← NIL] RETURNS [MDSZone] = -- creates a new zone whose allocation behavior is determined by 'initialPages'. -- 'id' is for assistance in debugging. BEGIN segType: DataSegmentType = AllocateSegmentType[]; fspZone: ZonePointer ← MakeNewZone[ base: GetPages[initialPages, segType], length: initialPages*AltoDefs.PageSize, deallocate: Storage.FreePages]; RETURN[InitZone[fspZone, segType + 1, id]]; END; TooManyZones: PUBLIC ERROR = CODE; SystemZone: PUBLIC PROCEDURE RETURNS [MDSZone] = -- returns the shared system zone BEGIN RETURN[sysZone] END; DestroyZone: PUBLIC PROCEDURE [zone: MDSZone] = -- unconditionally destroys the zone. It is the client's responsibility to ensure -- that no dangling pointers remain. BEGIN z: MDSZoneHandle = LOOPHOLE[zone]; FreeSegmentType[z.segType]; FSPDefs.DestroyZone[z.fspZone]; END; PruneZone: PUBLIC PROCEDURE [zone: MDSZone] = -- attempts to eliminate excessive space allocated to the zone. BEGIN [] ← FSPDefs.PruneZone[LOOPHOLE[zone, MDSZoneHandle].fspZone]; END; -- Internal Procedures -- InitZone: PROCEDURE [fspZone: ZonePointer, segType: DataSegmentType, id: STRING] RETURNS [MDSZone] = BEGIN tempZoneObject: MDSZoneObject ← MDSZoneObject[ procs: @allocProcs, fspZone: fspZone, segType: segType, id: NIL]; tempZone: MDSZone = LOOPHOLE[@tempZoneObject]; zone: MDSZoneHandle = tempZone.NEW[MDSZoneObject]; IF id ~= NIL AND id.length ~= 0 THEN BEGIN tempZoneObject.id ← tempZone.NEW[StringBody[id.length]]; StringDefs.AppendString[tempZoneObject.id, id]; END; zone↑ ← tempZoneObject; RETURN[LOOPHOLE[zone]] END; AllocateSegmentType: ENTRY PROCEDURE RETURNS [DataSegmentType] = BEGIN last: SegTypeIndex = rover; DO rover ← IF rover = LAST [SegTypeIndex] THEN FIRST[SegTypeIndex] ELSE SUCC[rover]; IF rover = last THEN EXIT; IF availableTypes[rover] THEN {availableTypes[rover] ← FALSE; RETURN[rover*2]}; ENDLOOP; RETURN WITH ERROR TooManyZones; END; FreeSegmentType: ENTRY PROCEDURE [segType: DataSegmentType] = BEGIN availableTypes[segType/2] ← TRUE; END; END.