DEFINITION MODULE Processes;
TYPE SIGNAL;
PROCEDURE StartProcess(P:PROC;n:CARDINAL);
PROCEDURE SEND(VAR s:SIGNAL);
PROCEDURE WAIT(VAR s:SIGNAL);
PROCEDURE Awaited(s:SIGNAL):BOOLEAN;
PROCEDURE Init(VAR s:SIGNAL);
END Processes.
IMPLEMENTATION MODULE Processes;
FROM SYSTEM IMPORT ADDRESS,TSIZE,NEWPROCESS,TRANSFER;
FROM Storage IMPORT ALLOCATE;
TYPE SIGNAL=POINTER TO ProcessDescriptor;
 ProcessDescriptor=
  RECORD next:SIGNAL;
   queue:SIGNAL;
   cor:ADDRESS;
   ready:BOOLEAN
  END;

VAR cp:SIGNAL;

PROCEDURE StartProcess(P:PROC;n:CARDINAL);
 VAR s0:SIGNAL; wsp:ADDRESS;
BEGIN s0:=cp;ALLOCATE(wsp,n);
 ALLOCATE(cp,TSIZE(ProcessDescriptor));
 WITH cp^ DO
  next:=s0^.next;s0^.next:=cp;
  ready:=TRUE;queue:=NIL
 END;
 NEWPROCESS(P,wsp,n,cp^.cor);TRANSFER(s0^.cor,cp^.cor)
END StartProcess;

PROCEDURE SEND(VAR s:SIGNAL);
 VAR s0:SIGNAL;
BEGIN
 IF s#NIL THEN
  s0:=cp; cp:=s;
  WITH cp^ DO
   s:=queue;ready:=TRUE;queue:=NIL;
  END;
  TRANSFER(s0^.cor,cp^.cor)
 END
END SEND;

PROCEDURE WAIT(VAR s:SIGNAL);
 VAR s0,s1:SIGNAL;
BEGIN
 IF s=NIL THEN s:=cp
 ELSE s0:=s; s1:=s0^.queue;
  WHILE s1 # NIL DO
   s0:=s1; s1:=s0^.queue;
  END;
  s0^.queue:=cp
 END;
 s0:=cp;
 REPEAT cp:=cp^.next UNTIL cp^.ready;
 IF cp=s0 THEN HALT END;
 s0^.ready:=FALSE;TRANSFER(s0^.cor,cp^.cor)
END WAIT;

PROCEDURE Awaited(s:SIGNAL):BOOLEAN;
BEGIN RETURN s # NIL
END Awaited;

PROCEDURE Init(VAR s:SIGNAL);
BEGIN s:=NIL
END Init;

BEGIN ALLOCATE(cp,TSIZE(ProcessDescriptor));
 WITH cp^ DO
  next:=cp;ready:=TRUE;queue:=NIL
 END
END Processes.
