Google
 

Trailing-Edge - PDP-10 Archives - decuslib10-02 - 43,50242/qpep.bli
There are no other files named qpep.bli in the archive.
00100	! - - -  QUASI PARALLELL EXECUTION PACKAGE  - - - - - - - -
00200	!
00300	!
00400	MODULE QPEP(INSPECT,DREGS=5,RSAVE,LOWSEG) =
00500	BEGIN
00600	
00700	MACRO          !  MAKE GLOBAL NAMES UNREADABLE BUT UNIQUE.
00800	  RELEASESPACE = RELSPACE$,
00900	  RELEASELIST = RELIST$,
01000	  RELEASEMEMBERS = RELMBR$,
01100	  INSERTBEFORE = INSBEF$,
01200	  INSERTAFTER = INSAFT$,
01300	  FIRSTATTIME = FSTATT$,
01400	  FIRSTAFTERTIME = FSTAFT$;
01500
01600	GLOBAL
01700	  DEBUGGING,            ! INDICATES RUN, WALK OR LIMP STATES.
01800	  TALLY,                ! COUNTS ACTIVE PHASES (EVENTS).
01900	  STOPCOUNT,            ! LIMIT FOR TALLY IN TALLY-MODE.
02000	  SQS,
02100	  TIME,
02200	  CURRENT,
02300	  MAINPROG;
02400
02500	OWN
02600	  CURNOT,		     ! CURRENT EVENTNOTICE.
02700	  NOTICES,                   ! LIST OF UNUSED EVENTNOTICES.
02800	  NOTCOUNT,                  ! NO. OF UNUSED EVENTNOTICES.
02900	  SEQUENCER;
03000
03100	EXTERNAL			! I/O ROUTINES.
03200	  OUTMSG,
03300	  OCTOUT,
03400	  FLOUT,
03500	  DECOUT;
03600	
03700	EXTERNAL                     ! CAP AND BLIPP ROUTINES
03800	  TYPLIS,
03900	  DDTBREAK,
04000	  INITBLIPP,
04100	  MAKEOBJ,
04200	  MAKELIST,
04300	  INCLUDE,
04400	  REMOVE,
04500	  UTAVLISTE,
04600	  INNILISTE,
04700	  INSERTBEFORE,
04800	  FIRST,
04900	  RELEASESPACE,
05000	  MAPLIST,
05100	  ISROFUN,
05200	  BLIPPERROR;
05300
05400	FORWARD
05500	  SEQUER(0),
05600	  MAKEEVNOT(2),
05700	  TERMINATE(1),
05800	  CANCEL(1);
05900
06000	STRUCTURE
06100	  OBJECT[X] = (@.OBJECT+.X)<0,36>;
06200	
06300	MAP OBJECT  SQS:CURRENT:MAINPROG:NOTICES:CURNOT;
06400
06500	MACRO                  ! CLASS INDICATORS.
06600	  FREECLASS = 0$,                ! FREELIST MEMBER
06700	  HEADCLASS = #777777$,               ! LIST HEAD
06800	  REPCLASS = #777776$,                ! REPRESENTATIVE
06900	  EVNOTCLASS = #777775$;             ! EVENTNOTICE CLASS.
07000
07100	MACRO                ! REGISTERS ETC.
07200	  RIGHTHALF = 0,18$,
07300	  LEFTHALF = 18,18$,
07400	  STATEAREA = 8$;        ! SIZE OF STATE AREA.
07500
07600	MACRO                     ! CONSTANTS.
07700	  NONE = #707070707070$,
07800	  HWNONE = #707070$;
07900
08000	MACRO                ! ERROR MESSAGES.
08100	  NOTPROCERR = 24$,        ! ACTUAL IS NOT A PROCESS.
08200	  EMPTYSQSERR = 25$,       ! SQS IS EMPTY.
08300	  NOTSCHEDERR = 27$,       ! SCEDULING REL. TO UNSLATED PROCESS.
08400	  SCHEDTIMERR = 26$;       ! SCHEDULING IN THE PAST.
08500
08600	MACRO                ! FIELDS IN OBJECTS.
08700	  PRED(E) = E[-3]<18,18>$,   ! PREDECESSOR
08800	  SUC(E) = E[-3]<0,18>$,     ! SUCCESSOR
08900	  CLASS(E) = E[-2]<18,18>$,  ! CLASS FIELD
09000	  OBJREF(E) = E[-1]$,        ! OBJECT POINTER IN REP.
09100	  SIZE(E) = E[-2]<0,18>$,    ! SIZE FIELD
09200	  POINTERS(E) = E[-3]$,      ! SUC AND PRED COMPINED
09300	  REACTPT(E) = E[0]$,        ! REACTIVATION POINT
09400	  EVNOT(P) = P[-1]<0,18>$,   ! EVENTNOTICE POINTER.
09500	  RARA(P) = P[-1]<18,18>$,   ! RAFL-RALF FIELD.
09600	  PROCPTR(E) = E[-1]$,       ! PROCESS POINTER.
09700	  TIMEFLD(E) = E[0]$;        ! TIME FIELD IN EVNOT.
09800	
09900	  MACRO			! INTERFACING OLD I/O TO BLISS I/O.
10000	    TYPECRLF = TYPELINE()$,
10100	    TYPDEC(N,LF) = (DECOUT(0,0,N);
10200			   IF LF THEN TYPECRLF)$,
10300	    TYPE(MSG,LF) = (OUTMSG(0,PLIT MSG);
10400			   IF LF THEN TYPECRLF)$,
10500	    TYPFLT(N,LF) = (FLOUT(0,N,0,3);
10600			   IF LF THEN TYPECRLF)$;
10700	
10800	EXTERNAL TYPELINE;		! FUDGE, FIX LATER.
10900	EXTERNAL TYPOCT;		! DEFINED IN BLIPP.
11000	
11100	%>
11200	PROCESS TEST
11300	
11400	ISPROCESS(P)
11500	CAN BE USED TO TEST IF AN OBJECT IS A PROCESS, I.E. IF ITS CLASS FIELD
11600	CONTAINS THE ADDRESS OF A PROCEDURE.  NOTE: SOME NON-PROCESSES MAY LOOK LIKE NO-PARAMETER,
11700	NO-LOCALS ROUTINES AND PASS THE TEST.  INSPECT-OPTION REQUIRED.
11800	VALUE:  0 OR 1.
11900	<%
12000	
12100	GLOBAL ROUTINE ISPROCESS(P) =
12200	BEGIN
12300	  MAP OBJECT P;
12400	  IF .P[-2]<21,15> EQL #77777 THEN 0 ELSE
12500	  ISROFUN(.CLASS(P))
12600	END;   !   END ISPROCESS.
12700	
12800	%_
12900	QPEP EXECUTIVE:
13000	
13100	INCALL()  - EXTERNAL -  IN PHELP.
13200	WILL PROCESS PROCEDURE CALLS IN LIMP MODE.
13300	VALUE: SAME AS PROCEDURE CALLED.
13400	
13500	EXESTATE()
13600	WAITS FOR ONE LINE OF INPUT FROM TTY, READS FIRST CHARACTER AND DE-
13700	TERMINES WHAT TO DO.  THE BUFFER WILL BE CLEARED AND VALUE OF
13800	DEBUGGING SET TO REFLECT DESIRED STATE:  0 FOR RUN, 1 FOR LIMP,
13900	2 FOR WALK, 3 FOR TALLY, 4 WHEN INTERPRETING CALLS.
14000	VALUE: 1 OR 0 FOR BREAKPOINTSTOP OR NOT RESPECTIVELY.
14100	
14200	BLD8(S)  - EXTERNAL -  IN PHELP
14300	PUILDS OCTAL CONSTANT FROM TTY INPUT, FIRST DIGIT IS .S.
14400	VALUE: OCTAL CONSTANT READ.
14500	
14600	OUTSYM()  - EXTERNAL - IN PHELP.
14700	OUTPUTS SYMBOL CORRESPONDING TO ADDRESS BY LOOKING UP IN DDT TABLE.
14800	VALUE: 0.
14900	
15000	TTYINP()  - MACRO -
15100	CHECKS STATE OF TTY INPUT BUFFER.
15200	VALUE: 1 IF A LINE HAS BEEN INPUT, OTHERWISE 0.
15300	
15400	TRACEOUT()
15500	OUTPUTS CLASSNAME, STACK BASE AND EVENT TIME FOR CURRENT PROCESS.
15600	VALUE: 0.
15700	
15800	TRACEBREAK()
15900	DUMMY ROUTINE (SIMILAR TO DDTBREAK) WHERE A BREAKPOIN MAY BE SET.
16000	SEE SECTION ON DEBUGGING IN POOMAS.DOC.
16100	VALUE: 0.
16200	
16300	SEQUER
16400	A COROUTINE INSTANCE OF SEQUER IS CREATED BY INITQPEP.  IT IS
16500	EXCHJ'ED INTO EACH TIME THE IDENTITY OF THE FIRST MEMBER OF
16600	SQS CHANGES, SO THAT THE NEW CURRENT MAY BE STARTED.
16700	THE FIRST MEMBER OF SQS WILL BE MADE CURRENT AND TIME
16800	WILL BE UPDATED.  IF THE VALUE OF THE EXCHJ WHERE CONTROL
16900	CAME IN IS NOT 0, IT IS THE REFERENCE TO A TERMINATED 
17000	PROCESS WHOSE REACTIVATION POINT MUST BE CLEARED.
17100	SET NEW EXECUTION-MODE ACCORDING TO INPUT.  IF MODE IS 'LIMP',
17200	ALWAYS WAIT FOR INPUT, OTHERWISE CONTINUE IN SAME STATE UNTIL
17300	A LINE HAS BEEN INPUT.
17400	VALUE: 0.
17500	_%
17600	
17700	MACRO TTYINP(DUMMYPARAMETER) =
17800	BEGIN
17900	  MACHOP TTCALL = #51, MOVEI = #201;
18000	  MOVEI(VREG,1);
18100	  TTCALL(#14,0);
18200	  MOVEI(VREG,0)
18300	END$;   !   END MACRO TTYINP.
18400	
18500	ROUTINE EXESTATE =
18600	BEGIN
18700	  EXTERNAL BLD8,INCALL;
18800	  MACHOP TTCALL = #51;
18900	  LOCAL CH;
19000	  TTCALL(4,CH);
19100	  SELECT .CH OF
19200	  NSET
19300	    "R" : (DEBUGGING _ 0;   CH _ 0);
19400	    "W" : (DEBUGGING _ 2;   CH _ 0);
19500	    "L" : (DEBUGGING _ 1;   CH _ 0);
19600	    "B" : (DEBUGGING _ 1;   CH _ 1);
19700	    "T" : ( DEBUGGING _ 3;
19800	            TTCALL(0,CH);
19900	            WHILE .CH EQL " " DO TTCALL(0,CH);
20000	            STOPCOUNT _ .TALLY + BLD8(.CH);
20100	            CH _ 0
20200	          );
20300	    "C" : (DEBUGGING _ 4;   INCALL();   CH _ 0);
20400	    OTHERWISE : ( IF .DEBUGGING EQL 4 THEN DEBUGGING _ 1;
20500	                  CH _ 0);
20600	  TESN;
20700	  TTCALL(#11,0);
20800	  .CH
20900	END;   !   END EXESTATE.
21000	
21100	ROUTINE TRACEOUT =
21200	BEGIN
21300	  EXTERNAL OUTSYM;
21400	  OUTSYM(.CLASS(CURRENT));   TYPE(' AT ',0);
21500	  TYPOCT(.CURRENT<RIGHTHALF>,0);   TYPE(' T= ',0);
21600	  TYPFLT(.TIME,0)
21700	END;   !   END ROUTINE TRACEOUT.
21800	
21900	ROUTINE SEQUER =
22000	BEGIN
22100	  LOCAL BRK,L;
22200	  MAP OBJECT  L;
22300	  BRK _ 0;
22400	  WHILE ((CURNOT _ FIRST(.SQS)) NEQ NONE) DO
22500	  ( ! SQS IS NOT EMPTY.
22600	    CURRENT _ .PROCPTR(CURNOT);
22700	    TIME _ .TIMEFLD(CURNOT);
22800	    CASE .DEBUGGING OF
22900	    SET
23000	
23100	      ! CASE 0:  RUN - MODE
23200	      IF TTYINP() THEN BRK _ EXESTATE();
23300	
23400	      ! CASE 1:  LIMP - MODE
23500	      ( TRACEOUT();
23600	        DO ( TYPE(' :',0);   BRK _ EXESTATE())
23700	          WHILE .DEBUGGING EQL 4
23800	      );
23900	
24000	      ! CASE 2:  WALK - MODE
24100	      ( TRACEOUT();   TYPECRLF;  IF TTYINP() THEN BRK _ EXESTATE());
24200	
24300	      ! CASE 3:  TALLY MODE.
24400	      ( IF TTYINP() THEN ( BRK _ EXESTATE();   EXITCASE);
24500	        IF .TALLY GEQ .STOPCOUNT THEN
24600	          ( DEBUGGING _ 1;   BRK _ 0)
24700	      );
24800	    TES;
24900	    TALLY _ .TALLY + 1;
25000	    L _ EXCHJ(.CURRENT,.BRK);
25100	    IF .L NEQ 0 THEN REACTPT(L) _ 0;
25200	  );
25300	  BLIPPERROR(EMPTYSQSERR);
25400	END;   ! END SEQUER.
25500	
25600	ROUTINE TRACEBREAK = (0);
25700	
25800	
25900	%_
26000	INITIALISATION OF QPEP:
26100
26200	INITQPEP()
26300	WILL INITIALIZE BLIPP AND ITS FREELIST, SQS WITH ONE EVENTNOTICE
26400	REFERENCING THE CALLING PROGRAM, CURRENT, MAINPROG, AND THE 
26500	SEQUENCER PROCESS.
26600	VALUE: 0.
26700	_%
26800
26900	GLOBAL ROUTINE INITQPEP =
27100	( SQS _ MAKELIST();
27200	  NOTICES _ MAKELIST();
27300	  NOTCOUNT _ TALLY _ 0;
27400	  DEBUGGING _ 1;
27500	  SEQUENCER _
27600	    CREATE SEQUER() AT MAKEOBJ(200,SEQUER) LENGTH 200
27700	    THEN EXCHJ(.MAINPROG,0);
27800	  MAINPROG _ .BREG;
27900	  CURRENT _ .MAINPROG;
28000	  TIME _ 0.0;
28100	  CURNOT _ INNILISTE(MAKEEVNOT(.CURRENT,0),.SQS);
28200	  (.CURRENT-1)<RIGHTHALF> _ FIRST(.SQS); ! SET EVNOT(CURRENT).
28300	);   ! END INITQPEP.
28400
28500
28600	%_
28700	SQS MANIPULATION:
28800
28900	MAKEEVNOT(P,T)
29000	CONSTRUCTS AN EVENTNOTICE WITH PROCESS REFERENCE P AND TIME
29100	REFERENCE T USING SPACE FROM THE LIST OF FREE NOTICES, OR, IF THIS IS
29200	EMPTY, FROM THE BLIPP FREELIST.
29300	VALUE: 0 IF ERRORS, ELSE ADDRESS OF NOTICE.
29400	
29500	RELEASENOTICE(P)
29600	WILL RETURN A FREE EVENTNOTICE TO THE LIST OF FREE EVENTNOTICES.
29700	IF THIS LIST IS LONG ALREADY, THE NOTICE WILL BE RETURNED TO THE
29800	FREE LIST.
29900	VALUE: 0 IF ERRORS, -1 IF RETURNED TO BLIPP FREELIST, LENGTH OF
30000	       SPECIAL NOTICE-LIST IF RETURNED THERE.
30100
30200	FIRSTATTIME(T)
30300	WILL SEARCH THE SQS FOR THE FIRST EVENTNOTICE AT TIME .T.
30400	VALUE: ADDRESS OF NOTICE IF IT EXISTS, OTHERWISE ADDRESS OF
30500	FIRST NOTICE AT HIGHER TIME OR IF SUCH DOES NOT EXIST ADDRESS
30600	OF SQS HEADER.
30700
30800	FIRSTAFTERTIME(T)
30900	ANALOGOUS TO FIRSTATTIME.
31000	_%
31100
31200	GLOBAL ROUTINE MAKEEVNOT(P,T) =
31300	BEGIN
31400	  LOCAL L;
31500	  MAP OBJECT  L:P;
31600	  IF .P<RIGHTHALF> EQL HWNONE THEN RETURN;
31700	  IF .CLASS(P) EQL REPCLASS THEN P _ .OBJREF(P);
31800	  IF NOT ISPROCESS(.P) THEN
31900	    (BLIPPERROR(NOTPROCERR);   RETURN);
32000	  IF .NOTICES NEQ .SUC(NOTICES) THEN
32100	    ( L _ UTAVLISTE(FIRST(.NOTICES));  NOTCOUNT _ .NOTCOUNT - 1)
32200	  ELSE
32300	    L _ MAKEOBJ(1,EVNOTCLASS);
32400	  IF .L NEQ 0 THEN
32500	  ( PROCPTR(L) _ .P;
32600	    TIMEFLD(L) _ .T;
32700	  );
32800	  .L
32900	END;   ! END MAKEEVNOT.
33000	
33100	ROUTINE RELEASENOTICE(P) =
33200	BEGIN
33300	  IF .NOTCOUNT LEQ 10 THEN
33400	    ( IF INCLUDE(REMOVE(.P),.NOTICES) NEQ 0 THEN NOTCOUNT _ .NOTCOUNT+1)
33500	  ELSE
33600	    ( RELEASESPACE(.P);  -1)
33700	END;   ! END RELEASEEVNOT.
33800
33900	GLOBAL ROUTINE FIRSTATTIME(T) =
34000	BEGIN
34100	  LOCAL L;
34200	  MAP OBJECT  L;
34300	  L _ .SUC(SQS);
34400	  WHILE .L NEQ .SQS DO
34500	    IF .TIMEFLD(L) LSS .T THEN L _ .SUC(L)
34600	    ELSE EXITLOOP;
34700	  .L
34800	END;   ! END FIRSTATTIME.
34900
35000	GLOBAL ROUTINE FIRSTAFTERTIME(T) =
35100	BEGIN
35200	  LOCAL L;
35300	  MAP OBJECT  L;
35400	  L _ .SUC(SQS);
35500	  WHILE .L NEQ .SQS DO
35600	    IF .TIMEFLD(L) LEQ .T THEN L _ .SUC(L)
35700	    ELSE EXITLOOP;
35800	  .L
35900	END;   ! END FIRSTAFTERTIME.
36000
36100	%_
36200	SCHEDULING.
36300
36400	TO SCHEDULE A PROCESS MEANS TO INSERT AN EVENTNOTICE REFE-
36500	RENCING IT IN THE SQS, THUS SPECIFYING THAT AN EVENT OF
36600	THIS PROCESS IS TO OCCUR AT A TIME NOT LESS THAN THE CURRENT
36700	TIME.  THERE IS AT MOST ONE EVENTNOTICE REFERENCING A
36800	PROCESS AT ANY ONE TIME.
36900	A PROCESS IS SAID TO BE SLATED IF THERE IS AN EVENTNOTICE
37000	REFERENCING IT IN THE SQS, I.E. IT HAS PREVIOUSLY BEEN
37100	SCHEDULED BUT THE EVENT IS NOT YET EXECUTED OR CANCELED.
37200	(ACTIVE OR SUSPENDED IN SIMULA.)
37300	A PROCESS CAN BE ACTIVATED OR REACTIVATED AT A GIVEN TIME
37400	OR RELATIVE TO ANOTHER PROCESS.  IF THE PROCESS IS ALREADY
37500	SLATED, AN ACTIVATE WILL BE IGNORED WHEREAS A REACTIVATE
37600	WILL CANCEL THE OLD EVENT AND RESCHEDULE IT.
37700	THE PROCESS MAY BE SCHEDULED FIRST OR LAST AMONG THE PROCESSES
37800	ALREADY SLATED FOR THE GIVEN TIME, OR IT MAY BE SCHEDULED
37900	IMMEDIATELY BEFORE OR AFTER ANOTHER GIVEN SLATED PROCESS.
38000
38100
38200	SCHEDULE(CODE,P,T)
38300	HANDLES ALL SCHEDULING.  P SPECIFIES PROCESS TO BE SCHEDULED,
38400	T IS THE TIME OR PROCESS WHICH DETERMINES THE POSITION IN SQS.
38500	.CODE DETERMINES WHICH OF THE POSSIBLE CASES WE HAVE AS FOLLOWS:
38600
38700	  ! BIT 33          ! BIT 34          ! BIT 35          !
38800	---------------------------------------------------------
38900	0 ! REACTIVATE      ! AT TIME .T      ! FIRST OR BEFORE !
39000	1 ! ACTIVATE        ! REL. TO PROC .T ! LAST OR AFTER   !
39100	---------------------------------------------------------
39200	VALUE: 0 IF ERRORS,
39300	      -1 IF NOTHING WAS SCHEDULED (.P WAS NONE),
39400	       1 IF NO OTHER EVENT HAPPENED DURING SCHEDULE,
39500	       2 IF OTHER EVENTS HAPPENED DURING SCHEDULE.
39600
39700
39800	FOR EASY DETERMINATION OF THE CODE PARAMETER USE MACRO CALLS AS FOLLOWS:
39900	
40000	NOTE: BEFORE, AFTER, FIRSTAT, LASTAT ARE THEMSELVES MACROS
40100	       OF NO PARAMETERS AND SMALL INTEGER CONSTANT VALUES.
40200	
40300	MACRO REACTIVATE IS ANALOGOUS TO MACRO ACTIVATE.  THE FOLLOWING
40400	OPTIONS ARE AVAILABLE.
40500
40600	ACTIVATE(P,BEFORE,T)
40700	ACTIVATES PROCESS P BEFORE PROCESS T.
40800
40900	ACTIVATE(P,AFTER,T)
41000	ACTIVATES PROCESS P AFTER PROCESS T.
41100
41200	ACTIVATE(P,FIRSTAT,T)
41300	ACTIVATES PROCESS P FIRST AT TIME T.
41400
41500	ACTIVATE(P,LASTAT,T)
41600	AS ABOVE BUT LAST AT TIME T.
41700
41800
41900	 MORE MACROS AND ONE ROUTINE FACILITATE SCHEDULING:
42000
42100	HOLDSHORT(T)
42200	EQUIVALENT TO REACTIVATEFIRST(.CURRENT,.TIME+T)
42300
42400	HOLDLONG(T)
42500	EQUIVALENT TO REACTIVATELAST(.CURRENT,.TIME+T)
42600
42700	HOLD(T)
42800	EQUIVALENT TO HOLDLONG(T) OR REACTIVATELAST(.CURRENT,.TIME+T)
42900
43000	WAIT(S)
43100	INCLUDES .CURRENT IN LIST .S AND CANCELS IT.
43200	_%
43300
43400	GLOBAL ROUTINE SCHEDULE(CODE,P,T) =
43500	BEGIN
43600	  LOCAL L,M;
43700	  MAP OBJECT  L:M:P:T;
43800	  IF .P<RIGHTHALF> EQL HWNONE THEN RETURN -1;
43900	  IF .CLASS(P) EQL REPCLASS THEN P _ .OBJREF(P);
44000	  IF NOT ISPROCESS(.P) THEN
44100	    (BLIPPERROR(NOTPROCERR);   RETURN);
44200	  IF .EVNOT(P) NEQ HWNONE THEN
44300	  ( IF (.CODE AND 4) NEQ 0 THEN RETURN
44400	    ELSE
44500	      ( M _ UTAVLISTE(.EVNOT(P));  EVNOT(P) _ HWNONE;
44600	        TIMEFLD(M) _ .T
44700	      )
44800	  )
44900	  ELSE 
45000	    IF ( M _ MAKEEVNOT(.P,.T) ) EQL 0 THEN RETURN;
45100	!
45200	! M IS NOW AN EVNOT FOR P, POSSIBLY WITH WRONG TIMEFIELD.
45300	! EVNOT(P) IS NONE TO BE PREPARED FOR ERRORS.
45400	!
45500	  IF (.CODE AND 2) NEQ 0 THEN
45600	  ( ! INSERT IN SQS RELATIVE TO PROCESS T
45700	    ( IF .T<RIGHTHALF> EQL HWNONE THEN EXITCOND
45800	      ELSE
45900	      ( IF .CLASS(T) EQL REPCLASS THEN T _ .OBJREF(T);
46000	        IF ISPROCESS(.T) THEN EXITCOMPOUND[2]
46100	      );
46200	      BLIPPERROR(NOTPROCERR);   RELEASENOTICE(.M);   RETURN
46300	    );
46400	    L _ .EVNOT(T);
46500	    IF .L EQL HWNONE THEN
46600	      (BLIPPERROR(NOTSCHEDERR);  RELEASENOTICE(.M);   RETURN);
46700	    TIMEFLD(M) _ .TIMEFLD(L);
46800	    IF .CODE AND 1 THEN L _ .SUC(L);
46900	!
47000	!    M IS NOW A GOOD EVNOT IN ALL CASES.
47100	!   IN BEFORE/AFTER CASE, L IS ITS SUCCESSOR TO BE IN THE SQS.
47200	!
47300	  )
47400	  ELSE
47500	  ( ! INSERT AT A GIVEN TIME.
47600	    IF .T LSS .TIME THEN
47700	    ( BLIPPERROR(SCHEDTIMERR);  RELEASENOTICE(.M);   RETURN);
47800	    L _ IF .CODE AND 1 THEN FIRSTAFTERTIME(.T)
47900	        ELSE FIRSTATTIME(.T);
48000	!
48100		!  L IS NOW SUCCESSOR IN SQS FOR ALL CASES.
48200	!
48300	  );
48400	  INNILISTE(.M,.L);
48500	  EVNOT(P) _ .M;
48600	  IF (.M<RIGHTHALF> EQL .SUC(SQS)) OR (.CURNOT NEQ .SUC(SQS)) THEN
48700	    ( IF EXCHJ(.SEQUENCER,0) THEN TRACEBREAK(); 2)
48800	  ELSE 1
48900	END;   ! END SCHEDULE.
49000
49100		
49200	GLOBAL ROUTINE WAIT(S) =
49300	( INCLUDE(.CURRENT,.S);
49400	  CANCEL(.CURRENT)
49500	);   ! END WAIT.
49600
49700	%_
49800	UN-SCHEDULING:
49900
50000	TERMINATE(P)
50100	REMOVES ANY EVENTNOTICE FOR .P FROM THE SQS AND CLEARS .P'S
50200	REACTIVATIONPOINT.  .P IS HEREAFTER TO BE REGARDED AS A DATA-
50300	STRUCTURE ONLY AND CAN NOT BE EXECUTED.
50400	IF .P IS .CURRENT, START NEXT PROCESS IN SQS.
50500	VALUE: 0 IF ERRORS, -1 IF .P IS NONE, OTHERWISE 1.
50600
50700	CANCEL(P)
50800	REMOVES ANY EVENTNOTICE FOR .P FROM SQS, IF .P IS CURRENT
50900	NEXT PROCESS IN SQS WILL BE STARTED.
51000	VALUE: 0 IF ERRORS, -1 IF .P IS NONE, OTHERWISE 1.
51100	
51200	KILL(P)
51300	TERMINATES PROCESS .P AND RETURNS ITS SPACE TO FREELIST.
51400	IF .P IS .CURRENT, NEXT PROCESS WILL BE STARTED.
51500	USED MOSTLY WHEN PROCESSES WANT TO KILL THEMSELVES.
51600	VALUE: 0 IF ERRORS, -1 IF .P IS NONE, OTHERWISE 1.
51700	_%
51800
51900	GLOBAL ROUTINE TERMINATE(P) =
52000	( MAP OBJECT  P;
52100	  IF .P<RIGHTHALF> EQL HWNONE THEN RETURN -1;
52200	  IF .CLASS(P) EQL REPCLASS THEN P _ .OBJREF(P);
52300	  IF NOT ISPROCESS(.P) THEN
52400	  (BLIPPERROR(NOTPROCERR);   RETURN);
52500	  IF .EVNOT(P) NEQ HWNONE THEN
52600	  ( RELEASENOTICE(.EVNOT(P));   EVNOT(P) _ NONE );
52700	  IF .P<RIGHTHALF> EQL .CURRENT<RIGHTHALF> THEN EXCHJ(.SEQUENCER,.P)
52800	  ELSE REACTPT(P) _ 0;
52900	  1
53000	);   ! END TERMINATE
53100
53200	GLOBAL ROUTINE CANCEL(P) =
53300	( MAP OBJECT  P;
53400	  IF .P<RIGHTHALF> EQL HWNONE THEN RETURN -1;
53500	  IF .CLASS(P) EQL REPCLASS THEN P _ .OBJREF(P);
53600	  IF NOT ISPROCESS(.P) THEN
53700	  ( BLIPPERROR(NOTPROCERR);   RETURN);
53800	  IF .EVNOT(P) NEQ HWNONE THEN
53900	  ( RELEASENOTICE(.EVNOT(P));   EVNOT(P) _ NONE);
54000	  IF .P<RIGHTHALF> EQL .CURRENT<RIGHTHALF> THEN
54100	    ( IF EXCHJ(.SEQUENCER,0) THEN TRACEBREAK());
54200	  1
54300	);   ! END CANCEL.
54400
54500	GLOBAL ROUTINE KILL(P) =
54600	BEGIN
54700	  MAP OBJECT P;
54800	  IF .P<RIGHTHALF> EQL HWNONE THEN RETURN -1;
54900	  IF .CLASS(P) EQL REPCLASS THEN (RELEASESPACE(.P);  P _ .OBJREF(P));
55000	  IF NOT ISPROCESS(.P) THEN
55100	    ( BLIPPERROR(NOTPROCERR);  RETURN);
55200	  IF .EVNOT(P) NEQ HWNONE THEN
55300	    ( RELEASENOTICE(.EVNOT(P));  EVNOT(P) _ NONE);
55400	  REACTPT(P) _ 0;
55500	  RELEASESPACE(.P);
55600	  IF .P<RIGHTHALF> EQL .CURRENT<RIGHTHALF> THEN
55700	    EXCHJ(.SEQUENCER,0);
55800	  1
55900	END;   ! END KILL.
56000	
56100	END   ! END QPEP.
56200	ELUDOM