-- SSImpl.Mesa Edited by Sandman on October 2, 1980 9:56 AM
-- Copyright Xerox Corporation 1979, 1980
DIRECTORY
Inline USING [LongCOPY],
ProcessDefs USING [DisableInterrupts, EnableInterrupts],
SegmentDefs USING [EasyUp, MaxRefs, OpenFile, SwapError],
Segments USING [PageNumber, SHandle],
Storage USING [FreeWords, Words],
StreamDefs USING [ReadBlock, WriteBlock],
Streams USING [Address, Ended, Handle],
SwapperOps USING [AllocVM, FreePage, UpdateVM, ValidateObject];
SSImpl: PROGRAM
IMPORTS SwapperOps, Inline, ProcessDefs, SegmentDefs, Storage, StreamDefs, Streams
EXPORTS Segments, Streams = PUBLIC
BEGIN
Kill: PUBLIC PROCEDURE [seg: Segments.SHandle, base: Segments.PageNumber] =
BEGIN OPEN ProcessDefs, SwapperOps;
vmpage: Segments.PageNumber;
pages: CARDINAL;
ValidateObject[seg];
IF seg.swappedin THEN RETURN;
IF seg.file.swapcount = SegmentDefs.MaxRefs THEN SIGNAL SegmentDefs.SwapError[seg];
IF ~seg.file.open THEN SegmentDefs.OpenFile[seg.file];
vmpage ← AllocVM[base, pages ← seg.pages, SegmentDefs.EasyUp, seg];
DisableInterrupts[];
IF seg.swappedin THEN {EnableInterrupts[]; UpdateVM[vmpage, pages, FreePage]; RETURN};
seg.VMpage ← vmpage;
seg.file.swapcount ← seg.file.swapcount + 1;
seg.swappedin ← TRUE;
UpdateVM[vmpage, pages, seg];
EnableInterrupts[];
RETURN
END;
MakeReadOnly: PROCEDURE [seg: Segments.SHandle] = {};
GetBlock: PROCEDURE [h: Streams.Handle, a: Streams.Address, words: CARDINAL]
RETURNS [read: CARDINAL] =
BEGIN
bufferSize: CARDINAL = MIN[words, 1024];
buffer: POINTER;
count: CARDINAL;
IF words = 0 THEN RETURN;
read ← 0;
buffer ← Storage.Words[bufferSize];
DO
count ← StreamDefs.ReadBlock[h, buffer, MIN[words, bufferSize] !
UNWIND => Storage.FreeWords[buffer]];
IF count = 0 THEN EXIT;
Inline.LongCOPY[from: buffer, to: a, nwords: count];
read ← read + count;
IF (words ← words - count) = 0 THEN EXIT;
a ← a + count;
IF Streams.Ended[h] THEN EXIT;
ENDLOOP;
Storage.FreeWords[buffer];
RETURN
END;
PutBlock: PROCEDURE [h: Streams.Handle, a: Streams.Address, words: CARDINAL]
RETURNS [written: CARDINAL] =
BEGIN
bufferSize: CARDINAL = MIN[words, 1024];
buffer: POINTER;
count: CARDINAL;
IF words = 0 THEN RETURN;
written ← 0;
buffer ← Storage.Words[bufferSize];
DO
Inline.LongCOPY[from: a, to: buffer, nwords: count ← MIN[words, bufferSize]];
count ← StreamDefs.WriteBlock[h, buffer, count !
UNWIND => Storage.FreeWords[buffer]];
IF count = 0 THEN EXIT;
written ← written + count;
IF (words ← words - count) = 0 THEN EXIT;
a ← a + count;
ENDLOOP;
Storage.FreeWords[buffer];
RETURN
END;
END.