-- 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.