|
|
DataMuseum.dkPresents historical artifacts from the history of: CR80 Hard and Floppy Disks |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about CR80 Hard and Floppy Disks Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 15232 (0x3b80)
Types: TextFile
Names: »CORU1«
└─⟦d9c1548a9⟧ Bits:30005185 8" CR80 Floppy CR80FD_0182 ( UTILITIES FOR X25 HOH )
└─⟦851bd64f0⟧
└─⟦this⟧ »ICL.CORU1«
;=======================================================================
;
; COROUTINE MONITOR, PART 1.
;
;=======================================================================
MESSAGE <:CALL: COMON1, 790813:>
;=======================================================================
;
; COROUTINE SYSTEM.
;
; THIS SYSTEM IS A MULTIPROGRAMMING SYSTEM FOR RUNNING A NUMBER OF
; PARALLEL ACTIVITIES WITHIN A SINGLE PROCESS.
;
; THE BASIC ENTITIES ARE:
; COROUTINES (PSEUDO PROCESSES)
; SEMAPHORES (SYNCHRONIZING AND COMMUNICATION PRIMITIVES)
; OPERATIONS (BUFFERS / MESSAGES)
;
; THE BASIC FUNCTIONS ARE:
; SIGNAL (SEMAPHORE)
; WAIT (SEMAPHORE)
; SIGNALCH (CHAINED SEMAPHORES)
; WAITCH (CHAINED SEMAPHORE)
; WAITANSWER (MESSAGEREF)
; WAITMESSAGE
; WAIT-TIMER-OR-INTERRUPT
;
;=======================================================================
USE BASE
;-----------------------------------------------------------------------
;
; BASIC DESCRIPTORS:
;
; CHAIN ELEMENTS AND QUEUE HEADS
AX=0
SUCC:= AX, AX=AX+1 ; SUCCESSOR (FORWARD CHAIN)
PRED:= AX, AX=AX+1 ; PREDECESSOR (BACKWARD CHAIN)
CHAINSIZE:= AX ; SIZE OF CHAIN HEAD
; SEMAPHORE
AX=0
SEMFST:= AX, AX=AX+1 ; FIRST WAITING COROUTINE
SEMLST:= AX, AX=AX+1 ; LAST WAITING COROUTINE
SEMVAL:= AX, AX=AX+1 ; SEMAPHORE VALUE
SEMSIZE:= AX ; SIZE OF SEMAPHORE
; COROUTINE DESCRIPTION
AX=CHAINSIZE ; ROOM FOR CHAIN FIELDS
SV0:= AX, AX=AX+1 ; REGISTER SAVE AREA
SV1:= AX, AX=AX+1 ;
SV2:= AX, AX=AX+1 ;
SV3:= AX, AX=AX+1 ;
SV4:= AX, AX=AX+1 ;
SV5:= AX, AX=AX+1 ;
SV6:= AX, AX=AX+1 ;
CORUSIZE:= AX ; SIZE OF COROUTINE DESCRIPTOR
CCHAIN=0 ; CHAIN FOR INITIALIZATION
IF TPON THEN
TPOS= 8<TPLS OR 1<SMXS
TPSIGN: INXFIL, TPSEM
TPWAIT: INXFIL, TPSEM
TPSGCH: INXFIL, TPSMOP
TPWTCH: INXFIL, TPSEM
TPEXIT: INXFIL, TPCORU
TPWTTI: INXFIL, TPCORU
TPWTMS: INXFIL, TPCORU
TPWANS: INXFIL, TPCORU
DVAL: 0
TPSM: RELFIL OR BINDAT OR 0<RCLGTS OR 1
DVAL
<:SEM :>
TPCOR: RELFIL OR BINDAT OR (CORUSIZE-1)<RCLGTS OR 1
DCORU: 0
<:CORU:>
TPOP: RELFIL OR BINDAT OR 6<RCLGTS OR 1
DOP: 0
<:OP :>
TPSEM: 1, TPSM
TPSMOP: 2, TPSM, TPOP
TPCORU: 1, TPCOR
FI
READYQ: RDYFST ; ADDRESS OF READY QUEUE
ANSWQ: ANSFST ; ADDRESS OF ANSWER QUEUE
MESSC: 0 ; COROUTINE WAITING FOR MESSAGE
TINTRC: 0 ; COROUTINE WAITING FOR TIMER
; OR INTERRUPT
CURRC: INITCH ; ADDRESS OF ACTIVE COROUTINE
; (REF TO INIT CHAIN AT STARTUP)
MSBREF: MSBUF ; REF TO RECEIVED MESSAGE
RDYFST: LOC ; EMPTY READY QUEUE
RDYLST: LOC-1 ;
ANSFST: LOC ; EMPTY ANSWER QUEUE
ANSLST: LOC-1 ;
MSBUF: 0, REPEAT 4 ; BUFFER FOR RECEIVING MESSAGES
USE PROG
;-----------------------------------------------------------------------
;
; MAIN WAITING POINT IN COROUTINE SYSTEM
;
; THE SYSTEM SCHEDULES ALL INTERNAL EVENTS BEFORE EXTERNAL EVENTS
; I.E. COROUTINES ARE ACTIVATED FROM THE READY QUEUE UNTIL THE READY
; QUEUE IS EMPTY.
; FINALLY THE SYSTEM AWAITS SOME EXTERNAL EVENT TO TRIGGER A NEW SERIES
; OF INTERNAL EVENTS.
;
;_______________________________________________________________________
WEVENT: MON INITWAIT ; BASE OF EVENT QUEUE
MOVC CDELAY R0 ; DELAY
MON SETDELAY ; SETDELAY(DELAY)
MOV MSBREF R1 ; MESSAGE AREA
JMP MAINWT ; GOTO MAIN WAITING POINT
WTNEXT: MON RESUMEEVENT ; RESUMEEVENT AND
MAINWT: MON WAITNEXT ; WAIT NEXT EVENT TO ARRIVE
JMP & TIMERC ; TIMEOUT,
JMP & ANSWRC ; ANSWER,
JMP & MESSGE ; MESSAGE ARRIVED
JMP & INTRPC ; INTERRUPT)
ANSWRC: MOV ANSWQ R7 ; ANSWERQUEUE => R7
NEXTAQ: MOV SUCC. X7 R7 ; NEXT COROUTINE => R7
IEQ R7 ANSWQ ; IF NO MORE IN QUEUE
JMP WTNEXT ; THEN GOTO WAIT NEXT EVENT
SEQ R2 SV2. X7 ; IF NOT WAITING FOR ACTUAL ANSWER
JMP NEXTAQ ; THEN GOTO NEXT IN ANSWER QUEUE
MOVL SV0. X7 R0 ; REESTABLISH R0, R1
MOV READYQ R5 ; READY QUEUE
MOV R7 R4 ; ACTUAL COROUTINE
JMP S6 LINK ; LINK(CURRENT, READY QUEUE)
JMP SCHED ; GOTO SCHEDULE
MESSGE: MOV MESSC R7 ; WAITING COROUTINE => R7
JOZ R7 WTNEXT ; IF NO WAITING COROUTINE
; THEN GOTO WAIT NEXT EVENT
MOV R1 SV1. X7 ; SET BUFFER ADDRESS
MOV R2 SV2. X7 ; SET MESSAGE REFERENCE
MOVC 0 R0 ;
MOV R0 MESSC ; CLEAR REF TO WAITING COROUTINE
JMP PREPC ; PREPARE COROUTINE FOR RUN
TIMERC:
INTRPC: MOV TINTRC R7 ; WAITING COROUTINE => R7
JOZ R7 WTNEXT ; IF NO COROUTINE IS WAITING
; THEN GOTO WAIT NEXT EVENT
MOVC 0 R0 ;
MOV R0 TINTRC ; CLEAR REF TO WAITING COROUTINE
JMP PREPC ; GOTO PREPARE COROUTINE FOR RUN
PREPC: MOV R7 R4 ; COROUTINE
MOVL SV0. X7 R0 ; REESTABLISH R0, R1
MOV READYQ R5 ; READY QUEUE
JMP S6 LINKON ; LINKON(COROUTINE, READYQUEUE)
SCHED: MOV READYQ R0 ; READY QUEUE
MOV SUCC. X0 R7 ; FIRST ELEMENT IN READY QUEUE
IEQ R0 R7 ; IF EMPTY (POINTS TO ITSELF)
JMP WEVENT ; THEN GOTO WAIT EVENT
MOV R7 CURRC ; SET CURRENT COROUTINE
ADDC -7 R7 ; MODIFY POINTER FOR UNSTACK
MODC SV6+1 ; UNSTACK
UNS 6 ; R0 - R6
NOLIST
IF TPON THEN
MOV R7 DCORU
MON OLTO, TPOS OR 1
TPEXIT
MOV CURRC R7
FI
LIST
JMP 0. X6 ; JUMP TO SAVED LINK
;-----------------------------------------------------------------------
;
; PROCEDURE LINK(ELEMENT, QUEUE)
;
; THIS PROCEDURE MOVES A QUEUE ELEMENT FROM ONE QUEUE TO ANOTHER
; THE ELEMENT IS REMOVED FROM WHEREVER IT IS LINKED BEFORE CALL
; THE QUEUES ARE DOUBLE LINKED
; THE ELEMENT IS LINKED INTO THE QUEUE AS THE VERY LAST ELEMENT
; CALL: EXIT:
; R4 ELEMENT ADDRESS UNCHANGED
; R5 QUEUE ADDRESS UNCHANGED
; R6 LINK UNCHANGED
; R7 CURRENT COROUTINE UNCHANGED
; -- IRRELEVANT UNCHANGED
;
;
; PROCEDURE LINKON (ELEMENT, QUEUE)
;
; THIS PROCEDURE LINKS AN ELEMENT INTO A QUEUE.
; THE ELEMENT IS EXPECTED NOT TO RESIDE IN ANY QUEUE WHEN THIS PROCEDURE
; IS CALLED (THE VALUES OF THE CHAIN FIELDS ARE CONSIDERED TO BE IRRE-
; LEVANT.
; CALL: EXIT:
; R4 ELEMENT ADDRESS UNCHANGED
; R5 QUEUE ADDRESS UNCHANGED
; R6 LINK UNCHANGED
; R7 CURRENT COROUTINE UNCHANGED
; -- IRRELEVANT UNCHANGED
;
;
; PROCEDURE LINKOFF (ELEMENT)
;
; THIS PROCEDURE REMOVES A QUEUE ELEMENT FROM WHEREVER IT IS LINKED UP
; WHEN THIS PROCEDURE IS CALLED.
; CALL: EXIT:
; R4 ELEMENT ADDRESS UNCHANGED
; R6 LINK UNCHANGED
; R7 CURRENT COROUTINE UNCHANGED
; -- IRRELEVANT UNCHANGED
LINKOFF:MOV R5 SV5. X7 ; SAVE R5
MOVC 0 R5 ; CLEAR QUEUE
LINK: MOVL R0 SV0. X7 ; SAVE R0, R1
; REMOVE ELEMENT FROM QUEUE
MOV PRED. X4 R0 ; PRED.ELEMENT => PREDECESSOR
MOV SUCC. X4 R1 ; SUCC.ELEMENT => SUCCESSOR
MOV R1 SUCC. X0 ; SUCCESSOR => SUCC.PREDECESSOR
MOV R0 PRED. X1 ; PREDECESSOR => PRED.SUCCESSOR
JON R5 LINTO ; IF LINKOFF THEN
MOV SV5. X7 R5 ; REESTABLISH R5
JMP LNKXIT ; GOTO EXIT
LINKON: MOVL R0 SV0. X7 ; SAVE R0, R1
MOV R4 SUCC. X4 ; SET EMPTY CHAIN
MOV R4 PRED. X4 ;
LINTO: ; LINK ELEMENT INTO QUEUE
MOV PRED. X5 R0 ; PRED.QUEUE => OLDLAST
MOV R4 SUCC. X0 ; ELEMENT => SUCC.OLDLAST
MOV R4 PRED. X5 ; ELEMENT => PRED.QUEUE
MOV R0 PRED. X4 ; OLDLAST => PRED.ELEMENT
MOV R5 SUCC. X4 ; QUEUE => SUCC.ELEMENT
LNKXIT: MOVL SV0. X7 R0 ; REESTABLISH R0, R1
JMP 0. X6 ; RETURN TO LINK
;-----------------------------------------------------------------------
;
; PROCEDURE SIGNAL (SEMAPHORE)
;
; THIS PROCEDURE INCREASES THE VALUE OF A SIMPLE SEMAPHORE BY ONE
; IN CASE THE VALUE WAS NEGATIVE BEFORE CALLING THE PROCEDURE (BECAUSE
; A COROUTINE WAS ALREADY WAITING FOR A SIGNAL) THE FIRST WAITING
; COROUTINE IS LINKED INTO THE READY QUEUE (TO BE ACTIVATED)
; IN ANY CASE THE CALLING COROUTINE WILL BE REACTIVATED AFTER CALLING
; THIS PROCEDURE (NO WAITING POINT)
; CALL: EXIT:
; R5 SEMAPHORE ADDRESS UNCHANGED
; R6 LINK UNCHANGED
; R7 CURRENT COROUTINE UNCHANGED
; -- IRRELEVANT UNCHANGED
SIGNAL: MOV R4 SV4. X7 ; SAVE R4,
MOV R5 SV5. X7 ; R5
MOV R6 SV6. X7 ; AND R6
INC SEMVAL.X5 ; INCREASE SEMAPHORE VALUE BY 1
MOV SEMVAL.X5 R6 ;
NOLIST
IF TPON THEN
MOV R6 DVAL
MON OLTO, TPOS OR 2
TPSIGN
MOV CURRC R7
FI
LIST
IGE R6 1 ; IF SEMVALUE > 0
JMP SIGXIT ; THEN GOTO EXIT
MOV SEMFST.X5 R4 ; SEMFST.SEMAPHORE => COROUTINE
MOV READYQ R5 ; READY QUEUE
JMP S6 LINK ; LINK (COROUTINE, READY QUEUE)
SIGXIT: MOV SV4. X7 R4 ; REESTABLISH R4,
MOV SV5. X7 R5 ; R5,
MOV SV6. X7 R6 ; AND R6
JMP 0. X6 ; RETURN TO LINK
;-----------------------------------------------------------------------
;
; PROCEDURE WAIT (SEMAPHORE)
;
; THIS PROCEDURE DECREASES THE VALUE OF A SIMPLE SEMAPHORE BY ONE
; IN CASE THE VALUE WAS NOT POSITIVE BEFORE CALLING THIS PROCEDURE
; (BECAUSE NO SIGNALS WERE READY) THE CALLING COROUTINE IS LINKED TO
; THE SEMAPHORE, WAITING FOR A SIGNAL TO ARRIVE.
; THIS IS A WAITING POINT PROCEDURE.
; CALL: EXIT:
; R5 SEMAPHORE ADDRESS UNCHANMGED
; R7 CURRENT COROUTINE UNCHANGED
; -- IRRELEVANT UNCHANGED
WAITS: MODC SV6+1 ; STACK
STC 6 ; R0 _ R6
MOV CURRC R7 ; REESTABLISH R7
DEC SEMVAL.X5 ; DECREMENT (SEMVAL.SEMAPHORE)
MOV SEMVAL.X5 R6 ; SEMVAL.SEMAPHORE => SEMVALUE
NOLIST
IF TPON THEN
MOV R6 DVAL
MON OLTO, TPOS OR 3
TPWAIT
MOV CURRC R7
FI
LIST
MOV R7 R4 ; CURRENT COROUTINE
ILT R6 0 ; IF SEMVALUE < 0
JMP S6 LINK ; THEN LINK (CURRENT, SEMAPHORE)
JMP SCHED ; GOT SCHEDULE
;-----------------------------------------------------------------------
;
; PROCEDURE SIGNALCH (SEMAPHORE, OPERATION)
;
; THIS PROCEDURE DELIVERS AN OPERATION AT A CHAINED SEMAPHORE.
; IN CASE A COROUTINE IS ALREADY WAITING AT THE SEMAPHORE, THE OPERA-
; TION IS HANDED TO THIS COROUTINE, WHICH IS THEN PUT INTO THE READY
; QUEUE (FOR LATER ACTIVATION).
; IN CASE NO COROUTINE WAITS AT THE SEMAPHORE, THE OPERATION IS LINKED
; TO IT, WAITING TO BE FETCHED BY WAITCH.
; CALL: EXIT:
; R4 OPERATION ADDRESS UNCHANGED
; R5 SEMAPHORE ADDRESS UNCHANGED
; R6 LINK UNCHANGED
; R7 CURRENT COROUTINE UNCHANGED
; -- IRRELEVANT UNCHANGED
SIGNCH: MOV R4 SV4. X7 ; SAVE R4,
MOV R5 SV5. X7 ; R5,
MOV R6 SV6. X7 ; AND R6
INC SEMVAL.X5 ; INCREASE SEMAPHORE VALUE
MOV SEMVAL.X5 R6 ;
NOLIST
IF TPON THEN
MOV R6 DVAL
MOV R4 DOP
MON OLTO, TPOS OR 4
TPSGCH
MOV CURRC R7
FI
LIST
SGE R6 1 ; IF SEMVALUE > 0
JMP SCHLSE ; THEN
JMP S6 LINKON ; LINKON(OPERATION,SEMAPHORE)
JMP SCHXIT ; ELSE
SCHLSE: MOV SEMFST.X5 R4 ; FIRST WAITING COROUTINE
MOV READYQ R5 ; READY QUEUE
JMP S6 LINK ; LINK(WAITINGCORU, READYQYEYE)
MOV SV4. X7 R6 ; OPERATION
MOV R6 SV4. X4 ; OPERATION => SV4.WAITINGCORU
MOV SV4. X7 R4 ; OPERATION
JMP S6 LINKOFF ; LINKOFF(OPERATION)
SCHXIT: MOV SV4. X7 R4 ; REESTABLISH R4,
MOV SV5. X7 R5 ; R5,
MOV SV6. X7 R6 ; AND R6
JMP 0. X6 ; RETURN TO LINK
;-----------------------------------------------------------------------
;
; PROCEDURE WAITCH (SEMAPHORE, OPERATION)
;
; THIS PROCEDURE FETCHES AN OPERATION FROM A SEMAPHORE.
; IN CASE AN OPERATION IS READY WHEN THE PROCEDURE IS CALLED, THE OPE-
; RATION IS SIMPLY HANDED TO THE CALLING COROUTINE.
; IN CASE NO OPERATION IS READY AT CALL TIME, THE CALLING COROUTINE IS
; DELAYED UNTIL AN OPERATION ARRIVES FOR IT.
; CALL: EXIT:
; R4 IRRELEVANT OPERATION ADDRESS
; R5 SEMAPHORE UNCHANGED
; R6 LINK UNCHANGED
; R7 CURRENT COROUTINE UNCHANGED
; -- IRRELEVANT UNCHANGED
WAITCH: MODC SV6+1 ; STACK
STC 6 ; R0 - R6
MOV CURRC R7 ; REESTABLISH R7
DEC SEMVAL.X5 ; DECREMENT (SEMVAL.SEMAPHORR)
MOV SEMVAL.X5 R6 ; SEMVALUE
NOLIST
IF TPON THEN
MOV R6 DVAL
MON OLTO, TPOS OR 5
TPWTCH
MOV CURRC R7
FI
LIST
SLT R6 0 ; IF SEMVALUE < 0
JMP WCHLSE ; THEN
MOV R7 R4 ; CURRENT COROUTINE
JMP S6 LINK ; LINK(CURRENTCORU, SEMAPHORE)
JMP SCHED ; ELSE
WCHLSE: MOV SEMFST.X5 R4 ; FIRST WAITING OPERATION
JMP S6 LINKOFF ; LINKOFF(OPERATION)
MOV R4 SV4. X7 ; OPERATION => SV4.CURRENTCORU
JMP SCHED ; GOTO SCHEDULE
;-----------------------------------------------------------------------
;
; PROCEDURE WAITANSWER (MESSAGEREF)
;
; THIS PROCEDURE INDICATES THAT THE CALLING COROUTINE IS TO BE DELAYED
; UNTIL AN ANSWER ARIVES TO THE MESSAGE POINTED OUT BY MESSAGEREF.
; THIS IS A WAITING POINT PROCEDURE.
; CALL: EXIT:
; R2 MESSAGEREF UNCHANGED
; R7 CURRENT COROUTINE UNCHANGED
; -- IRRELEVANT UNCHANGED
WANSW: MODC SV6+1 ; STACK
STC 6 ; R0 _ R6
MOV CURRC R7 ; REESTABLISH R7
NOLIST
IF TPON THEN
MOV R7 DCORU
MON OLTO, TPOS OR 6
TPWANS
MOV CURRC R7
FI
LIST
MOV R7 R4 ; CURRENT COROUTINE
MOV ANSWQ R5 ; ANSWER QUEUE
JMP S6 LINK ; LINK (CURRENT, ANSWER QUEUE)
JMP SCHED ; GOTO SCHEDULE
;-----------------------------------------------------------------------
;
; PROCEDURE WAITMESSAGE (EVENT, MESSAGE), (ALREADY AWAITED, NORMAL)
;
; THIS PROCEDURE INDICATES THAT THE CALLING COROUTINE IS TO BE DELAYED
; UNTIL A MESSAGE ARRIVES TO THE PROCESS.
; NOTE, THAT ONLY ONE COROUTINE MAY WAIT FOR MESSAGES AT A TIME.
; (USUALLY A DEDICATED MESSAGE SCHEDULER COROUTINE IS THE ONLY COROU_
; TINE AWAITING MESSAGES).
; THIS IS A WAITING POINT PROCEDURE.
; CALL: EXIT:
; R1 IRRELEVANT MESSAGE ADDRESS
; R2 IRRELEVANT EVENT
; R7 CURRENT COROUTINE UNCHANGED
; -- IRRELEVANT UNCHANGED
WTMESS: MODC SV6+1 ; STACK
STC 6 ; R0 - R6
MOV CURRC R7 ; REESTABLISH R7
NOLIST
IF TPON THEN
MOV R7 DCORU
MON OLTO, TPOS OR 7
TPWTMS
MOV CURRC R7
FI
LIST
MOV MESSC R2 ; IF ANOTHER COROUTINE IS WAITING
JON R2 0. X6 ; THEN RETURN TO LINK
INC SV6. X7 ; ELSE INCREMENT LINK
MOV R7 MESSC ; CURRC => WAITING FOR MESSAGE
MOV R7 R4 ; CURRENT COROUTINE
JMP S6 LINKOFF ; LINKOFF(CURRENT COROUTINE)
JMP SCHED ; GOTO SCHEDULE
;-----------------------------------------------------------------------
;
; PROCEDURE WAITTIMER_OR_INTERRUPT (), (ALREADY AWAITED, NORMAL)
;
; THIS PROCEDURE INDICATES THAT THE CALLING COROUTINE IS TO BE DELAYED
; UNTIL THE PROCESS IS INTERRUPTED OR TIMED OUT.
; NOTE, THAT ONLY ONE COROUTINE MAY WAIT FOR THESE EVENTS AT A TIME.
; THIS IS A WAITING POINT PROCEDURE.
; CALL: EXIT:
; R7 CURRENT COROUTINE UNCHANGED
; -- IRRELEVANT UNCHANGED
WTINTR: MODC SV6+1 ; STACK
STC 6 ; R0 _ R6
MOV CURRC R7 ; REESTABLISH R7
NOLIST
IF TPON THEN
MOV R7 DCORU
MON OLTO, TPOS OR 8
TPWTTI
MOV CURRC R7
FI
LIST
MOV TINTRC R0 ; IF ANOTHER COROUTINE IS WAITING
JON R0 0. X6 ; THEN RETURN TO LINK
INC SV6. X7 ; ELSE INCREMENT LINK
MOV R7 TINTRC ; CURRC => WAITING COROUTINE
MOV R7 R4 ; CURRENT COROUTINE
JMP S6 LINKOFF ; LINKOFF(CURRENT COROUTINE)
JMP SCHED ; GOTO SCHEDULE
;-----------------------------------------------------------------------
;
; COROUTINE INITIALIZATION
;
; THIS PIECE OF CODE INITIALIZES ALL COROUTINE DESCRIPTORS AND PUTS
; ALL COROUTINES INTO THE READY QUEUE.
; THIS IS DONE BY SCANNING THE LIST OF COROUTINE BLOCKS (TYPICALLY
; THERE WILL BE A BLOCK PER COROUTINE TYPE - CONTAINING A NUMBER OF
; OF INCARNATIONS OF THE ACTUAL COROUTINE TYPE).
; INITIALIZATION RECORD
AX=0
ICHAIN:= AX, AX=AX+1 ; CHAIN TO NEXT INIT BLOCK
IPRPC:= AX, AX=AX+1 ; ENTRY POINT OF COROUTINE
ISIZE:= AX, AX=AX+1 ; SIZE OF COROUTINE RECORD
ICOUNT:= AX, AX=AX+1 ; NUMBER OF COROUTINES IN BLOCK
COINIT: MOV CURRC R1 ; START OF INITIALIZATION CHAIN
NXTBLC: JOZ R1 SCHED ; IF NO MORE BLOCKS THEN SCHEDULE
ADDC -4 R1 ; START OF INIT RECORD
MOV R1 R7 ; CURRENT COROUTINE
MOV ICOUNT.X7 R0 ; COROUTINE COUNTER
MOV IPRPC. X7 R2 ; ENTRY POINT
MOV ISIZE. X7 R3 ; COROUTINE RECORD SIZE
MOV ICHAIN.X7 R1 ; ADDRESS OF NEXT BLOCK IN CHAIN
MOV READYQ R5 ; READY CUEUE
NEXTC: MOV R7 R4 ; CURRENT COROUTINE
MOV R7 SUCC. X7 ; INIT CHAIN FIELDS
MOV R7 PRED. X7 ;
JMP S6 LINK ; LINK (CURRENT, READY QUEUE)
MOV R2 SV6. X7 ; SET ENTRY POINT (SAVED LINK)
ADD R3 R7 ; NEXT COROUTINE RECORD
SOB R0 NEXTC ; REPEAT UNTIL COUNT = 0
JMP NXTBLC ; GOTO NEXT BLOCK
«eof»