-- file: LongFSPDefs.Mesa; edited by Wyatt on October 27, 1980  2:59 PM
-- Copyright  Xerox Corporation 1979, 1980

LongFSPDefs: DEFINITIONS =
  BEGIN

  -- types and formats of zone headers and nodes

  BlockSize: TYPE = CARDINAL [0..77777B];

  NodePointer: TYPE = LONG POINTER TO NodeHeader;
  FreeNodePointer: TYPE = LONG POINTER TO free NodeHeader;

  NodeHeader: TYPE = RECORD [
    length: BlockSize,
    extension:
      SELECT state: * FROM
	inuse => NULL,
	free => [fwdp, backp: FreeNodePointer],
	ENDCASE];

  Deallocator: TYPE = PROCEDURE [LONG POINTER];

  ZonePointer: TYPE = LONG POINTER TO ZoneHeader;

  ZoneHeader: TYPE = RECORD [
    node: free NodeHeader,
    rover: FreeNodePointer, -- roving pointer to slow down fragmentation
    -- (see Knuth, Vol I, p. 597 #6)
    restOfZone: ZonePointer, -- link to additional segments of zone
    length: BlockSize,
    deallocate: Deallocator,
    threshold: PUBLIC BlockSize,
    checking: PUBLIC BOOLEAN ← FALSE];

  ZoneOverhead: CARDINAL = SIZE[ZoneHeader] + SIZE[inuse NodeHeader];
  NodeOverhead: CARDINAL = SIZE[inuse NodeHeader];

  -- NOTE: A zone whose largest possible node is N words, must have
  --   N + ZoneOverhead + NodeOverhead words of storage
  -- public procedures and signals


  MakeNewZone: PROCEDURE [
    base: LONG POINTER, length: BlockSize, deallocate: Deallocator]
    RETURNS [z: ZonePointer];
  MakeZone: PROCEDURE [base: LONG POINTER, length: BlockSize] RETURNS [z: ZonePointer];
  AddToNewZone: PROCEDURE [
    z: ZonePointer, base: LONG POINTER, length: BlockSize, deallocate: Deallocator];
  AddToZone: PROCEDURE [z: ZonePointer, base: LONG POINTER, length: BlockSize];
  PruneZone: PROCEDURE [z: ZonePointer] RETURNS [BOOLEAN];
  DestroyZone: PROCEDURE [z: ZonePointer];
  DoNothingDeallocate: Deallocator; -- adds storage to System Heap

  NoRoomInZone: SIGNAL [z: ZonePointer]; -- not enough space to fill a request


  MakeNode: PROCEDURE [z: ZonePointer, n: BlockSize] RETURNS [LONG POINTER];
  FreeNode: PROCEDURE [z: ZonePointer, p: LONG POINTER];
  SplitNode: PROCEDURE [z: ZonePointer, p: LONG POINTER, n: BlockSize];
  NodeSize: PROCEDURE [p: LONG POINTER] RETURNS [BlockSize];

  ZoneTooSmall: ERROR [LONG POINTER];
  ZoneTooLarge: ERROR [LONG POINTER];
  InvalidZone: ERROR [LONG POINTER]; -- zone header looks fishy

  NodeLoop: ERROR [ZonePointer];
  InvalidNode: ERROR [LONG POINTER]; -- node appears damaged


  END.