-- SegmentsB.Mesa Edited by Sandman on July 1, 1980 11:14 AM -- Copyright Xerox Corporation 1979, 1980 DIRECTORY AltoDefs USING [MaxVMPage, PageNumber, PageSize, PagesPerMDS], AltoFileDefs USING [eofDA, vDA], InlineDefs USING [COPY], NucleusOps USING [], Region USING [Handle, Index, Page, PagesPerRegion, PageStatus], SegmentDefs USING [ AccessOptions, AddressFromPage, AllocInfo, DataSegmentAddress, DataSegmentHandle, DefaultBase, DefaultMDSBase, DefaultPages, DeleteDataSegment, EasyDown, EasyUp, FileAccessError, FileHandle, FileHint, FileSegmentAddress, FileSegmentHandle, GetEndOfFile, HardDown, InvalidSegmentSize, LongAddressFromPage, LongVMtoSegment, MakeDataSegment, MakeSwappedIn, NewFileSegment, Object, ObjectHandle, ObjectType, PageCount, PageNumber, RefCount, ReleaseFile, SegCount, SegLockCount, SegmentHandle, SegmentLocation, SegmentType, SwapError, SwapIn, SwapOut, SwapUp, Unlock], Storage USING [PagesForWords], SwapperOps USING [ EnumerateObjects, MapVM, mdsIndex, PositionSeg, regions, UpdateVM, ValidateObject], SystemDefs USING []; SegmentsB: PROGRAM IMPORTS SwapperOps, InlineDefs, SegmentDefs, Storage EXPORTS SwapperOps, SegmentDefs, SystemDefs, Storage, NucleusOps SHARES SegmentDefs =PUBLIC BEGIN OPEN AltoFileDefs, SwapperOps, SegmentDefs; -- Window Segments (such as they are) MoveFileSegment: PUBLIC PROCEDURE [ seg: FileSegmentHandle, base: PageNumber, pages: PageCount] = BEGIN ValidateObject[seg]; IF base = DefaultBase THEN base ← 1; IF pages = DefaultPages THEN pages ← GetEndOfFile[seg.file].page - base + 1; IF pages ~IN (0..AltoDefs.PagesPerMDS] THEN ERROR InvalidSegmentSize[pages]; SwapOut[seg]; seg.base ← base; seg.pages ← pages; RETURN END; MapFileSegment: PROCEDURE [ seg: FileSegmentHandle, file: FileHandle, base: PageNumber] = BEGIN wasin, waswrite: BOOLEAN; old: FileHandle = seg.file; ValidateObject[seg]; IF ~old.read THEN ERROR FileAccessError[old]; IF ~file.write THEN ERROR FileAccessError[file]; IF base = DefaultBase THEN base ← 1; wasin ← seg.swappedin; waswrite ← seg.write; IF ~wasin THEN SwapIn[seg]; old.swapcount ← old.swapcount - 1; old.segcount ← old.segcount - 1; seg.file ← file; seg.base ← base; WITH s: seg SELECT FROM disk => s.hint ← FileHint[eofDA, 0]; ENDCASE; seg.write ← TRUE; file.segcount ← file.segcount + 1; file.swapcount ← file.swapcount + 1; IF wasin OR ~waswrite THEN SwapUp[seg]; seg.write ← waswrite; IF ~wasin THEN BEGIN Unlock[seg]; SwapOut[seg] END; IF old.segcount = 0 THEN ReleaseFile[old]; RETURN END; BootFileSegment: PROCEDURE [ file: FileHandle, base: PageNumber, pages: PageCount, access: AccessOptions, addr: POINTER] RETURNS [seg: FileSegmentHandle] = BEGIN seg ← NewFileSegment[file, base, pages, access]; IF addr # NIL THEN BEGIN seg.VMpage ← PageFromAddress[addr]; seg.swappedin ← TRUE; seg.lock ← seg.lock + 1; file.swapcount ← file.swapcount + 1; SwapperOps.UpdateVM[seg.VMpage, pages, seg]; END; RETURN END; -- Segment Initialization CopyDataToFileSegment: PROCEDURE [ dataseg: DataSegmentHandle, fileseg: FileSegmentHandle] = BEGIN IF dataseg.pages # fileseg.pages THEN SwapError[fileseg]; IF fileseg.swappedin OR fileseg.loc = remote THEN MoveContents[ seg: fileseg, from: DataSegmentAddress[dataseg], to: FileSegmentAddress[fileseg]] ELSE WITH s: fileseg SELECT FROM disk => BEGIN s.VMpage ← dataseg.VMpage; IF s.hint.page # s.base OR s.hint.da = eofDA THEN [] ← PositionSeg[@s, FALSE]; MapVM[@s, WriteD]; END; ENDCASE; END; CopyFileToDataSegment: PROCEDURE [ fileseg: FileSegmentHandle, dataseg: DataSegmentHandle] = BEGIN IF dataseg.pages # fileseg.pages THEN SwapError[fileseg]; IF fileseg.swappedin OR fileseg.loc = remote THEN MoveContents[ seg: fileseg, from: FileSegmentAddress[fileseg], to: DataSegmentAddress[dataseg]] ELSE WITH s: fileseg SELECT FROM disk => BEGIN s.VMpage ← dataseg.VMpage; IF (s.hint.page # s.base OR s.hint.da = eofDA) AND PositionSeg[@s, TRUE] AND s.pages = 1 THEN NULL ELSE MapVM[@s, ReadD]; END; ENDCASE; END; MoveContents: PROCEDURE [seg: FileSegmentHandle, from, to: POINTER] = BEGIN waslocked: BOOLEAN = seg.lock # 0; SwapIn[seg]; InlineDefs.COPY[from: from, to: to, nwords: seg.pages*AltoDefs.PageSize]; IF ~waslocked THEN BEGIN Unlock[seg]; IF seg.loc = remote THEN SwapOut[seg]; END; RETURN END; -- Simplified Data Segments GetPages: PROCEDURE [npages: CARDINAL, info: AllocInfo] RETURNS [POINTER] = BEGIN RETURN[DataSegmentAddress[MakeDataSegment[DefaultMDSBase, npages, info]]] END; AllocatePages: PROCEDURE [npages: CARDINAL] RETURNS [POINTER] = BEGIN RETURN[GetPages[npages, EasyDown]] END; Pages, AllocateResidentPages: PROC [npages: CARDINAL] RETURNS [POINTER] = BEGIN RETURN[GetPages[npages, HardDown]] END; AllocateSegment: PROCEDURE [nwords: CARDINAL] RETURNS [POINTER] = BEGIN RETURN[GetPages[Storage.PagesForWords[nwords], EasyDown]] END; Words, AllocateResidentSegment: PROCEDURE [nwords: CARDINAL] RETURNS [POINTER] = BEGIN RETURN[GetPages[Storage.PagesForWords[nwords], HardDown]] END; SegmentSize: PROCEDURE [base: POINTER] RETURNS [CARDINAL] = BEGIN seg: DataSegmentHandle = VMtoDataSegment[base]; RETURN[IF seg = NIL THEN 0 ELSE seg.pages*AltoDefs.PageSize] END; FreePages, FreeSegment, FreeWords: PROCEDURE [base: POINTER] = BEGIN seg: DataSegmentHandle = VMtoDataSegment[base]; IF seg # NIL THEN DeleteDataSegment[seg]; RETURN END; EnumerateFileSegments: PROCEDURE [ proc: PROCEDURE [FileSegmentHandle] RETURNS [BOOLEAN]] RETURNS [FileSegmentHandle] = BEGIN CheckSegment: PROCEDURE [seg: SegmentHandle] RETURNS [BOOLEAN] = BEGIN RETURN[WITH s: seg SELECT FROM file => proc[@s], ENDCASE => FALSE] END; RETURN[LOOPHOLE[EnumerateObjects[segment, LOOPHOLE[CheckSegment]]]]; END; VMtoDataSegment: PROCEDURE [a: POINTER] RETURNS [DataSegmentHandle] = BEGIN seg: SegmentHandle ← VMtoSegment[a]; IF seg = NIL THEN RETURN[NIL]; WITH s: seg SELECT FROM data => RETURN[@s]; ENDCASE; RETURN[NIL]; END; VMtoFileSegment: PROCEDURE [a: POINTER] RETURNS [FileSegmentHandle] = BEGIN seg: SegmentHandle ← VMtoSegment[a]; IF seg = NIL THEN RETURN[NIL]; WITH s: seg SELECT FROM file => RETURN[@s]; ENDCASE; RETURN[NIL]; END; VMtoSegment: PROCEDURE [a: POINTER] RETURNS [SegmentHandle] = BEGIN pg: PageNumber = LOOPHOLE[a, CARDINAL]/AltoDefs.PageSize; IF a = NIL THEN RETURN[NIL]; RETURN[regions[mdsIndex].status[pg].seg]; END; SegmentAddress: PROCEDURE [seg: SegmentHandle] RETURNS [POINTER] = BEGIN WITH s: seg SELECT FROM file => IF ~s.swappedin THEN RETURN[NIL]; ENDCASE; RETURN[AddressFromPage[seg.VMpage]] END; EnumerateDataSegments: PROCEDURE [ proc: PROCEDURE [DataSegmentHandle] RETURNS [BOOLEAN]] RETURNS [DataSegmentHandle] = BEGIN CheckSegment: PROCEDURE [seg: SegmentHandle] RETURNS [BOOLEAN] = BEGIN RETURN[WITH s: seg SELECT FROM data => proc[@s], ENDCASE => FALSE] END; RETURN[LOOPHOLE[EnumerateObjects[segment, LOOPHOLE[CheckSegment]]]]; END; PageFromAddress: PROCEDURE [a: POINTER] RETURNS [page: PageNumber] = BEGIN RETURN[ SwapperOps.mdsIndex*Region.PagesPerRegion + LOOPHOLE[a, CARDINAL]/AltoDefs.PageSize] END; PageAvailable: PROCEDURE [page: PageNumber, info: AllocInfo] RETURNS [BOOLEAN] = BEGIN r: Region.Handle; IF (r ← GetRegion[page]) = NIL THEN RETURN[FALSE]; RETURN[r.available[page MOD Region.PagesPerRegion, info]]; END; PagesAvailable: PROCEDURE [base: PageNumber, pages: PageCount, info: AllocInfo] RETURNS [BOOLEAN] = BEGIN FOR base IN [base..base + pages) DO IF ~PageAvailable[base, info] THEN RETURN[FALSE] ENDLOOP; RETURN[TRUE]; END; GetRegion: PROCEDURE [page: PageNumber] RETURNS [r: Region.Handle] = BEGIN r ← NIL; IF CARDINAL[page] <= AltoDefs.MaxVMPage THEN r ← regions[CARDINAL[page] MOD Region.PagesPerRegion]; RETURN END; InvalidVMPage: ERROR [page: UNSPECIFIED] = CODE; ValidateVMPage: PROCEDURE [page: UNSPECIFIED] = BEGIN IF GetRegion[page] = NIL THEN ERROR InvalidVMPage[page]; END; LongSegmentAddress: PROCEDURE [seg: SegmentHandle] RETURNS [LONG POINTER] = BEGIN WITH s: seg SELECT FROM file => IF ~s.swappedin THEN RETURN[NIL]; ENDCASE; RETURN[LongAddressFromPage[seg.VMpage]] END; LongVMtoDataSegment: PROCEDURE [a: LONG POINTER] RETURNS [DataSegmentHandle] = BEGIN seg: SegmentHandle ← LongVMtoSegment[a]; IF seg = NIL THEN RETURN[NIL]; WITH s: seg SELECT FROM data => RETURN[@s]; ENDCASE; RETURN[NIL]; END; LongDataSegmentAddress: PROCEDURE [seg: DataSegmentHandle] RETURNS [LONG POINTER] = LOOPHOLE[LongSegmentAddress]; LongFileSegmentAddress: PROCEDURE [seg: FileSegmentHandle] RETURNS [LONG POINTER] = LOOPHOLE[LongSegmentAddress]; END.