-- PSB.mesa   (last edited by Johnsson on January 27, 1981  3:52 PM)

DIRECTORY
  Environment USING [bitsPerWord],
  PrincOps USING [FrameHandle, StateVector];

PSB: DEFINITIONS =
  BEGIN

  PDABase: TYPE = LONG BASE POINTER TO ProcessDataArea;
  PDA: PDABase = LOOPHOLE[200000B];

  ProcessDataArea: TYPE = MACHINE DEPENDENT RECORD [
    vp(0):
      SELECT OVERLAID * FROM
	header => [
	  ready(0): Queue,
	  count(1): CARDINAL,  -- number of PSB's (excludes global info overlaid on PDABase.PSB[0..StartPsb) ).
	  timeout(2): PDABase RELATIVE POINTER TO TimeoutVector,
	  available(3): ARRAY [0..5) OF UNSPECIFIED ← ALL[0],
	  state(10B): StateAllocationTable,
	  interrupt(20B): InterruptVector,
	  fault(60B): FaultVector],
	blocks => [
	  block(0): ARRAY [0.. --StartPsb+PDA.count--0) OF ProcessStateBlock],
	ENDCASE];

  PsbIndex: TYPE = CARDINAL [0..1024);
  PsbNull: PsbIndex = 0;

  StartPsb: PsbIndex = -- first actual Psb follows header.
    (SIZE[ProcessDataArea] + SIZE[ProcessStateBlock] - 1)/SIZE[ProcessStateBlock];

  PsbHandle: TYPE = PDABase RELATIVE POINTER TO ProcessStateBlock;
  NullPsbHandle: PsbHandle = LOOPHOLE[0];

  ProcessStateBlock: TYPE = MACHINE DEPENDENT RECORD [
    link(0): PsbLink,
    flags(1): PsbFlags,
    context(2): Context,
    mds(3): CARDINAL];  -- temporarily used for timeout until moved to timeoutVector.

  Context: TYPE = MACHINE DEPENDENT RECORD [
    context(0): SELECT OVERLAID * FROM
      frame => [frame(0): PrincOps.FrameHandle], -- (in the psb's mds.)
      state => [state(0): PSB.StateVectorHandle],
      ENDCASE];

  Priority: TYPE = [0..7];

  PsbLink: TYPE = MACHINE DEPENDENT RECORD [
    failed(0:0..0): BOOLEAN,
    priority(0:1..3): Priority,
    next(0:4..13): PsbIndex,
    reserved(0:14..14): [0..1] ← 0,
    vector(0:15..15): BOOLEAN];

  PsbFlags: TYPE = MACHINE DEPENDENT RECORD [
    available(0:0..2): [0..7] ← 0,
    reserved(0:3..3): [0..1] ← 0,
    cleanup(0:4..13): PsbIndex,
    waiting(0:14..14): BOOLEAN,
    abort(0:15..15): BOOLEAN];

  Monitor: TYPE = MACHINE DEPENDENT RECORD [
    reserved(0:0..3): [0..17B] ← 0,
    tail(0:4..13): PsbIndex,
    available(0:14..14): [0..1] ← 0,
    locked(0:15..15): BOOLEAN];

  LockedEmpty: Monitor = [tail: PsbNull, locked: TRUE];
  UnlockedEmpty: Monitor = [tail: PsbNull, locked: FALSE];

  Condition: TYPE = MACHINE DEPENDENT RECORD [
    reserved(0:0..3): [0..17B] ← 0,
    tail(0:4..13): PsbIndex,
    abortable(0:14..14): BOOLEAN,
    wakeup(0:15..15): BOOLEAN];

  ConditionVariable: TYPE = MACHINE DEPENDENT RECORD [
    -- this is the implementation of CONDITIONs
    condition(0): Condition,
    timeout(1): Ticks];

  QueueHandle: TYPE = LONG POINTER TO Queue;

  Queue: TYPE = MACHINE DEPENDENT RECORD [
    -- (Note: format matches that of condition variables and monitor locks.)
    reserved1(0:0..3): [0..17B] ← 0,
    tail(0:4..13): PsbIndex,
    reserved2(0:14..15): [0..3] ← 0];

  QueueEmpty: Queue = [tail: PsbNull];

  StateAllocationTable: TYPE = ARRAY Priority OF StateVectorHandle;

  StateVectorHandle: TYPE = PDABase RELATIVE POINTER TO PrincOps.StateVector;
  NullStateVectorHandle: PSB.StateVectorHandle = LOOPHOLE[0];

  FaultVector: TYPE = ARRAY FaultIndex OF FaultQueue;

  FaultIndex: TYPE = [0..8);

  qFrameFault: FaultIndex = 0;
  qPageFault: FaultIndex = 1;
  qWriteProtectFault: FaultIndex = 2;

  FaultQueue: TYPE = MACHINE DEPENDENT RECORD [
    queue(0): Queue, condition(1): Condition];

  InterruptVector: TYPE = ARRAY InterruptLevel OF InterruptItem;

  InterruptLevel: TYPE = [0..Environment.bitsPerWord);

  InterruptItem: TYPE = MACHINE DEPENDENT RECORD [
    condition(0): Condition,
    available(1): UNSPECIFIED];  -- temp used for timeout till timeoutVector.

  TimeoutVector: TYPE = -- (must be 16-word aligned.)
    ARRAY PsbIndex OF Ticks; -- (only PDA.count are actually used.)

  Ticks: TYPE = CARDINAL;

  NoTimeout: Ticks = 0;

  END.