! ! TO MAKE S SERIES SUPERVISOR REQUIRES:- ! 1) UNCOMMENT S SERIES INTERUPT SEQUENCE AFTER IST4I: AND DISCARD ! P SERIES INTERUUPT CODE ! 2) REPLACE COMF BY S SERIES COM IN ERCC08.COMSF ! 3) CHANGE ALL CALL OF GPC TO DCU ! 4) UNCOMMENT ALL LINES STARTED BY !PSERIES ! %INTEGERFNSPEC REQUEST INPUT(%INTEGER OUTPUT POSN,TRIGGER POSN) %INTEGERFNSPEC REQUEST OUTPUT(%INTEGER OUTPUT POSN,TRIGGER POSN) %INTEGERFNSPEC CHANGE CONTEXT %LONGINTEGERFNSPEC RTDR(%INTEGERFN A) %EXTERNALROUTINE SUP29 !----------------------------------------------------------------------- %OWNSTRING(3) SUPID="24N" !----------------------------------------------------------------------- !* COMMUNICATIONS RECORD FORMAT - EXTANT FROM CHOPSUPE 18D ONWARDS * %RECORDFORMAT COMF(%INTEGER OCPTYPE,IPLDEV,SBLKS,SEPGS,NDISCS, %C DDTADDR,GPCTABSIZE,GPCA,SFCTABSIZE,SFCA,SFCK,DIRSITE, %C DCODEDA,SUPLVN,KLOKCORRECT,DATE0,DATE1,DATE2, %C TIME0,TIME1,TIME2,EPAGESIZE,USERS,PROCMON,DQADDR, %C SACPORT,OCPPORT,ITINT,CONTYPEA,GPCCONFA,FPCCONFA,SFCCONFA, %C BLKADDR,DPTADDR,SMACS,TRANS,%LONGINTEGER KMON, %C %INTEGER SPDRQ,SMACPOS,SUPVSN,PSTVA,SECSFRMN,SECSTOCD, %C SYNC1DEST,SYNC2DEST,ASYNCDEST,MAXPROCS,INSPERSEC,ELAPHEAD, %C COMMSRECA,STOREAAD,PROCAAD,SFCCTAD,DRUMTAD,SP0,SP1,SP2,SP3, %C SP4,SP5,SP6,SP7,SP8,SP9, %C LSTL,LSTB,PSTL,PSTB,HKEYS,HOOT,SIM,CLKX,CLKY,CLKZ, %C HBIT,SLAVEOFF,INHSSR,SDR1,SDR2,SDR3, %C SDR4,SESR,HOFFBIT,S2,S3,S4,END) %RECORDNAME COM(COMF) COM==RECORD(X'80000000'+48<<18) STRING(ADDR(COM_SUPVSN))=SUPID %CONSTINTEGER VIRTAD=X'81000000' %CONSTINTEGER MAXPROCS=128 COM_MAXPROCS=MAXPROCS !%INTEGER EPAGESIZE,SEGEPSIZE ! EPAGESIZE=COM_EPAGESIZE ! SEGEPSIZE=256//EPAGESIZE %CONSTINTEGER EPAGESIZE=4,SEGEPSIZE=64 !----------------------------------------------------------------------- ! PERIPHERAL CONTROLLER CONFIGURATION DECLARATIONS %BYTEINTEGERARRAYNAME CONTYPE %BYTEINTEGERARRAYFORMAT CONTYPEF(0:15) CONTYPE==ARRAY(COM_CONTYPEA,CONTYPEF) %SWITCH CONROUT(0:3) %INTEGERARRAYNAME BLOCKAD %INTEGERARRAYFORMAT BLOCKADF(0:63) BLOCKAD==ARRAY(COM_BLKADDR,BLOCKADF) !----------------------------------------------------------------------- ! MISC. ROUTINE SPECS %EXTERNALROUTINESPEC SLAVESONOFF(%INTEGER ONOFF) %EXTERNALSTRING(15)%FNSPEC STRINT(%INTEGER N) %EXTERNALSTRING(8)%FNSPEC STRHEX(%INTEGER N) %EXTERNALSTRING(63)%FNSPEC STRSP(%INTEGER N) %EXTERNALROUTINESPEC PTREC(%RECORDNAME P) %EXTERNALROUTINESPEC MONITOR(%STRING(63) S) %EXTERNALROUTINESPEC OPMESS(%STRING(63) S) %EXTERNALROUTINESPEC DISPLAY TEXT(%INTEGER SCREEN,LINE,CHAR, %C %STRING(41) S) %EXTERNALROUTINESPEC UPDATE TIME %EXTERNALROUTINESPEC DPONPUTONQ(%RECORDNAME P) %EXTERNALROUTINESPEC TURNONER(%RECORDNAME P) %EXTERNALROUTINESPEC DUMP TABLE(%INTEGER TABNO,ADR,LEN) %ROUTINESPEC PROCMON CONTROL(%RECORDNAME P) %INTEGER I,J,K,FSTASL,BSTASL,FREEEPAGES,UNALLOCEPS,OVERALLOC, %C DEADLOCKS,STASLSEMA,DRUMSIZE,DRUMTASL,MAXP4,KSERVICE,LSERVICE, %C CURPROC1,CURPROC2,OLDLNB,ACTW0,ACTW1,ACTW2,ACTW3,IDLE,LCN, %C MPLEVEL,PAGEFREES,SESTK,SEIP,SELN,SCASSPC,KSTACK,ISTAD, %C LNBP5,PORT,GETEPN ?%INTEGER DRUMALLOC,MAXABTN,RECAPN,PTURNN,PSHAREN,IDLEN,LPN,XSTRN,XSTREP %LONGINTEGER L %STRING(3) STRPROC !----------------------------------------------------------------------- %RECORDFORMAT SSNP1F(%INTEGER LNB,PSR,PC,SSR,SF,IT,IC,LTB,XNB,%C B,DR0,DR1,A0,A1,A2,A3,PEAD,II) %RECORD LSSNP1I(SSNP1F) %RECORDFORMAT ISTF(%INTEGER LNB,PSR,PC,SSR,SF,IT,IC,SP) %RECORD KSSNP1,LSSNP1,ISTDUM(ISTF) %RECORDNAME ISTP,KSSNP1P,LSSNP1P(ISTF) %LONGINTEGERARRAYFORMAT PSTF(0:127) ;! PUBLIC SEGMENT TABLE FORMAT %LONGINTEGERARRAYNAME PST %INTEGERARRAYFORMAT PTF(0:255) ;! PAGE TABLE FORMAT !----------------------------------------------------------------------- ! STORE TABLE ETC. DECLARATIONS %RECORDFORMAT STOREF(%BYTEINTEGER FLAGS,USERS, %C %HALFINTEGER LINK,BLINK,FLINK,%INTEGER REALAD) %RECORDARRAY STORE(0:COM_SEPGS-1)(STOREF) ;! ONE RECORD PER EPAGE %INTEGERNAME STORESEMA !----------------------------------------------------------------------- ! ACTIVE MEMORY TABLE DECLARATIONS ETC. %CONSTINTEGER AMTASEG=21 %CONSTINTEGER MAXAMTAK=MAXPROCS//2//EPAGESIZE*EPAGESIZE %RECORDFORMAT AMTF(%INTEGER DA,%HALFINTEGER DDP,LINK,USERS, %C %BYTEINTEGER LEN,OUTS) ! DA : DISC ADDRESS ! DDP : AMTDD POINTER ! LINK : COLLISION LINK ! USERS : NO OF USERS OF PAGES OF THIS BLOCK ! LEN : BLOCK LENGTH IN EPAGES ! OUTS : NO OF PAGE-OUTS OF PAGES IN THIS BLOCK IN PROGRESS %CONSTINTEGER AMTFLEN=12 %RECORDARRAYFORMAT AMTAF(1:MAXAMTAK<<10//AMTFLEN)(AMTF) %RECORDARRAYNAME AMTA(AMTF) %CONSTINTEGER AMTDDSEG=22 %CONSTINTEGER MAXAMTDDK=MAXPROCS//EPAGESIZE*EPAGESIZE %CONSTINTEGER DDFLEN=2 %HALFINTEGERARRAYFORMAT AMTDDF(1:MAXAMTDDK<<10//DDFLEN) %HALFINTEGERARRAYNAME AMTDD ! EACH %HALF %INTEGER : NEW EPAGE(1) / STOREX-DRUMTX(1) / ?X(14) %CONSTINTEGER MAXBLOCK=16 ;! MAX BLOCK SIZE %IF COM_SFCK=0 %THEN DRUMSIZE=0 %ELSE DRUMSIZE=COM_SFCK//EPAGESIZE %HALFINTEGERARRAY DRUMT(0:DRUMSIZE) ! SPARE(2) / STOREX(14) %CONSTINTEGER DTEND=X'FFFF' %CONSTINTEGER NEWEPBIT=X'8000' %CONSTINTEGER DTXBIT=X'4000' %CONSTINTEGER STXMASK=X'3FFF' %CONSTINTEGER DDBIT=X'8000' !----------------------------------------------------------------------- ! SCHEDULING CATEGORY TABLES ETC. %RECORDFORMAT CATTABF(%BYTEINTEGER PRIORITY,EPLIM,RTLIM,MOREP,MORET, %C LESSP,LESST,SUSP,RQTS1,RQTS2,SP1,SP2) %RECORDARRAYFORMAT CATTABAF(0:13)(CATTABF) %RECORDARRAYNAME CATTAB(CATTABF) %OWNBYTEINTEGERARRAY CATDATA(0:12*14-1)= %C 1, 0, 0, 0, 0, 0, 0, 0, 1,1, 0,0, 1,72, 6, 11, 9, 5, 8, 8, 1,1, 0,0, 1,24, 4, 5, 3, 0, 0, 2, 1,1, 0,0, 2,24, 8, 6, 4, 0, 2, 2, 1,2, 0,0, 3,24,24, 7, 4, 0, 3, 2, 2,2, 0,0, 2,48, 4, 8, 6, 2, 0, 5, 1,1, 0,0, 3,48, 8, 9, 7, 3, 5, 5, 1,2, 0,0, 4,48,20, 10, 7, 4, 6, 5, 2,2, 0,0, 2,72, 4, 11, 9, 5, 0, 8, 1,1, 0,0, 3,72, 8, 12,10, 6, 8, 8, 1,2, 0,0, 4,72,16, 13,10, 7, 9, 8, 2,2, 0,0, 3,96, 4, 11,12, 8, 0,11, 1,1, 0,0, 3,96, 8, 12,13, 9,11,11, 1,2, 0,0, 4,96,16, 13,13,10,12,11, 2,2, 0,0; %OWNINTEGER MAXEPAGES=96 CATTAB==ARRAY(ADDR(CATDATA(0)),CATTABAF) !----------------------------------------------------------------------- ! PON & POFF ETC. DECLARATIONS %EXTERNALROUTINESPEC PON(%RECORDNAME P) %EXTERNALROUTINESPEC FASTPON(%INTEGER CELL) %EXTERNALINTEGERFNSPEC NEWPPCELL %EXTERNALROUTINESPEC RETURN PPCELL(%INTEGER PPCELL) %EXTERNALROUTINESPEC SEMALOOP(%INTEGERNAME SEMA) %EXTERNALROUTINESPEC POFF(%RECORDNAME P) %EXTERNALROUTINESPEC SUPPOFF(%RECORDNAME SERV,P) %EXTERNALROUTINESPEC INHIBIT(%INTEGER SERVICE) %EXTERNALROUTINESPEC UNINHIBIT(%INTEGER SERVICE) %EXTERNALROUTINESPEC CLEAR PARMS(%INTEGER SERVICE) %EXTERNALINTEGERFNSPEC PPINIT(%INTEGERFN NEW EPAGE) %INTEGERFNSPEC NEW EPAGE %RECORDFORMAT PARMF(%INTEGER DEST,SRCE,P1,P2,P3,P4,P5,P6) %RECORDFORMAT PARMAF(%INTEGERARRAY P(0:7)) %RECORDFORMAT PARMXF(%INTEGER DEST,SRCE,P1,P2,P3,P4,P5,P6,LINK) %RECORDARRAYFORMAT PARMSPF(0:2015)(PARMXF) %RECORDARRAYNAME PARM(PARMXF) ;! 0 NOT USED %CONSTINTEGER LOCSN0=64 %CONSTINTEGER LOCSN1= LOCSN0+MAXPROCS COM_SYNC1DEST=LOCSN1 %CONSTINTEGER LOCSN2= LOCSN0+2*MAXPROCS COM_SYNC2DEST=LOCSN2 %CONSTINTEGER LOCSN3= LOCSN0+3*MAXPROCS COM_ASYNCDEST=LOCSN3 %CONSTINTEGER MAXSERV= LOCSN0+4*MAXPROCS %RECORDFORMAT SERVF(%INTEGER P,L) %RECORDNAME KSERV,KSERVQ,LSERV,LSERVQ(SERVF) %EXTRINSICRECORDARRAY SERVA(0:MAXSERV)(SERVF) ;! 0 NOT USED %RECORD P(PARMF) %EXTRINSICINTEGER KERNELQ,RUNQ1,RUNQ2 %INTEGERNAME RUNQ,CURPROC %EXTERNALLONGINTEGER KMON KMON=COM_KMON !----------------------------------------------------------------------- ! SERVICE ROUTINE SPECS %ROUTINESPEC SCHEDULE(%RECORDNAME P) %ROUTINESPEC PAGETURN(%RECORDNAME P) %ROUTINESPEC GET EPAGE(%RECORDNAME P) %ROUTINESPEC RETURN EPAGE(%RECORDNAME P) %ROUTINESPEC DEADLOCK %ROUTINESPEC ACTIVE MEM(%RECORDNAME P) ?%ROUTINESPEC CLEAR TIME %LONGINTEGERFNSPEC CLOCK %ROUTINESPEC UPDISP(%INTEGER PROCESS,OFFSET,%STRING(13) S) %EXTERNALROUTINESPEC ELAPSEDINT(%RECORDNAME P) %EXTERNALROUTINESPEC SEMAPHORE(%RECORDNAME P) !PSERIES;%EXTERNALROUTINESPEC DISC(%RECORDNAME P) !SSERIES %EXTERNALROUTINESPEC DISC MINDER(%RECORDNAME P) %EXTERNALROUTINESPEC PDISC(%RECORDNAME P) %EXTERNALROUTINESPEC MOVE(%RECORDNAME P) %EXTERNALROUTINESPEC DRUM(%RECORDNAME P) %EXTERNALROUTINESPEC GPC(%RECORDNAME P) %EXTERNALROUTINESPEC TAPE(%RECORDNAME P) %EXTERNALROUTINESPEC OPER(%RECORDNAME P) %EXTERNALROUTINESPEC PRINTER(%RECORDNAME P) %EXTERNALROUTINESPEC LP ADAPTOR(%RECORDNAME P) %EXTERNALROUTINESPEC CR ADAPTOR(%RECORDNAME P) %EXTERNALROUTINESPEC CP ADAPTOR(%RECORDNAME P) %EXTERNALROUTINESPEC COMMS CONTROL(%RECORDNAME P) %EXTERNALROUTINESPEC MK1FEADAPTOR(%RECORDNAME P) %EXTERNALROUTINESPEC COMREP(%RECORDNAME P) %SWITCH SERVROUT(1:64) ;! KERNEL SERVICES, (1:LOCSN0) !----------------------------------------------------------------------- ! TIMING INFORMATION DECS. ?%ROUTINESPEC TIMEOUT(%RECORDNAME P) %LONGINTEGERARRAY SERVIT,SERVIC(0:LOCSN0+2) %INTEGERARRAY SERVN(0:LOCSN0+2) %LONGINTEGER CLOCK0,IDLEIT,LCIT,LCIC,LPIT ?%LONGINTEGER PTIT,PTIC,DRUMIT,DRUMIC,PDISCIT,PDISCIC,GETIT,GETIC, %C AMIT,AMIC ?%INTEGER PTCALLN,DRUMCALLN,PDISCCALLN,AMCALLN,GETCALLN,IT,ITT,IC,ICC %INTEGERNAME KIT ;! IT IN KERNEL CONTEXT !----------------------------------------------------------------------- ! PROCESS INORMATION ARRAY DECS ETC. %RECORDFORMAT PROCF(%STRING(6) USER,%BYTEINTEGER INCAR,CATEGORY, %C RUNQ,ACTIVE,%INTEGER LAMTX,LSTAD,STACK, STATUS) %EXTERNALRECORDARRAY PROCA(0:MAXPROCS)(PROCF) %EXTERNALINTEGER PROCMON=0 !----------------------------------------------------------------------- ! LOCAL CONTROLLER DECS ETC. %ROUTINESPEC LOCAL CONTROL %CONSTINTEGER LSTLEN=128 ;! LOCAL SEGMENT TABLE LENGTH %LONGINTEGERARRAYFORMAT LSTF(0:LSTLEN-1) %CONSTINTEGER LSTACKLEN=3 ;! LOCAL CONT. STACK ELEN %CONSTINTEGER LSTACKLENP=2 ;! PAGED PART %CONSTINTEGER LSTKN=3 ;! NO OF LOCAL STACKS %CONSTLONGINTEGER DIRACR=1 ;! DIRECTOR ACR LEVEL %CONSTINTEGER MAXIT=X'FFFFFF' %CONSTINTEGER TIMESLICE=X'4000' ;! 131072 MICROSECS %CONSTINTEGER OUT18CHARGE=X'400'; ! CHARGE FOR OUT18 =8 MILLESECS %OWNINTEGER OUT18INS; ! CHARGE *INS RATE %EXTERNALINTEGERFNSPEC SYSTEMCALL %CONSTINTEGER COMMSALLOC=8 %EXTRINSICINTEGER QUEUED STREAMS !----------------------------------------------------------------------- ! INTERRUPT ROUTINE SPECS %EXTERNALROUTINESPEC SYSERR(%INTEGER STK,IP) !----------------------------------------------------------------------- ! INITIALISE IST (AFTER DECLARATIONS I.E. LNB & SF VALID) ISTAD=X'80000000'+COM_OCPPORT<<18 ISTP==RECORD(ISTAD) ;! IST BASE *STLN_OLDLNB ;! USED TO FRIG %MONITOR LATER ISTP_LNB=OLDLNB ISTP_PSR=X'00140001' ;! ACR=1, PRIV=1, PM=0, ACS=1 ISTP_PC=0 ISTP_SSR=X'01800FFE' ;! ONLY SYSERR *STSF_I ISTP_SF=I ISTP_IT=MAXIT ISTP_IC=MAXIT ISTP_SP=0 %CYCLE I=ISTAD+X'20',X'20',ISTAD+X'160' RECORD(I)<-ISTP %REPEAT ! SET UP LOCAL CONTROLLER->KERNEL CONTEXT KSSNP1=ISTP *JLK_ ; *LSS_%TOS ; *ST_I KSSNP1_PC=I KSTACK=OLDLNB&X'FFFC0000' KSSNP1P==RECORD(KSTACK!X'40000') LSSNP1P==RECORD(X'40000') ! MASK SYSERR. ON SYSERR. INTERRUPT ISTP_SSR=X'01800FFF' ! SET SYSTEM ERROR SF TO DISTANT PLACE ISTP_SF=ISTP_SF+X'1000' ! INSERT PCS *LXN_ISTAD *JLK_ ; *LSS_%TOS ; *ST_(%XNB+2) *JLK_ ; *LSS_%TOS ; *ST_(%XNB+10) *JLK_ ; *LSS_%TOS ; *ST_(%XNB+18) *JLK_ ; *LSS_%TOS ; *ST_(%XNB+26) *JLK_ ; *LSS_%TOS ; *ST_(%XNB+34) *JLK_ ; *LSS_%TOS ; *ST_(%XNB+42) *JLK_ ; *LSS_%TOS ; *ST_(%XNB+50) *JLK_ ; *LSS_%TOS ; *ST_(%XNB+58) *JLK_ ; *LSS_%TOS ; *ST_(%XNB+66) *JLK_ ; *LSS_%TOS ; *ST_(%XNB+74) *JLK_ ; *LSS_%TOS ; *ST_(%XNB+82) *JLK_ ; *LSS_%TOS ; *ST_(%XNB+90) !----------------------------------------------------------------------- ! CREATE LOCAL CONTROLLER CONTEXT LSSNP1I=0 LSSNP1I_LNB=LSTLEN*8+LSTKN*X'80'+X'50' LSSNP1I_PSR=X'00140001' *JLK_ *LSS_%TOS *ST_I LSSNP1I_PC=I ;! GOES TO CALL OF LOCAL CONTROL AFTER ACTIVATE LSSNP1I_SSR=X'01800FFE' LSSNP1I_SF=LSTLEN*8+LSTKN*X'80'+X'80' ;! 12 MORE WORDS AFTER LNB LSSNP1I_IT=MAXIT LSSNP1I_IC=MAXIT *LSS_(%LNB+5) ;! PRESERVE DISPLAY PTR *ST_LNBP5 !----------------------------------------------------------------------- ! GET SYSTEM CALL ASSEMBLER PC SCASSPC=SYSTEMCALL COM_DCODEDA=COM_SUPLVN<<24!COM_DIRSITE !----------------------------------------------------------------------- ! SET UP CLOCK REGS I=COM_CLKZ *LB_I *LSS_13 ;! SHOULD GIVE 1 INTERRUPT EVERY 2 SECS (APPROX) *ST_(0+%B) ;! Z-REG %IF COM_OCPTYPE=4 %THEN %START ;! 2980 ONLY I=X'80000000'>>COM_SACPORT *LB_X'4012' *LSS_(0+%B) *OR_I *ST_(0+%B) %FINISH %ELSE %START %IF COM_OCPTYPE=6 %THEN %START ;! 2976 I=X'80000000'>>COM_OCPPORT *LB_X'4012' *LSS_(0+%B) *OR_I *ST_(0+%B) %FINISH %FINISH OUT18INS=OUT18CHARGE*1000*COM_ITINT//COM_INSPERSEC !----------------------------------------------------------------------- ! FIND END OF KERNEL STACK ETC. PST==ARRAY(X'80040000',PSTF) ;! PST IN SEG 8193 (OCPPORT NEVER 1) ! CLEAR CHOPSUPE CODE GLA & STACK SEGMENTS FROM PST PST(44)=0 ; PST(45)=0 ; PST(46)=0 ; PST(47)=0 ! CLEAR 8 K OF STACK %CYCLE I=0,1,7999; *LSD_0; *ST_%TOS; %REPEAT %CYCLE I=0,1,7999; *LSD_%TOS; %REPEAT K=128//EPAGESIZE ;! EPAGESPERBLOCK %CYCLE I=0,1,COM_SEPGS-1 STORE(I)=0 J=I//K STORE(I)_REALAD=BLOCKAD(J)!(EPAGESIZE*(I-J*K))<<10 %REPEAT ! SET KERNEL STACK SEGMENT LIMIT L=(ISTP_SF&X'3FFFF'+X'107F')>>7 I=PST(4)&X'0FFFFFF8'+L<<7 J=EPAGESIZE<<10 K=(I+J-1)//J*J ;! ALLIGN ON EPAGE L=L+(K-I)>>7 PST(4)=PST(4)&X'FFFC007FFFFFFFFF'!(L-1)<<39 ! INITIALISE FREE STORE PAGES ARRAY FSTASL=K//J BSTASL=COM_SEPGS-1 %CYCLE I=FSTASL,1,BSTASL-1 STORE(I)_FLINK=I+1 %REPEAT STORE(BSTASL)_FLINK=0 FREEEPAGES=COM_SEPGS-FSTASL J=12 ;! USE 12K TO 16K %IF COM_OCPTYPE=3 %THEN K=16 %ELSE K=32 ;! USE OVERLAY AREA IF NOT 2970 J=(J+EPAGESIZE-1)//EPAGESIZE K=K//EPAGESIZE-1 %CYCLE I=J,1,K STORE(I)_FLINK=I+1 %REPEAT STORE(K)_FLINK=FSTASL FSTASL=J FREEEPAGES=FREEEPAGES+K-J+1 STORE(FSTASL)_BLINK=0 I=FSTASL ;! SET UP BACKWARD LINKS %UNTIL I=BSTASL %CYCLE J=I I=STORE(I)_FLINK STORE(I)_BLINK=J %REPEAT STORESEMA==STORE(0)_REALAD STORESEMA=-1 STASLSEMA=-1 GETEPN=0 !----------------------------------------------------------------------- COM_STOREAAD=ADDR(STORE(0)) COM_PROCAAD=ADDR(PROCA(0)) COM_DRUMTAD=ADDR(DRUMT(0)) PARM==ARRAY(PPINIT(NEW EPAGE),PARMSPF) OVERALLOC=COM_SEPGS//5; ! 20% OVERALLOCATION UNALLOCEPS=FREEEPAGES+OVERALLOC-COMMSALLOC CURPROC1=0 CURPROC2=0 IDLE=0 KIT==INTEGER(X'80140014') !----------------------------------------------------------------------- ! INITIALISE ACTIVATE WORDS ACTW0=(LSTLEN-1)<<18 ACTW2=0 ;! NOT USED !----------------------------------------------------------------------- ! INITIALISE GPC, DRUM & DISC ROUTINES P_DEST=X'300002' !PSERIES; P_P1=COM_GPCA !SSERIES P_P1=COM_DCUA GPC(P) P_DEST=X'370000' P_P1=EPAGESIZE P_P2=COMMSALLOC P_P3=ADDR(PARM(0)) COMMS CONTROL(P) P_DEST=X'200000' !PSERIES; DISC(P) %UNLESS DRUMSIZE=0 %THEN %START P_DEST=X'280000' P_P1=EPAGESIZE P_P2=COM_SFCA P_P3=ADDR(STORE(0)) P_P4=ADDR(PARM(0)) DRUM(P) %FINISH !----------------------------------------------------------------------- ! TURN ON SLAVING WHICH HAS BEEN INHIBITED BY CHOPSUPE SLAVESONOFF(-1) !----------------------------------------------------------------------- ! INITIALISE LEFT-HAND OPER SCREEN DISPLAY TEXT(0,0,0," EMAS 2900 SUP".SUPID) DISPLAY TEXT(0,0,22,STRING(ADDR(COM_DATE0)+3)) %CYCLE I=1,1,MAXPROCS STRPROC=STRINT(I) UPDISP(I,3-LENGTH(STRPROC),STRPROC) %REPEAT P_DEST=X'30000' SCHEDULE(P) P_DEST=X'80000' ACTIVE MEM(P) !----------------------------------------------------------------------- ! START "DIRECT" PROCESS P_DEST=X'30001' P_SRCE=0 ;! NO REPLY WANTED STRING(ADDR(P_P1))="DIRECT" P_P3=COM_SUPLVN<<24!X'400' ;! LSTACKDA P_P4=0 ;! USE DEFAULT DIRVSN P_P5=P_P3+LSTACKLEN ;! DSTACKDA P_P6=P_P5+SEGEPSIZE ;! DGLADA PON(P) !----------------------------------------------------------------------- ! CLEAR TIMING ARRAY ETC. ? CLEAR TIME P_DEST=X'A0001' P_SRCE=0 P_P1=X'B0000' P_P2=2 PON(P) ;! KICK UPDATE TIME ? P_P1=X'3000F' ? PON(P) ;! UPDATE SCHEDULER INFO ON OPER P_P1=X'320009' PON(P) ;! DISPLAY OPER P_P1=X'360000' PON(P) ;! KICK PRINTER P_P1=X'80004' P_P2=10 PON(P) ;! ACTIVE MEM P_P1=X'D0001' PON(P) ;! KICK ERROR REPORTING !----------------------------------------------------------------------- ! SERVICE LOOPS KSERVE:! KERNEL SERVICES ? *LSS_X'FFFFFF' ;! SET IT & IC TO MAX. ? *ST_(5) ? *ST_(6) *LSS_X'01800820' ;! LET INTERRUPTS IN *ST_(3) *LSS_X'01800FFE' *ST_(3) %IF KERNELQ=0 %THEN %START %IF CURPROC1=0 %THEN %START %IF RUNQ1#0 %THEN CURPROC==CURPROC1 %AND RUNQ==RUNQ1 %AND ->LSERVE %IF CURPROC2=0 %THEN %START %IF RUNQ2#0 %THEN CURPROC==CURPROC2%AND RUNQ==RUNQ2%AND ->LSERVE ? IDLEN=IDLEN+1 IDLE=1 *LSS_X'01800820' ;! ALL EXCEPT TIMER INTERRUPTS *ST_(3) IDLE0: *IDLE_0 ->IDLE0 ;! IN CASE "EKS" SET %FINISH %ELSE CURPROC==CURPROC2 %AND RUNQ==RUNQ2 %FINISH %ELSE CURPROC==CURPROC1 %AND RUNQ==RUNQ1 ? LPN=LPN+1 ACTW1=PROCA(CURPROC)_LSTAD ACTW3=PROCA(CURPROC)_STACK *ACT_ACTW0 ;! REACTIVATE INTERRUPTED PROCESS %FINISH KSERVQ==SERVA(KERNELQ) KSERVICE=KSERVQ_L KSERV==SERVA(KSERVICE) %IF KSERV_P>0 %THEN %START %IF KSERVICE>LOCSN1 %THEN %START ;! SUSPEND REPLY %IF KSERVICE<=LOCSN2 %THEN I=KSERVICE-LOCSN1 %ELSE %START %IF KSERVICE<=LOCSN3 %THEN I=KSERVICE-LOCSN2 %C %ELSE I=KSERVICE-LOCSN3 %FINISH INHIBIT(I+LOCSN1) INHIBIT(I+LOCSN2) INHIBIT(I+LOCSN3) P_DEST=X'30007' ;! RESCHEDULE LOCAL CONTROLLER P_SRCE=0 P_P1=I SCHEDULE(P) ->KEXIT %FINISH SUPPOFF(KSERV,P) ->SERVROUT(KSERVICE) %FINISH %ELSE %START %IF KSERVICE=KERNELQ %THEN KERNELQ=0 %ELSE %START KSERVQ==SERVA(KERNELQ) KSERVQ_L=KSERV_L %FINISH KSERV_L=0 %FINISH ->KSERVE !----------------------------------------------------------------------- ! SERVICE ROUTINE CALLS SERVROUT(1):SERVROUT(2):->INVALID SERVROUT(3):SCHEDULE(P) ; ->KEXIT SERVROUT(4):PAGETURN(P) ; ->KEXIT SERVROUT(5):GET EPAGE(P) ; ->KEXIT SERVROUT(6):RETURN EPAGE(P) ; ->KEXIT SERVROUT(7):SEMAPHORE(P) ; ->KEXIT SERVROUT(8):ACTIVE MEM(P) ; ->KEXIT SERVROUT(9):! ONLY FOR PARM QUOTES ? TIMEOUT(P) ; ->KEXIT SERVROUT(10):ELAPSEDINT(P) ; ->KEXIT SERVROUT(11):UPDATE TIME ; ->KEXIT SERVROUT(12):DPONPUTONQ(P) ; ->KEXIT SERVROUT(13):TURNONER(P) ; ->KEXIT SERVROUT(14):PROCMON CONTROL(P) ; ->KEXIT SERVROUT(15):SERVROUT(16): SERVROUT(17):SERVROUT(18):SERVROUT(19):SERVROUT(20):SERVROUT(21): SERVROUT(22):SERVROUT(23):SERVROUT(24):SERVROUT(25):SERVROUT(26): SERVROUT(27):SERVROUT(28):SERVROUT(29):SERVROUT(30):SERVROUT(31): ->INVALID SERVROUT(32): !PSERIES; DISC(P) !SSERIES DISC MINDER(P) ->KEXIT SERVROUT(33):PDISC(P) ; ->KEXIT SERVROUT(34):SERVROUT(35):->INVALID SERVROUT(36):SERVROUT(37):MOVE(P) ; ->KEXIT SERVROUT(38):SERVROUT(39):->INVALID SERVROUT(40):DRUM(P) ; ->KEXIT SERVROUT(41): SERVROUT(42):SERVROUT(43):SERVROUT(44):SERVROUT(45):SERVROUT(46): SERVROUT(47):->INVALID SERVROUT(48):GPC(P) ; ->KEXIT SERVROUT(49):TAPE(P) ; ->KEXIT SERVROUT(50):OPER(P) ; ->KEXIT SERVROUT(51):LP ADAPTOR(P) ; ->KEXIT SERVROUT(52):CR ADAPTOR(P) ; ->KEXIT SERVROUT(53):CP ADAPTOR(P) ; ->KEXIT SERVROUT(54):PRINTER(P) ; ->KEXIT SERVROUT(55):SERVROUT(56):COMMS CONTROL(P) ; ->KEXIT SERVROUT(57):MK1FEADAPTOR(P) ; ->KEXIT SERVROUT(58):SERVROUT(59):SERVROUT(60):SERVROUT(61):->INVALID SERVROUT(62):COMREP(P) ; ->KEXIT SERVROUT(63):SERVROUT(64):->INVALID !----------------------------------------------------------------------- KEXIT:%IF KSERV_P<=0 %THEN %START %IF KSERVICE=KERNELQ %THEN KERNELQ=0 %ELSE %START KSERVQ==SERVA(KERNELQ) KSERVQ_L=KSERV_L %FINISH KSERV_L=0 %FINISH ? %IF KSERVICE>LOCSN1 %THEN KSERVICE=3 ;! SCHEDULER KTIMES:! RECORD SERVICE ROUTINE TIMES ? *LSS_(6) ;? *ST_IC ;? *LSS_(5) ;? *ST_IT ? SERVIT(KSERVICE)=SERVIT(KSERVICE)+MAXIT-IT ? SERVIC(KSERVICE)=SERVIC(KSERVICE)+MAXIT-IC ? SERVN(KSERVICE)=SERVN(KSERVICE)+1 ->KSERVE !----------------------------------------------------------------------- INVALID:PRINT STRING("INVALID POFF:") PTREC(P) ->KSERVE !----------------------------------------------------------------------- LSERVE:! LOCAL CONTROLLER SERVICES LSERVQ==SERVA(RUNQ) LSERVICE=LSERVQ_L LSERV==SERVA(LSERVICE) %IF LSERV_P>0 %THEN %START SUPPOFF(LSERV,P) %IF LSERV_P=0 %THEN %START %IF LSERVICE=RUNQ %THEN RUNQ=0 %ELSE %START LSERVQ==SERVA(RUNQ) LSERVQ_L=LSERV_L %FINISH LSERV_L=0 %FINISH %ELSE RUNQ=LSERVICE CURPROC=LSERVICE-LOCSN0 ACTW1=PROCA(CURPROC)_LSTAD ACTW3=0 ;! SSN=0 ? LCN=LCN+1 ? *LSS_(6) ;? *ST_IC ;? *LSS_(5) ;? *ST_IT ? LCIC=LCIC+MAXIT-IC ? LCIT=LCIT+MAXIT-IT *ACT_ACTW0 ;! ACTIVATE TO LOCAL CONTROLLER !----------------------------------------------------------------------- LCCALL:*JLK_%TOS ; LOCAL CONTROL ;! INITIAL CALL !----------------------------------------------------------------------- LCRETURN:*JLK_%TOS ! LOCAL CONTROL RETURNS TO HERE CURPROC=0 %FINISH %ELSE %START %IF LSERVICE=RUNQ %THEN RUNQ=0 %ELSE %START LSERVQ==SERVA(RUNQ) LSERVQ_L=LSERV_L %FINISH LSERV_L=0 %FINISH ->KSERVE !----------------------------------------------------------------------- ! INTERRUPT ENTRY POINTS ! SYSTEM ERROR IST1I:*JLK_%TOS ;! ENTRY POINT IS LINK PC I.E. NEXT INSTR *LSS_%TOS ; *ST_SESTK ; *LSS_%TOS ; *ST_SEIP *LSS_(%LNB+7) ; *ST_SELN ;! OLD LINE NUMBER SYSERR(SESTK,SEIP) ->KSERVE; ! EXCEPT IN S SERIES !!! ! DOES NOT RETURN !----------------------------------------------------------------------- ! EXTERNAL IST2I:*JLK_%TOS ! EXTERNAL INTERRUPTS (CLOCK) ENTER HERE *LSS_%TOS ; *ST_I *LSS_%TOS ; *ST_J %IF IDLE#0 %THEN IDLEIT=IDLEIT+MAXIT-KIT %AND IDLE=0 P_P1=I P_P2=J !PSERIES; I=X'44000100'!COM_SACPORT<<20 ;! CLEAR 2980 SAC EXT. REG. !PSERIES; *LB_I !PSERIES; *LSS_(0+%B) !PSERIES; *ST_J !PSERIES; P_P3=J P_DEST=X'A0000' ELAPSEDINT(P) ? KSERVICE=10 ->KTIMES !----------------------------------------------------------------------- ! MULTIPROCESSOR IST3I:*JLK_%TOS *IDLE_X'F3' !----------------------------------------------------------------------- ! PERIPHERAL IST4I:*JLK_%TOS ! PERIPHERAL INTERRUPTS ENTER HERE *LSS_%TOS ;! OLD STACK *LSS_%TOS ;! PARAMETER = SAC NUMBER<<20 *ST_I %IF IDLE#0 %THEN IDLEIT=IDLEIT+MAXIT-KIT %AND IDLE=0 !SSERIES P_SRCE=0 !SSERIES %IF INTEGER(COM_DCUCONFA)>24 %START !SSERIES OPMESS("INT FROM DCU ".STRINT(I>>24)." ??") !SSERIES ->KSERVE !SSERIES %FINISH !SSERIES P_DEST=X'300003' !SSERIES P_P1=I !SSERIES DCU(P) !SSERIES KSERVICE=58 !SSERIES ->KTIMES PORT=I>>20&3 I=X'44000000'!PORT<<20 ;! IMAGE STORE ADDR FOR TRUNK FLAGS *LB_I *LSS_(0+%B) *ST_I K=0 %CYCLE *LSS_I *SHZ_J *USH_1 *ST_I P_SRCE=0 J=J+K P_P1=PORT<<4!J ->CONROUT(CONTYPE(J)) %IF J<=15 CONROUT(0):! IN CASE OF SPURIOUS BITS ? KSERVICE=1 ->CONTINUE CONROUT(1):P_DEST=X'280003' DRUM(P) ? KSERVICE=42 ->CONTINUE CONROUT(2):P_DEST=X'200003' !PSERIES; DISC(P) ? KSERVICE=34 ->CONTINUE CONROUT(3):P_DEST=X'300003' GPC(P) ? KSERVICE=58 CONTINUE:%IF I=0 %THEN ->KTIMES ? *LSS_(6) ;? *ST_IC ;? *LSS_(5) ;? *ST_IT ? *LSS_X'FFFFFF' ; *ST_(5) ; *ST_(6) ? SERVN(KSERVICE)=SERVN(KSERVICE)+1 ? SERVIT(KSERVICE)=SERVIT(KSERVICE)+MAXIT-IT ? SERVIC(KSERVICE)=SERVIC(KSERVICE)+MAXIT-IC K=J+1 %REPEAT !----------------------------------------------------------------------- ! VIRTUAL STORE INTERRUPT (BEFORE PROCESS CREATED) IST5I:*JLK_%TOS ; *IDLE_X'F5' !----------------------------------------------------------------------- ! INTERVAL TIMER INTERRUPT (BEFORE PROCESS CREATED) IST6I:*JLK_%TOS ; *IDLE_X'F6' !----------------------------------------------------------------------- ! PROGRAM ERROR INTERRUPT (BEFORE PROCESS CREATED) IST7I:*JLK_%TOS ; *IDLE_X'F7' !----------------------------------------------------------------------- ! SYSTEM CALL (BEFORE PROCESS CREATED) IST8I:*JLK_%TOS ; *IDLE_X'F8' !----------------------------------------------------------------------- ! OUT INTERRUPT (BEFORE PROCESS CREATED) IST9I:*JLK_%TOS ; *IDLE_X'F9' !----------------------------------------------------------------------- ! EXTRACODE IST10I:*JLK_%TOS ; *IDLE_X'FA' !----------------------------------------------------------------------- ! EVENT PENDING (BEFORE PROCESS CREATE) IST11I:*JLK_%TOS ; *IDLE_X'FB' !----------------------------------------------------------------------- ! INSTRUCTION COUNTER (BEFORE PROCESS CREATE) IST12I:*JLK_%TOS ; *IDLE_X'FC' !----------------------------------------------------------------------- %ROUTINE SCHEDULE(%RECORDNAME P) ! ACTIVITY 0 : MAXEPAGES TOO BIG ! ACTIVITY 1 : CREATE PROCESS ! ACTIVITY 2 : REPLY FROM CREATE PROCESS ! ACTIVITY 3 : RUN OUT OF EPAGE ALLOCATION FROM LOCAL CONTROLLER ! ACTIVITY 4 : RUN OUT OF TIME SLICES FROM LOCAL CONTROLLER ! ACTIVITY 5 : SUSPEND PROCESS ! ACTIVITY 7 : UNSUSPEND PROCESS ! ACTIVITY 8 : DESTROY PROCESS ! ACTIVITY 9 : REPLY FROM PAGE-IN OF LOCAL CONTROLLER STACK ! ACTIVITY 10: MORE EPAGES ON THE FLY ? ! ACTIVITY 11: MORE TIME ON THE FLY ? ! ACTIVITY 12: MORE OF PARTIAL ALLOCATION REQUEST ! ACTIVITY 13: PROCESS WAITING ON ALLOCATION ! ACTIVITY 14: DEADLOCK RECOVERY %ROUTINESPEC PARE EPAGES %ROUTINESPEC ONPQ %RECORDSPEC P(PARMF) %CONSTBYTEINTEGERARRAY PRAT(0:31)= %C 1,1,2,1,3,1,1,2,1,1,2,1,1,4,1,2,1,1,2,1,1,1,2,1,1,3,1,1,2,1,1,2 %CONSTINTEGER PRATMAX=31 %OWNINTEGER PRATP=0 !----------------------------------------------------------------------- ! PRIORITY QUEUE ARRAY ETC. %OWNBYTEINTEGERARRAY PQ(1:MAXPROCS)=0(MAXPROCS) %OWNBYTEINTEGERARRAY PQH(1:4)=0(4) ;! NUMBER OF PRIORITIES=4 %OWNINTEGER NPQ=0,P4L=0,NPL4=0,PARTPROC,PARTALLOC,ALLOCREST,PARTWAIT=0 ?%OWNINTEGER SUSPN=0 %OWNBYTEINTEGERARRAY PQN(1:4)=0(4) !----------------------------------------------------------------------- ?%CONSTSTRING(2)%ARRAY STRPN(1:4)="P1","P2","P3","P4" %CONSTSTRING(16)%ARRAY STARTMESS(0:2)=" PROCESS CREATED", " : SYSTEM FULL"," : NO AMT" %LONGINTEGERARRAYNAME LST %INTEGER SRCE,ACT,PROCESS,PTY,LSTAD,LSTACKDA,DCODEDA,DSTACKDA, %C DGLADA,XEPS,OLDCATSLOT,NEWCATSLOT,INCAR,PPCELL,I,J,K,L %LONGINTEGER LIM %STRING(15) USER !----------------------------------------------------------------------- %RECORDNAME OLDCAT,NEWCAT(CATTABF) !----------------------------------------------------------------------- %RECORDNAME PROC(PROCF) %RECORDNAME PARMA(PARMAF) %SWITCH ACTIVITY(0:15) ? %IF KMON&1<<3#0 %THEN PRINT STRING("SCHEDULE:") %AND PTREC(P) ACT=P_DEST&X'FFFF' PROCESS=P_P1 %IF 0ACTIVITY(ACT) !----------------------------------------------------------------------- ACTIVITY(0):! INITIALISE I=UNALLOCEPS//2-LSTACKLEN %IF MAXEPAGES>I %THEN %START MAXEPAGES=I %CYCLE I=1,1,13 %IF CATTAB(I)_EPLIM>MAXEPAGES %THEN CATTAB(I)_EPLIM=MAXEPAGES %REPEAT %FINISH MAXP4=UNALLOCEPS//(2*MAXEPAGES) COM_USERS=0 MPLEVEL=0 PAGEFREES=0 %CYCLE I=1,1,MAXPROCS PROCA(I)=0 INHIBIT(I+LOCSN0) INHIBIT(I+LOCSN1) INHIBIT(I+LOCSN2) INHIBIT(I+LOCSN3) %REPEAT ? DISPLAY TEXT(0,2,0,"RUNQ1 RUNQ2 PQ1 PQ2 PQ3 PQ4 SUSP") ? DISPLAY TEXT(0,3,0," 0 0 0 0 0 0 0") %RETURN !----------------------------------------------------------------------- ACTIVITY(1):! CREATE PROCESS ! P_P1/P2 : STRING(USER NAME) ! P_P3 : LOCAL CONTROLLER STACK DISC ADDRESS ! P_P4 : DIRECTOR CODE DISC ADDRESS (<=0 FOR DEFAULT) ! P_P5 : DIRECTOR STACK DISC ADDRESS ! P_P6 : DIRECTOR GLA DISC ADDRESS SRCE=P_SRCE USER=STRING(ADDR(P_P1)) INCAR=BYTE INTEGER(ADDR(P_P2)+3) %IF COM_USERS=MAXPROCS %THEN P_P1=1 %AND ->STARTREP ;! SYSTEM FULL PROCESS=0 %IF USER="DIRECT" %THEN PROCESS=1 %IF USER="SPOOLR" %THEN PROCESS=3 %IF USER="VOLUMS" %THEN PROCESS=2 %IF PROCESS>0 %START PROC==PROCA(PROCESS) %IF PROC_USER#"" %THEN P_P1=3 %AND ->STARTREP %FINISH %ELSE %START %CYCLE PROCESS=4,1,MAXPROCS PROC==PROCA(PROCESS) %IF PROC_USER="" %THEN %EXIT %REPEAT %FINISH LSTACKDA=P_P3 %IF P_P4<=0 %THEN DCODEDA=COM_DCODEDA %ELSE DCODEDA=P_P4 DSTACKDA=P_P5 DGLADA=P_P6 P_DEST=X'80001' ;! GET AMTX FOR LOCAL CONTROLLER STACK P_SRCE=0 P_P1=0 P_P2=LSTACKDA P_P3=X'FFFF0000'!(LSTACKLEN-1) ;! "NEW" EPAGES ACTIVE MEM(P) %IF P_P2<=0 %THEN P_P1=2 %AND ->STARTREP ;! NO AMT PROC_LAMTX=P_P2 COM_USERS=COM_USERS+1 PROC_USER=USER UPDISP(PROCESS,4,USER) PROC_INCAR=INCAR PROC_ACTIVE=255 PROC_CATEGORY=0 CLEAR PARMS(PROCESS+LOCSN0) CLEAR PARMS(PROCESS+LOCSN1) CLEAR PARMS(PROCESS+LOCSN2) CLEAR PARMS(PROCESS+LOCSN3) ! PON TO INITIALIZE LOCAL CONTROLLER P_DEST=(PROCESS+LOCSN0)<<16 P_SRCE=X'30002' P_P1=PROCESS P_P2=DCODEDA P_P3=DGLADA P_P4=DSTACKDA PON(P) ;! INHIBITED AS YET THOUGH ! REPLY TO START-UP P_P1=0 ;! PROCESS CREATED SUCCESSFULLY P_P2=(PROCESS+LOCSN1)<<16 P_P3=(PROCESS+LOCSN2)<<16 P_P4=(PROCESS+LOCSN3)<<16!1 ;! ASYNCH SNO FOR INPUT CONTROL MESS P_P5=PROCESS STARTREP:%IF SRCE<=0 %THEN OPMESS(USER.STARTMESS(P_P1)) %C %ELSE P_DEST=SRCE %AND P_SRCE=X'30001' %AND PON(P) %IF P_P1=0 %THEN OLDCAT==CATTAB(0) %AND ONPQ %AND ->LOAD %RETURN !----------------------------------------------------------------------- ACTIVITY(2):! REPLY FROM CREATE PROCESS PROC_CATEGORY=1 ;! INITIAL CATEGORY ->OLDC !----------------------------------------------------------------------- ACTIVITY(3):! OUT OF EPAGES NEWCATSLOT=OLDCAT_MOREP PROC_CATEGORY=NEWCATSLOT ->OLDC !----------------------------------------------------------------------- ACTIVITY(10):! MORE EPAGES ON THE FLY ? %UNLESS PARTPROC=NPQ=0 %THEN P_P1=0 %AND %RETURN ;! NO NEWCATSLOT=OLDCAT_MOREP NEWCAT==CATTAB(NEWCATSLOT) XEPS=NEWCAT_EPLIM-OLDCAT_EPLIM %UNLESS XEPS>0 %AND UNALLOCEPS>=XEPS %THEN P_P1=0 %AND %RETURN UNALLOCEPS=UNALLOCEPS-XEPS PROC_CATEGORY=NEWCATSLOT CONT:P_P1=NEWCAT_EPLIM P_P2=NEWCAT_RTLIM %IF OLDCAT_PRIORITY=4 %THEN P4L=P4L-1 %IF NEWCAT_PRIORITY=4 %THEN P4L=P4L+1 %RETURN !----------------------------------------------------------------------- ACTIVITY(4):! OUT OF TIME NEWCATSLOT=OLDCAT_MORET PARE EPAGES ->OLDC !----------------------------------------------------------------------- ACTIVITY(11):! MORE TIME (AND AT LEAST PRESENT NO OF EPAGES) ON THE FLY? %UNLESS PARTPROC=NPQ=0 %THEN P_P1=0 %AND %RETURN NEWCATSLOT=OLDCAT_MORET PARE EPAGES %IF PROCESS=PARTPROC %THEN %START %IF PARTALLOC>=NEWCAT_EPLIM %THEN %START ;! NEW ALLOC ALREADY UNALLOCEPS=UNALLOCEPS+PARTALLOC-NEWCAT_EPLIM PARTPROC=0 P_P3=0 %FINISH %ELSE %START ALLOCREST=ALLOCREST-OLDCAT_EPLIM+NEWCAT_EPLIM P_P3=1 ;! STILL PARTIAL ALLOCATION %FINISH %FINISH %ELSE %START UNALLOCEPS=UNALLOCEPS+OLDCAT_EPLIM-NEWCAT_EPLIM P_P3=0 %FINISH ->CONT !----------------------------------------------------------------------- ACTIVITY(5):! SUSPEND ? SUSPN=SUSPN+1 UNINHIBIT(P_SRCE) ;! SERVICE AWAITED UNINHIBIT(PROCESS+LOCSN3) %UNLESS P_SRCE>LOCSN3 ? UPDISP(PROCESS,11,"S ") PROC_ACTIVE=0 NEWCATSLOT=OLDCAT_SUSP PARE EPAGES %IF NEWCAT_PRIORITY<4 %AND PROCESS>3 %THEN NPL4=NPL4+1 ->OLDC !----------------------------------------------------------------------- ACTIVITY(7):! UNSUSPEND ? SUSPN=SUSPN-1 PROC_ACTIVE=255 %IF OLDCAT_PRIORITY<4 %AND PROCESS>3 %THEN NPL4=NPL4-1 ONPQ ->LOAD !----------------------------------------------------------------------- ACTIVITY(8):! DESTROY PROCESS MPLEVEL=MPLEVEL-1 DESTROY:UPDISP(PROCESS,4," ") COM_USERS=COM_USERS-1 INHIBIT(PROCESS+LOCSN0) INHIBIT(PROCESS+LOCSN1) INHIBIT(PROCESS+LOCSN2) INHIBIT(PROCESS+LOCSN3) %IF OLDCAT_PRIORITY=4 %THEN P4L=P4L-1 %CYCLE I=0,1,LSTACKLEN-1 P_DEST=X'40002' ;! PAGE-TURN OUT P_P1=PROC_LAMTX<<16!I P_P2=0 ;! REGARD AS NOT WRITTEN TO PAGETURN(P) %REPEAT P_DEST=X'80002' ;! RETURN AMTX FOR LOCAL CONTROLLER STACK P_SRCE=0 P_P1=0 ;! ID NOT USED P_P2=PROC_LAMTX ACTIVE MEM(P) PROC=0 ->CPL !----------------------------------------------------------------------- OLDC:! UPDATE UNALLOCEPS FOR REMOVAL OF PROCESS FROM STORE MPLEVEL=MPLEVEL-1 DEAD:%IF OLDCAT_PRIORITY=4 %THEN P4L=P4L-1 ! PAGE OUT LOCAL CONTROLLER STACK PROC_RUNQ=0 %CYCLE I=0,1,LSTACKLEN-1 P_DEST=X'40002' ;! PAGETURN/PAGE-OUT P_P1=PROC_LAMTX<<16!I %IF I>=LSTACKLENP %THEN P_P2=2 %ELSE P_P2=X'C' ! MAKE "NEW" IF NON-PAGED PART PAGETURN(P) ;! NO REPLIES %REPEAT %UNLESS ACT=5 %THEN ONPQ !----------------------------------------------------------------------- CPL:! DEAL WITH PARTIAL ALLOCATIONS FIRST %IF PROCESS=PARTPROC %THEN %START PARTPROC=0 UNALLOCEPS=UNALLOCEPS+PARTALLOC+LSTACKLEN %FINISH %ELSE UNALLOCEPS=UNALLOCEPS+OLDCAT_EPLIM+LSTACKLEN LOAD:%IF PARTPROC#0 %THEN %START %IF UNALLOCEPS<=0 %THEN %RETURN %IF ALLOCREST<=UNALLOCEPS %THEN I=ALLOCREST %ELSE I=UNALLOCEPS PARTALLOC=PARTALLOC+I ALLOCREST=ALLOCREST-I UNALLOCEPS=UNALLOCEPS-I %IF PARTWAIT#0 %THEN %START ;! PROCESS ALREADY WAITING P_DEST=(PARTPROC+LOCSN0)<<16!7 P_P1=PARTALLOC %IF ALLOCREST=0 %THEN P_P2=0 %ELSE P_P2=1 PON(P) MPLEVEL=MPLEVEL+1 PARTWAIT=0 %FINISH %IF ALLOCREST=0 %THEN PARTPROC=0 %FINISH !----------------------------------------------------------------------- %CYCLE ;! LOAD AS MANY AS POSSIBLE %IF NPQ=0 %OR UNALLOCEPSNPTY ! LOAD ONLY MAXP4 PRIORITY 4 PROCESS UNLESS NOTHING ELSE %IF PTY=4 %THEN %START %IF P4L>=MAXP4 %THEN %START %IF PQN(4)#NPQ %THEN ->NPTY %IF NPL4>0 %THEN %RETURN %FINISH P4L=P4L+1 %FINISH PROCESS=PQ(PQH(PTY)) PROC==PROCA(PROCESS) UNALLOCEPS=UNALLOCEPS-LSTACKLEN %IF PROCESS=PQH(PTY) %THEN PQH(PTY)=0 %C %ELSE PQ(PQH(PTY))=PQ(PROCESS) NPQ=NPQ-1 PQN(PTY)=PQN(PTY)-1 ! PAGE IN LOCAL CONTROLLER STACK P_DEST=X'40001' ;! PAGETURN/PAGE-IN P_SRCE=X'30009' P_P1=PROC_LAMTX<<16 PPCELL=NEWPPCELL P_P2=PPCELL<<16!PROCESS<<8 PARM(PPCELL)_P6=0 ;! READ FAIL FLAG %CYCLE I=0,1,LSTACKLEN-1 PON(P) P_P1=P_P1+1 P_P2=P_P2+1 %REPEAT PQ(PROCESS)=LSTACKLEN ;! TO COUNT PAGE-TURN REPLIES I=CATTAB(PROC_CATEGORY)_EPLIM %IF I<=UNALLOCEPS %THEN UNALLOCEPS=UNALLOCEPS-I %ELSE %START PARTALLOC=UNALLOCEPS UNALLOCEPS=0 ALLOCREST=I-PARTALLOC PARTPROC=PROCESS PARTWAIT=0 %RETURN %FINISH %REPEAT !----------------------------------------------------------------------- ACTIVITY(12):! MORE OF PARTIAL ALLOCATION REQUEST %IF PROCESS=PARTPROC %THEN P_P1=PARTALLOC %AND P_P2=1 %ELSE %C P_P1=OLDCAT_EPLIM %AND P_P2=0 %RETURN !----------------------------------------------------------------------- ACTIVITY(13):! NOW WAITING FOR ALLOCATION MPLEVEL=MPLEVEL-1 %IF GETEPN=MPLEVEL %THEN P_P1=1 %ELSE P_P1=0 %AND PARTWAIT=1 %RETURN !----------------------------------------------------------------------- ACTIVITY(14):! DEADLOCK RECOVERY ->DEAD !----------------------------------------------------------------------- ACTIVITY(9):! REPLY FROM PAGE-IN LOCAL CONTROLLER STACK PPCELL=P_P1>>16 PARMA==RECORD(ADDR(PARM(PPCELL))) I=P_P1&X'FF' ;! EPAGE NO PARMA_P(I)=P_P2 ;! SAVE REAL ADDRESS %IF P_P3#0 %THEN PARMA_P(7)=1 ;! FAIL FLAG PROCESS=P_P1>>8&X'FF' PQ(PROCESS)=PQ(PROCESS)-1 %RETURN %UNLESS PQ(PROCESS)=0 ;! WAIT UNTIL ALL PAGES HERE PROC==PROCA(PROCESS) OLDCATSLOT=PROC_CATEGORY OLDCAT==CATTAB(OLDCATSLOT) %IF PARMA_P(7)#0 %THEN %START ! READ FAIL - TRY TO PAGE IT OUT AND TRY AGAIN PRINT STRING("LOCAL CONTROLLER STACK READ FAIL, PROCESS ".%C STRINT(PROCESS)) %IF PARTPROC=PROCESS %THEN PARTPROC=0 ->DESTROY %FINISH LSTAD=PARMA_P(0) PROC_LSTAD=LSTAD LST==ARRAY(VIRTAD!LSTAD,LSTF) LIM=LSTACKLEN*EPAGESIZE-1 K=LSTAD+LSTLEN*8+X'50' LST(0)=X'4150038080000001'!LIM<<42!K ! FILL IN PAGE TABLE ENTRIES K=VIRTAD!K %CYCLE I=0,1,LSTACKLEN-1 L=X'80000001'!PARMA_P(I) %CYCLE J=0,1,EPAGESIZE-1 INTEGER(K+J<<2)=L+J<<10 %REPEAT K=K+EPAGESIZE<<2 %REPEAT RETURN PPCELL(PPCELL) LST(1)=X'00F0000080000001'!DIRACR<<56!(LSTAD+LSTLEN*8) PROC_RUNQ=OLDCAT_RQTS1 ? UPDISP(PROCESS,11,"R".TOSTRING(PROC_RUNQ+'0')) MPLEVEL=MPLEVEL+1 %IF OLDCATSLOT=0 %THEN %START ;! PROCESS BEING CREATED ! ALL LST ENTRIES FROM 2 ZERO ALREADY I=VIRTAD!LST(1)&X'0FFFFFF8' RECORD(I)<-LSSNP1I ;! COPY LOCAL CONTROLLER CONTEXT IN INTEGER(I+LSTKN*X'80'+X'64')=LNBP5 ;! DISPLAY PTR UNINHIBIT(PROCESS+LOCSN0) ;! LET CREATE PON GO %FINISH %ELSE %START P_DEST=(PROCESS+LOCSN0)<<16!1 P_SRCE=X'30000' %IF PARTPROC=PROCESS %THEN P_P1=PARTALLOC %AND P_P3=1 %ELSE %C P_P1=OLDCAT_EPLIM %AND P_P3=0 P_P2=OLDCAT_RTLIM PON(P) %FINISH %RETURN !----------------------------------------------------------------------- ACTIVITY(15):! UPDATE OPER INFO ?%BEGIN ?%INTEGERARRAY RUNQ(0:2) ? %CYCLE I=0,1,2 ? RUNQ(I)=0 ? %REPEAT ? %CYCLE I=1,1,MAXPROCS ? PROC==PROCA(I) ? %IF PROC_USER#"" %THEN RUNQ(PROC_RUNQ)=RUNQ(PROC_RUNQ)+1 ? %REPEAT ? %CYCLE I=1,1,2 ? DISPLAY TEXT(0,3,I*6-4,STRINT(RUNQ(I))." ") ? %REPEAT ? %CYCLE I=1,1,4 ? DISPLAY TEXT(0,3,I*4+10,STRINT(PQN(I))." ") ? %REPEAT ? DISPLAY TEXT(0,3,31,STRINT(SUSPN)." ") ?%END ? %RETURN !----------------------------------------------------------------------- %ROUTINE PARE EPAGES %CONSTINTEGER LEEWAY=2 %CYCLE NEWCAT==CATTAB(NEWCATSLOT) %IF NEWCAT_LESSP=0 %OR P_P2+LEEWAY>CATTAB(NEWCAT_LESSP)_EPLIM %C %THEN PROC_CATEGORY=NEWCATSLOT %AND %RETURN NEWCATSLOT=NEWCAT_LESSP %REPEAT %END %ROUTINE ONPQ PTY=CATTAB(PROC_CATEGORY)_PRIORITY %IF PQH(PTY)=0 %THEN PQ(PROCESS)=PROCESS %ELSE %C PQ(PROCESS)=PQ(PQH(PTY)) %AND PQ(PQH(PTY))=PROCESS ! IF PROCESS HOLDING A SEMA PUT ON FRONT OF PRIORITY Q PQH(PTY)=PROCESS %UNLESS PROC_STATUS&1#0 %AND PQH(PTY)#0 NPQ=NPQ+1 ;! COUNT PROCESSES QUEUED PQN(PTY)=PQN(PTY)+1 ? UPDISP(PROCESS,11,STRPN(PTY)) %END %END !----------------------------------------------------------------------- %ROUTINE PAGETURN(%RECORDNAME P) %RECORDSPEC P(PARMF) ! ALL ACTS : P_P1=AMTX<<16!EPX ! ACTIVITY 1 : "PAGE IN" REQUEST FROM LOCAL ! : P_P2=IDENTIFIER ! ACTIVITY 2 : "PAGE OUT" REQUEST FROM LOCAL ! : P_P2=FLAGS ! ACTIVITY 3 : REPLY FROM "EPAGE" ! : P_P2=STOREX ! ACTIVITY 4 : REPLY FROM DISC/READ ! ACTIVITY 5 : REPLY FROM DISC/WRITE ! ACTIVITY 6 : REPLY FROM DRUM/READ ! ACTIVITY 7 : REPLY FROM DRUM/WRITE %ROUTINESPEC PUSHPIT %INTEGER AEX,AMTX,EPX,DDX,DTX,FLAGS,STOREX,SRCE,CALL,ID,%C I,J %RECORDNAME AMT(AMTF) %RECORDNAME ST(STOREF) %SWITCH ACTIVITY(1:7) ? %IF KMON&1<<4#0 %THEN PRINT STRING("PAGETURN:") %AND PTREC(P) AEX=P_P1 AMTX=AEX>>16 EPX=AEX&X'FFFF' AMT==AMTA(AMTX) DDX=AMT_DDP+EPX ->ACTIVITY(P_DEST&X'FFFF') !----------------------------------------------------------------------- ACTIVITY(1):! PAGE-IN (ALLOWS FOR PAGETURN TO BE "CALLED") ? PTURNN=PTURNN+1 I=AMTDD(DDX) %IF I&DTXBIT=0 %THEN DTX=-1 %AND STOREX=I&STXMASK %ELSE %C DTX=I&STXMASK %AND STOREX=DRUMT(DTX) AMT_USERS=AMT_USERS+1 CALL=P_SRCE SRCE=CALL&X'7FFFFFFF' ID=P_P2 %IF STOREX#STXMASK %THEN %START ;! EPAGE ALLOCATED HERE:ST==STORE(STOREX) %IF ST_FLAGS=1 %THEN %START ;! RECAPTURE ST_FLAGS=0 ST_USERS=0 ST_LINK=0 %UNLESS ST_BLINK=0 %THEN STORE(ST_BLINK)_FLINK=ST_FLINK %C %ELSE FSTASL=ST_FLINK %UNLESS ST_FLINK=0 %THEN STORE(ST_FLINK)_BLINK=ST_BLINK %C %ELSE BSTASL=ST_BLINK FREEEPAGES=FREEEPAGES-1 %IF FREEEPAGES=0 %THEN INHIBIT(5) ? RECAPN=RECAPN+1 %FINISH %ELSE %START ? PSHAREN=PSHAREN+1 %IF ST_USERS=0 %THEN PAGEFREES=PAGEFREES-1 ;! PAGE-OUT IN PROGRESS %FINISH ! STORE FLAGS : ! BIT 0 : DISC TRANSFER IN PROGRESS(1)/NOT IN PROGRESS(0) ! BIT 1 : DISC INPUT(0)/OUTPUT(1) ! BIT 2 : DRUM TRANSFER IN PROGRESS(1)/NOT IN PROGRESS(0) ! BIT 3 : DRUM INPUT(0)/OUTPUT(1) ! BIT 4 : WRITTEN TO MARKER ! BIT 5 : TYPE (0:DISC ONLY, 1:DISC & DRUM) ! BIT 6 : MAKE NEW ! BIT 7 : RECAPTURABLE ST_USERS=ST_USERS+1 %IF ST_USERS>1 %THEN UNALLOCEPS=UNALLOCEPS+1 ! EPAGE ASSUMED TO BE EITHER IN STORE OR IN TRANSIT ! IF ->STORE TRANSIT, SAVE IN PAGE-IN-TRANSIT TABLE %IF ST_FLAGS&X'C0'=X'80' %OR ST_FLAGS&X'30'=X'20' %THEN %C PUSHPIT %AND P_DEST=0 %ELSE %START ! INTACT COPY IN STORE (EVEN IF STORE-> TRANSIT), SO REPLY NOW P_P1=ID ;! IDENTIFIER P_P2=STORE(STOREX)_REALAD P_P3=0 ;! SUCCESS %IF CALL>0 %THEN P_DEST=SRCE %AND P_SRCE=X'40001' %AND PON(P) %FINISH %RETURN %FINISH ! ALLOCATE EPAGE P_DEST=X'50000' ;! GET EPAGE P_SRCE=X'80040003' ! AEX INTACT IN P1 %IF AMTDD(DDX)&NEWEPBIT#0 %THEN P_P2=0 %ELSE P_P2=1 ;! CLEAR IF NEW P_P5=SRCE P_P6=ID ? *LSS_(6) ;? *ST_IC ;? *LSS_(5) ;? *ST_IT GET EPAGE(P) ? *LSS_(5) ;? *ST_ITT ;? *LSS_(6) ;? *ST_ICC ? GETIT=GETIT+IT-ITT ;? PTIT=PTIT-IT+ITT ? GETIC=GETIC+IC-ICC ;? PTIC=PTIC-IC+ICC ? GETCALLN=GETCALLN+1 %IF P_DEST#0 %THEN ->ACT3 %ELSE %RETURN !----------------------------------------------------------------------- ACTIVITY(3):! REPLY FROM GET EPAGE I=AMTDD(DDX) %IF I&DTXBIT=0 %THEN DTX=-1 %AND STOREX=I&STXMASK %ELSE %C DTX=I&STXMASK %AND STOREX=DRUMT(DTX) CALL=1 ;! I.E. >0 SRCE=P_P5 ID=P_P6 ! IN CASE 2ND PAGE-IN REQUEST BEFORE GET EPAGE REPLY %IF STOREX#STXMASK %THEN %START %IF P_P2#0 %THEN RETURN EPAGE(P) ->HERE %FINISH %IF P_P2=0 %THEN P_DEST=SRCE!1 %AND P_P3=-1 %AND PON(P) %AND %C AMT_USERS=AMT_USERS-1 %AND %RETURN ACT3:STOREX=P_P2 ST==STORE(STOREX) ST_USERS=1 ST_LINK=0 %IF AMTDD(DDX)&NEWEPBIT#0 %THEN %START ;! NEW EPAGE AMTDD(DDX)=STOREX ;! NOT "NEW" & NOT DRUM ST_FLAGS=8 ;! "WRITTEN" P_P1=ID P_P2=STORE(STOREX)_REALAD P_P3=0 ;! SUCCESS %IF CALL>0 %THEN P_DEST=SRCE %AND P_SRCE=X'40001' %AND PON(P) %FINISH %ELSE %START PUSHPIT %IF DTX<0 %THEN %START ;! NOT ON DRUM DRUMRF:AMTDD(DDX)=STOREX ST_FLAGS=X'80' ;! DISC->STORE TRANSIT P_DEST=X'210005' ;! DIRECT REPLIES TO LC P_SRCE=0 P_P1=AEX P_P2=AMT_DA+EPX ;! DISC ADDRESS P_P3=STOREX ? *LSS_(6) ;? *ST_IC ;? *LSS_(5) ;? *ST_IT PDISC(P) ? *LSS_(5) ;? *ST_ITT ;? *LSS_(6) ;? *ST_ICC ? PDISCIT=PDISCIT+IT-ITT ;? PTIT=PTIT-IT+ITT ? PDISCIC=PDISCIC+IC-ICC ;? PTIC=PTIC-IC+ICC ? PDISCCALLN=PDISCCALLN+1 %FINISH %ELSE %START ;! ON DRUM DRUMT(DTX)=STOREX ST_FLAGS=X'20' ;! DRUM->STORE TRANSIT P_DEST=X'280001' P_SRCE=X'80040006' ! AEX INTACT IN P1 P_P2=DTX P_P3=STOREX ? *LSS_(6) ;? *ST_IC ;? *LSS_(5) ;? *ST_IT DRUM(P) ? *LSS_(5) ;? *ST_ITT ;? *LSS_(6) ;? *ST_ICC ? DRUMIT=DRUMIT+IT-ITT ;? PTIT=PTIT-IT+ITT ? DRUMIC=DRUMIC+IC-ICC ;? PTIC=PTIC-IC+ICC ? DRUMCALLN=DRUMCALLN+1 %FINISH P_DEST=0 %FINISH %RETURN !----------------------------------------------------------------------- ACTIVITY(6):! REPLY FROM DRUM/READ ON FAILURE ONLY DTX=AMTDD(DDX)&STXMASK STOREX=DRUMT(DTX) ST==STORE(STOREX) DRUMT(DTX)=DRUMTASL ;! RETURN DRUM PAGE DRUMTASL=DTX ? DRUMALLOC=DRUMALLOC-1 ->DRUMRF !----------------------------------------------------------------------- ACTIVITY(2):! PAGE-OUT I=AMTDD(DDX) %IF I&DTXBIT=0 %THEN DTX=-1 %AND STOREX=I&STXMASK %ELSE %C DTX=I&STXMASK %AND STOREX=DRUMT(DTX) ST==STORE(STOREX) AMT_USERS=AMT_USERS-1 ST_FLAGS=ST_FLAGS!P_P2 ;! INSERT WRITTEN ETC. MARKERS ST_USERS=ST_USERS-1 %IF ST_USERS>0 %THEN UNALLOCEPS=UNALLOCEPS-1 %AND %RETURN PAGEFREES=PAGEFREES+1 ;! PAGE ABOUT TO BECOME FREE %IF ST_FLAGS&X'A0'#0 %THEN %RETURN PAGEOUT:FLAGS=0 %IF ST_FLAGS&X'08'#0 %THEN %START ! WRITE TO DISC IF PAGE WRITTEN TO ST_FLAGS=ST_FLAGS!X'C0' ;! DISC TRANSFER OUT BITS FLAGS=1 ;! TRANSFER INITIATED AMT_OUTS=AMT_OUTS+1 ;! AVOIDS DRUM SPACE BEING DEALLOCATED P_DEST=X'210002' ;! STORE->DISC P_SRCE=X'80040005' P_P1=AEX P_P2=AMT_DA+EPX ;! DISC ADDR P_P3=ST_REALAD!VIRTAD ? *LSS_(6) ;? *ST_IC ;? *LSS_(5) ;? *ST_IT PDISC(P) ? *LSS_(5) ;? *ST_ITT ;? *LSS_(6) ;? *ST_ICC ? PDISCIT=PDISCIT+IT-ITT ;? PTIT=PTIT-IT+ITT ? PDISCIC=PDISCIC+IC-ICC ;? PTIC=PTIC-IC+ICC ? PDISCCALLN=PDISCCALLN+1 %FINISH %IF ST_FLAGS&4=0 %THEN %START ;! NO DRUM UPDATE %IF DTX>=0 %THEN %START ;! RETURN DRUM PAGE AMTDD(DDX)=STOREX DRUMT(DTX)=DRUMTASL DRUMTASL=DTX ? DRUMALLOC=DRUMALLOC-1 DTX=-1 %FINISH ->NODRUM %FINISH %IF DTX<0 %THEN %START ;! NOT ON DRUM YET %IF DRUMTASL=DTEND %THEN ->NODRUM %ELSE %START DTX=DRUMTASL ;! GET DRUM PAGE DRUMTASL=DRUMT(DRUMTASL) ? DRUMALLOC=DRUMALLOC+1 AMTDD(DDX)=DTXBIT!DTX DRUMT(DTX)=STOREX ->DRUMUP %FINISH %FINISH %IF ST_FLAGS&8#0 %THEN %START ;! PAGE WRITTEN TO DRUMUP:ST_FLAGS=ST_FLAGS!X'30' ;! DRUM TRANSFER OUT BITS FLAGS=1 ;! TRANSFER INITIATED AMT_OUTS=AMT_OUTS+1 ;! AVOIDS AMT SPACE GOING P_DEST=X'280002' ;! DRUM WRITE P_SRCE=X'80040007' P_P1=AEX P_P2=DTX P_P3=STOREX P_P4=ADDR(AMT_OUTS) ? *LSS_(6) ;? *ST_IC ;? *LSS_(5) ;? *ST_IT DRUM(P) ? *LSS_(5) ;? *ST_ITT ;? *LSS_(6) ;? *ST_ICC ? DRUMIT=DRUMIT+IT-ITT ;? PTIT=PTIT-IT+ITT ? DRUMIC=DRUMIC+IC-ICC ;? PTIC=PTIC-IC+ICC ? DRUMCALLN=DRUMCALLN+1 %FINISH NODRUM:%IF FLAGS=0 %THEN %START ;! NO TRANSFERS INITIATED %IF DTX<0 %THEN %START %IF ST_FLAGS&2#0 %THEN AMTDD(DDX)=NEWEPBIT!STXMASK %C %AND ST_FLAGS=0 %ELSE ST_LINK=DDX %AND ST_FLAGS=1 %FINISH %ELSE ST_LINK=DDBIT!DTX %AND ST_FLAGS=1 P_P2=STOREX RETURN EPAGE(P) PAGEFREES=PAGEFREES-1 %IF AMT_USERS=0 %AND AMT_OUTS=0 %THEN %START P_DEST=3 P_P2=AMTX ? *LSS_(6) ;? *ST_IC ;? *LSS_(5) ;? *ST_IT ACTIVE MEM(P) ? *LSS_(5) ;? *ST_ITT ;? *LSS_(6) ;? *ST_ICC ? AMIT=AMIT+IT-ITT ;? PTIT=PTIT-IT+ITT ? AMIC=AMIC+IC-ICC ;? PTIC=PTIC-IC+ICC ? AMCALLN=AMCALLN+1 %FINISH %FINISH %ELSE ST_FLAGS=ST_FLAGS&X'F0' ;! REMOVE OLD BITS %RETURN ;! ->RETURN !----------------------------------------------------------------------- ACTIVITY(5):! REPLY FROM DISC/WRITE I=AMTDD(DDX) %IF I&DTXBIT=0 %THEN DTX=-1 %AND STOREX=I&STXMASK %ELSE %C DTX=I&STXMASK %AND STOREX=DRUMT(DTX) ST==STORE(STOREX) ! DISC WRITE FAILURE ??? ST_FLAGS=ST_FLAGS&X'3F' ;! NO DISC TRANSFER AMT_OUTS=AMT_OUTS-1 %IF ST_FLAGS&X'A0'#0 %OR ST_USERS#0 %THEN %RETURN %IF ST_FLAGS#0 %THEN ->PAGEOUT REP:%IF DTX<0 %THEN ST_LINK=DDX %ELSE ST_LINK=DDBIT!DTX ST_FLAGS=1 P_P2=STOREX RETURN EPAGE(P) PAGEFREES=PAGEFREES-1 %IF AMT_USERS=0 %AND AMT_OUTS=0 %THEN %START P_DEST=3 P_P2=AMTX ? *LSS_(6) ;? *ST_IC ;? *LSS_(5) ;? *ST_IT ACTIVE MEM(P) ? *LSS_(5) ;? *ST_ITT ;? *LSS_(6) ;? *ST_ICC ? AMIT=AMIT+IT-ITT ;? PTIT=PTIT-IT+ITT ? AMIC=AMIC+IC-ICC ;? PTIC=PTIC-IC+ICC ? AMCALLN=AMCALLN+1 %FINISH %RETURN !----------------------------------------------------------------------- ACTIVITY(7):! REPLY FROM DRUM/WRITE DTX=AMTDD(DDX)&STXMASK STOREX=DRUMT(DTX) ST==STORE(STOREX) %IF P_P2<0 %THEN %START ;! WRITE FAILURE AMTDD(DDX)=STOREX ;! RETURN DRUM PAGE DRUMT(DTX)=DRUMTASL DRUMTASL=DTX ? DRUMALLOC=DRUMALLOC-1 DTX=-1 %FINISH ! NEXT 2 LINES NOW DONE IN DRUM ROUTINE !ST_FLAGS=ST_FLAGS&X'CF' ;! NO DRUM TRANSFER !AMT_OUTS=AMT_OUTS-1 %IF ST_FLAGS&X'A0'#0 %OR ST_USERS#0 %THEN %RETURN %IF ST_FLAGS#0 %THEN ->PAGEOUT ->REP ;! RETURN EPAGE !----------------------------------------------------------------------- %ROUTINE PUSHPIT %RECORDNAME PP(PARMXF) %INTEGER I I=NEWPPCELL PP==PARM(I) PP_DEST=SRCE PP_SRCE=X'40001' PP_P1=ID PP_P2=STORE(STOREX)_REALAD PP_P3=0 ;! SUCCESS FLAG PP_LINK=ST_LINK ST_LINK=I %END !----------------------------------------------------------------------- %END !---------------------------------------------------------------------- %ROUTINE GET EPAGE(%RECORDNAME P) %RECORDSPEC P(PARMF) %RECORDNAME STOREP(STOREF) %INTEGER STOREX,PS,I,STAD ! *INCT_STASLSEMA ! *JCC_8, ! SEMALOOP(STASLSEMA) !SEMACL: %IF FREEEPAGES=0 %THEN %START P_SRCE=P_SRCE&X'7FFFFFFF' PON(P) PS=P_SRCE %IF PS=X'40003' %THEN PS=P_P5 %IF LOCSN0>16<=LOCSN1 %THEN GETEPN=GETEPN+1 %IF PAGEFREES=0 %AND MPLEVEL=GETEPN %THEN DEADLOCK P_DEST=0 %RETURN %FINISH ? %IF KMON&1<<5#0 %THEN PRINT STRING("GETEPAGE:") %AND PTREC(P) STOREX=FSTASL STOREP==STORE(STOREX) FSTASL=STORE(FSTASL)_FLINK %IF FSTASL=0 %THEN BSTASL=0 %ELSE STORE(FSTASL)_BLINK=0 %IF STOREP_FLAGS=1 %THEN %START ;! RECAPTURABLE FLAG I=STOREP_LINK %IF I&DDBIT=0 %THEN AMTDD(I)=AMTDD(I)!STXMASK %ELSE %C I=I&(\DDBIT) %AND DRUMT(I)=STXMASK STOREP_FLAGS=0 %FINISH STAD=VIRTAD!STOREP_REALAD %IF P_P2=0 %AND STOREX#0 %THEN %START ;! CLEAR TO ZERO I=X'58000000'!EPAGESIZE<<10 *LDTB_I *LDA_STAD *MVL_%L=%DR,0,0 %FINISH P_P2=STOREX ;! LEAVE P1 & P3 & P5 & P6 INTACT P_P4=STAD %IF P_SRCE>0 %THEN %START P_DEST=P_SRCE P_SRCE=X'50000' PON(P) PS=P_DEST %IF PS=X'40003' %THEN PS=P_P5 %IF LOCSN0>16<=LOCSN1 %THEN GETEPN=GETEPN-1 %FINISH FREEEPAGES=FREEEPAGES-1 %IF FREEEPAGES=0 %THEN %START INHIBIT(5) %IF PAGEFREES=0 %AND MPLEVEL=GETEPN %THEN DEADLOCK %FINISH !RETURN:STASLSEMA=-1 %END !----------------------------------------------------------------------- %INTEGERFN NEW EPAGE %RECORD P(PARMF) %INTEGER I %IF FREEEPAGES=0 %THEN %RESULT=-1 P_DEST=X'50000' P_SRCE=0 P_P2=0 ;! CLEAR TO ZERO GET EPAGE(P) %RESULT=STORE(P_P2)_REALAD %END !----------------------------------------------------------------------- %ROUTINE RETURN EPAGE(%RECORDNAME P) %RECORDSPEC P(PARMF) %RECORDNAME STOREP(STOREF) %INTEGER STOREX ! *INCT_STASLSEMA ! *JCC_8, ! SEMALOOP(STASLSEMA) !SEMACL: ? %IF KMON&1<<6#0 %THEN PRINT STRING("RETURNEPAGE:") %AND PTREC(P) STOREX=P_P2 STOREP==STORE(STOREX) %IF STOREP_REALAD<0 %THEN %C OPMESS("PAGE ".STRINT(STOREX)." ABANDONED") %AND %RETURN STOREP_FLINK=0 STOREP_BLINK=BSTASL %IF BSTASL=0 %THEN FSTASL=STOREX %ELSE STORE(BSTASL)_FLINK=STOREX BSTASL=STOREX %IF FREEEPAGES=0 %THEN UNINHIBIT(5) FREEEPAGES=FREEEPAGES+1 ! STASLSEMA=-1 %END !----------------------------------------------------------------------- %ROUTINE DEADLOCK %INTEGER PP,PPP,PL,PS ! HORRIBLE FRIG TO MAKE SURE SUITABLE PROCESS GETS PAGE ZERO !!! PP=SERVA(5)_P&X'7FFFFFFF' ;! SERVICE 5 = GET EPAGE PPP=PP %UNTIL PP=PPP %CYCLE PL=PARM(PP)_LINK PS=PARM(PL)_SRCE %IF PS=X'00040003' %THEN PS=PARM(PL)_P5 ;! 4/3=PAGE-IN GET EPAGE %IF LOCSN0>16<=LOCSN1 %THEN %START SERVA(5)_P=X'80000000'!PP UNINHIBIT(5) FREEEPAGES=1 PRINT STRING("DEADLOCK RECOVERED ") DEADLOCKS=DEADLOCKS+1 %RETURN %FINISH PP=PL %REPEAT MONITOR("DEADLOCK UNRECOVERABLE") %END !----------------------------------------------------------------------- %ROUTINE ACTIVE MEM(%RECORDNAME P) %RECORDSPEC P(PARMF) %ROUTINESPEC APPENDAMTA(%INTEGER NEWSPACE,REALAD) %ROUTINESPEC APPENDAMTDD(%INTEGER NEWSPACE,REALAD) %ROUTINESPEC DDASLALLOC(%INTEGER FROM,TO) %ROUTINESPEC DEALLOCAMT %ROUTINESPEC DEALLOCDD(%INTEGER DDX,LEN) %INTEGER HASH,DDX,GARB,AMTX,SRCE,ID,DA,LEN,MASK,REALAD,FREEMAX,I,J,K %LONGINTEGER LIM %RECORDNAME PROC(PROCF) %OWNHALFINTEGERARRAY AMTHASH(0:511)=0(512) %RECORDNAME AMT(AMTF) %OWNINTEGERARRAYNAME AMTAPT %OWNINTEGER AMTASIZE,AMTASL,AMTCLOCKS,AMTANEXT,AMTAGETEP=0 %OWNINTEGERARRAYNAME AMTDDPT %OWNINTEGERARRAY DDASL(1:MAXBLOCK)=0(MAXBLOCK) %OWNINTEGER AMTDDSIZE,AMTDDNEXT,AMTDDGETEP=0 %SWITCH ACT(0:7) ? %IF KMON&1<<8#0 %THEN PRINT STRING("ACTIVEMEM:") %AND PTREC(P) SRCE=P_SRCE ID=P_P1 ->ACT(P_DEST&X'FFFF') !----------------------------------------------------------------------- ACT(0):! INITIALISE REALAD=NEW EPAGE LIM=MAXAMTAK-1 ! PUBLIC SEGMENT 'AMTASEG' FOR AMTA RECORD ARRAY PST(AMTASEG)=X'4110038080000001'!LIM<<42!REALAD ! SET UP PAGE TABLE FOR IT AT BEGINNING OF FIRST EPAGE OF ITSELF AMTAPT==ARRAY(VIRTAD!REALAD,PTF) AMTA==ARRAY(X'80000000'!AMTASEG<<18+MAXAMTAK<<2,AMTAF) APPENDAMTA(EPAGESIZE<<10-MAXAMTAK<<2,REALAD) REALAD=NEW EPAGE LIM=MAXAMTDDK-1 ! PUBLIC SEGMENT 'AMTDDSEG' FOR AMTDD ARRAY PST(AMTDDSEG)=X'4110038080000001'!LIM<<42!REALAD ! SET UP PAGE TABLE FOR IT AT BEGINNING OF FIRST EPAGE OF ITSELF AMTDDPT==ARRAY(VIRTAD!REALAD,PTF) AMTDD==ARRAY(X'80000000'!AMTDDSEG<<18+MAXAMTDDK<<2,AMTDDF) APPENDAMTDD(EPAGESIZE<<10-MAXAMTDDK<<2,REALAD) %IF DRUMSIZE=0 %THEN DRUMTASL=DTEND %ELSE %START %CYCLE I=0,1,DRUMSIZE-2 DRUMT(I)=I+1 %REPEAT DRUMT(DRUMSIZE-1)=DTEND DRUMTASL=0 ? DRUMALLOC=0 ? DISPLAY TEXT(0,2,36,"DRUM") ? DISPLAY TEXT(0,3,37,"0%") %FINISH %RETURN !----------------------------------------------------------------------- ACT(1):! GET AMTX DA=P_P2 LEN=P_P3&X'F'+1 MASK=P_P3 ;! "NEW" EPAGE BIT MASK (TOP BITS) HASH=(DA-(DA//509)*509)&X'1FF' ;! DA MIGHT BE NEGATIVE %IF AMTHASH(HASH)#0 %THEN %START ;! SOMETHING HAS SAME HASH AMTX=AMTHASH(HASH) %UNTIL AMTX=0 %CYCLE ;! SCAN DOWN LIST AMT==AMTA(AMTX) %IF AMT_DA=DA %THEN %START ;! THIS DA ALREADY IN TABLE %IF AMT_LEN#LEN %THEN %START %IF AMT_USERS#0 %THEN AMTX=-3 %AND ->RETURN %IF AMT_LENRETURN ;! EXTEND ? %CYCLE I=AMT_DDP+LEN,1,AMT_DDP+AMT_LEN-1 ! RETURN IF STILL IN USE %IF AMTDD(I)&STXMASK#STXMASK %THEN AMTX=0 %AND ->RETURN %REPEAT DEALLOCDD(AMT_DDP+LEN,AMT_LEN-LEN) AMT_LEN=LEN %FINISH AMT_USERS=AMT_USERS+1 ;! USERS ->RETURN %FINISH AMTX=AMT_LINK %REPEAT %FINISH %IF AMTASL=0 %THEN %START ;! NO AMT CELLS FREE ! APPEND EXTRA EPAGE TO AMTA SEGMENT IF POSSIBLE %IF AMTANEXTAMTAGOTEP AMTAGETEP=1 %FINISH AMTX=-1 ->RETURN AMTAGOTEP:APPENDAMTA(EPAGESIZE<<10,STORE(P_P2)_REALAD) %FINISH ! ALLOCATE NEW SPACE GARB=0 ;! NOT GARBAGE COLLECTED YET RETRY:%IF DDASL(LEN)#0 %THEN %START DDX=DDASL(LEN) DDASL(LEN)=AMTDD(DDX) %FINISH %ELSE %START ! TAKE SPACE FROM A BIGGER HOLE I=LEN+1 %WHILE I<=MAXBLOCK %CYCLE DDX=DDASL(I) %IF DDX#0 %THEN %START DDASL(I)=AMTDD(DDX) AMTDD(DDX+LEN)=DDASL(I-LEN) DDASL(I-LEN)=DDX+LEN ->SETAMT %FINISH I=I+1 %REPEAT ! NO HOLES BIG ENOUGH %IF GARB#0 %THEN AMTX=-2 %AND ->RETURN ;! STILL NOT ENOUGH SPACE OPMESS("AMTDD GARBAGE COLLECT") ! CLEAR ALL FREE HOLES TO ZERO %CYCLE I=1,1,MAXBLOCK %WHILE DDASL(I)#0 %THEN J=DDASL(I) %AND DDASL(I)=AMTDD(J) %C %AND AMTDD(J)=0 %REPEAT FREEMAX=0 I=AMTDDSIZE+1 ALLOC:%WHILE I>1 %CYCLE I=I-1 %IF AMTDD(I)=0 %THEN %START DDX=I %WHILE I>1 %CYCLE I=I-1 %IF AMTDD(I)#0 %THEN DDASLALLOC(I+1,DDX) %AND ->ALLOC %REPEAT DDASLALLOC(1,DDX) %EXIT %FINISH %REPEAT GARB=1 ! APPEND EXTRA EPAGE TO AMTDD SEGMENT IF POSSIBLE %IF FREEMAX<32 %AND AMTDDNEXTRETRY %FINISH SETAMT:AMTX=AMTASL ;! PUSHDOWN NEW AMT CELL AMT==AMTA(AMTX) AMTASL=AMT_LINK AMT_DA=DA AMT_DDP=DDX AMT_USERS=1 AMT_LEN=LEN AMT_OUTS=0 AMT_LINK=AMTHASH(HASH) AMTHASH(HASH)=AMTX %CYCLE I=DDX,1,DDX+LEN-1 AMTDD(I)=MASK>>31<<15!STXMASK MASK=MASK<<1 %REPEAT RETURN:P_P1=ID P_P2=AMTX %IF SRCE>0 %THEN P_DEST=SRCE %AND P_SRCE=X'80001' %AND PON(P) %RETURN !----------------------------------------------------------------------- ACT(2):! RETURN AMTX AMTX=P_P2 AMT==AMTA(AMTX) MASK=0 %CYCLE I=AMT_DDP+AMT_LEN-1,-1,AMT_DDP ;! GET "NEW" EPAGE BIT MASK MASK=AMTDD(I)>>15<<31!MASK>>1 %REPEAT AMT_USERS=AMT_USERS-1 %IF AMT_USERS=0 %AND AMT_OUTS=0 %THEN DEALLOCDD(AMT_DDP,AMT_LEN) %C %AND DEALLOCAMT P_P1=MASK %RETURN !----------------------------------------------------------------------- ACT(3):! RETURN AMTX AFTER TRANFERS FINISHED AMTX=P_P2 AMT==AMTA(AMTX) DEALLOCDD(AMT_DDP,AMT_LEN) DEALLOCAMT %RETURN !----------------------------------------------------------------------- ACT(4):! ENTERED EVERY 10 SECS ? %IF DRUMSIZE#0 %THEN DISPLAY TEXT(0,3,37,STRINT(100* %C DRUMALLOC//DRUMSIZE)."% ") ! CHECK FOR INACTIVE PROCESSES EVERY 30 SECS %IF AMTCLOCKS<3 %THEN AMTCLOCKS=AMTCLOCKS+1 %AND %RETURN AMTCLOCKS=0 ! RELEASE AM IF NOT BEING USED I=1 J=0 %UNTIL J=COM_USERS %CYCLE PROC==PROCA(I) %IF PROC_USER#"" %THEN %START %IF PROC_ACTIVE=4 %THEN %START ;! 2 MINS INACTIVITY P_DEST=(I+LOCSN3)<<16 ;! ASYNCH ACT 0 P_SRCE=X'80000' P_P1=2 ;! RELEASE ACTIVE MEMORY PON(P) %FINISH PROC_ACTIVE=PROC_ACTIVE+1 %UNLESS PROC_ACTIVE>4 J=J+1 %FINISH I=I+1 %REPEAT %RETURN !----------------------------------------------------------------------- ACT(5):! CHECK DISC ADDRESS ACTIVE DA=P_P1 HASH=(DA-(DA//509)*509)&X'1FF' AMTX=AMTHASH(HASH) %WHILE AMTX#0 %THEN %CYCLE AMT==AMTA(AMTX) %IF AMT_DA=DA %THEN %START %IF AMT_OUTS#0 %THEN P_DEST=1 %AND %RETURN OPMESS("BLOCK STILL ACTIVE") OPMESS("AMTX : X".STRHEX(AMTX)) OPMESS("DA : X".STRHEX(AMT_DA)) OPMESS("USERS : ".STRINT(AMT_USERS)) OPMESS("OUTS : ".STRINT(AMT_OUTS)) %EXIT ;! TREAT AS OK %FINISH AMTX=AMT_LINK %REPEAT P_DEST=0 %RETURN !----------------------------------------------------------------------- ACT(6):! EXTRA EPAGE FOR AMTA HAS ARRIVED APPENDAMTA(EPAGESIZE<<10,STORE(P_P2)_REALAD) AMTAGETEP=0 %RETURN !----------------------------------------------------------------------- ACT(7):! EXTRA EPAGE FOR AMTDD HAS ARRIVED APPENDAMTDD(EPAGESIZE<<10,STORE(P_P2)_REALAD) AMTDDGETEP=0 %RETURN !----------------------------------------------------------------------- %ROUTINE APPENDAMTA(%INTEGER NEWSPACE,REALAD) %INTEGER FIRSTNEW,I,J UNALLOCEPS=UNALLOCEPS-1 J=X'80000001'!REALAD %CYCLE I=0,1,EPAGESIZE-1 AMTAPT(I+AMTANEXT)=J+I<<10 %REPEAT AMTANEXT=AMTANEXT+EPAGESIZE FIRSTNEW=AMTASIZE+1 AMTASIZE=AMTASIZE+NEWSPACE//AMTFLEN ;! MIGHT WASTE THE ODD RECORD %CYCLE I=FIRSTNEW,1,AMTASIZE-1 AMTA(I)_LINK=I+1 %REPEAT AMTA(AMTASIZE)_LINK=AMTASL AMTASL=FIRSTNEW OPMESS("AMTA NOW ".STRINT(AMTANEXT)."KB") %END !----------------------------------------------------------------------- %ROUTINE APPENDAMTDD(%INTEGER NEWSPACE,REALAD) %INTEGER FIRSTNEW,I,J UNALLOCEPS=UNALLOCEPS-1 J=X'80000001'!REALAD %CYCLE I=0,1,EPAGESIZE-1 AMTDDPT(I+AMTDDNEXT)=J+I<<10 %REPEAT AMTDDNEXT=AMTDDNEXT+EPAGESIZE FIRSTNEW=AMTDDSIZE+1 AMTDDSIZE=AMTDDSIZE+NEWSPACE//DDFLEN FREEMAX=0 DDASLALLOC(FIRSTNEW,AMTDDSIZE) OPMESS("AMTDD NOW ".STRINT(AMTDDNEXT)."KB") %END !----------------------------------------------------------------------- %ROUTINE DDASLALLOC(%INTEGER FROM,TO) ! CHOP UP AMTDD(FROM:TO) INTO MAXBLOCKS AND A LEFTOVER %INTEGER LEN %CYCLE LEN=TO-FROM+1 %IF LEN>=MAXBLOCK %THEN %START AMTDD(FROM)=DDASL(MAXBLOCK) DDASL(MAXBLOCK)=FROM FREEMAX=FREEMAX+1 FROM=FROM+MAXBLOCK %FINISH %ELSE %START %IF FROM<=TO %THEN AMTDD(FROM)=DDASL(LEN) %AND DDASL(LEN)=FROM %RETURN %FINISH %REPEAT %END !----------------------------------------------------------------------- %ROUTINE DEALLOCAMT %INTEGER AMTP,AMTPP,HASH,DA DA=AMTA(AMTX)_DA HASH=(DA-(DA//509)*509)&X'1FF' AMTP=AMTHASH(HASH) ;! FIND PREVIOUS CELL %IF AMTP=AMTX %THEN AMTHASH(HASH)=AMTA(AMTP)_LINK %ELSE %START AMTPP=AMTP %AND AMTP=AMTA(AMTP)_LINK %UNTIL AMTP=AMTX AMTA(AMTPP)_LINK=AMTA(AMTP)_LINK %FINISH AMTA(AMTP)_LINK=AMTASL ;! RETURN CELL AMTASL=AMTX %END !----------------------------------------------------------------------- %ROUTINE DEALLOCDD(%INTEGER DDX,LEN) %INTEGER I,J,DTX %CYCLE I=DDX,1,DDX+LEN-1 %IF AMTDD(I)&DTXBIT#0 %THEN %START ;! RETURN DRUM PAGE DTX=AMTDD(I)&STXMASK J=DRUMT(DTX) %IF J#STXMASK %THEN STORE(J)_FLAGS=0 DRUMT(DTX)=DRUMTASL DRUMTASL=DTX ? DRUMALLOC=DRUMALLOC-1 %FINISH %ELSE %START J=AMTDD(I)&STXMASK %IF J#STXMASK %THEN STORE(J)_FLAGS=0 %FINISH AMTDD(I)=0 %REPEAT I=DDASL(LEN) AMTDD(DDX)=I DDASL(LEN)=DDX %END !----------------------------------------------------------------------- %END !----------------------------------------------------------------------- ?%ROUTINE TIMEOUT(%RECORDNAME P) ?%RECORDSPEC P(PARMF) ?%CONSTSTRING(15)%ARRAY SERVROUT(0:66)="IDLE TIME",""(2),"SCHEDULE", "PAGETURN","GET EPAGE","RETURNEPAGE","SEMAPHORE","ACTIVEMEM","", "ELAPSEDINT","UPDATE TIME","DPONPUTONQ","TURNONEP","PROCMON",""(17), "DISC","DISCP","DISC INTERRUPT","","MOVE/1","MOVE/2",""(2), "DRUM/1","DRUM/2","DRUM INTERRUPT",""(5),"GPC","TAPE", "OPER","LP ADAPTOR","CR ADAPTOR","CP ADAPTOR","PRINTER", "COMMS CONTROL/1","COMMS CONTROL/2","MK1FEADAPTOR","GPC INTERRUPT", ""(3),"COMREP",""(2),"LOCAL CONTROL","LOCAL PROCESS" ;! (0:LOCSN0+2) ?%STRING(31)%FN STRPRINT(%REAL X,%INTEGER B,A) ?! STRING OF "PRINT(X,B,A)" ?%STRING(31) S,T,U ?%INTEGER I ?%REAL Y ? %IF X<0 %THEN X=-X %AND U="-" %ELSE U="" ? Y=10**A ? X=INT(X*Y)/Y ;! ROUND ? I=INTPT(X) ? S=U.STRINT(I) ? %WHILE LENGTH(S)>33<<32!L&X'0FFFFFFFF')<<1 %END !----------------------------------------------------------------------- %ROUTINE UPDISP(%INTEGER PROCESS,OFFSET,%STRING(13) S) %INTEGER I %IF PROCESS<=57 %THEN %START I=(PROCESS-1)//19 DISPLAY TEXT(0,PROCESS-I*19+4,I*13+OFFSET,S) %FINISH %ELSE %START PROCESS=PROCESS-57 I=(PROCESS-1)//24 DISPLAY TEXT(0,PROCESS-I*24+23,I*13+OFFSET,S) %FINISH %END !----------------------------------------------------------------------- !----------------------------------------------------------------------- %ROUTINE LOCAL CONTROL !----------------------------------------------------------------------- ! DIRECTOR COMMUNICATIONS RECORDS %RECORD DIROUTP(PARMF) %RECORDFORMAT SIGOUTPF(%INTEGER DEST,SRCE,P1,P2,P3,P4,P5,P6, %C TYPE,SSN,SSNAD,SUSP) %RECORD SIGOUTP(SIGOUTPF) !----------------------------------------------------------------------- ! CLAIMED BLOCK TABLES %BYTEINTEGERARRAY SST(0:LSTLEN-1) %RECORDFORMAT CBTF(%INTEGER DA,%BYTEINTEGER ABTX,MASK2,TAGS,LINK) %RECORDARRAY CBTA(0:254)(CBTF) %INTEGER CBTASL %RECORDNAME CBT(CBTF) %INTEGER CBTP !----------------------------------------------------------------------- ! SYSTEM CALL TABLE INDEX %LONGINTEGERARRAY SCTI(-1:3),SCTJ3(-1:7) !----------------------------------------------------------------------- ! CONSOLE IO RECORDS %RECORDFORMAT IOSTATF(%INTEGER IAD,%STRING(15) INTMESS, %C %INTEGER INBUFLEN,OUTBUFLEN,INSTREAM,OUTSTREAM) %RECORDNAME IOSTAT(IOSTATF) !----------------------------------------------------------------------- ! ACCOUNTING INFORMATION %RECORDFORMAT ACNTF(%LONGINTEGER LTIME,%INTEGER PTURNS) %RECORDNAME ACNT(ACNTF) ! INSTRUCTION COUNTER REVS WORD %INTEGERNAME ICREVS,SEMAHELD !----------------------------------------------------------------------- ! ACTIVE BLOCK TABLES %CONSTINTEGER MAXABT=48 %RECORDFORMAT ABTF(%HALFINTEGER AMTX,%BYTEINTEGER CBTX,SEG,STEP, %C PREV,NEXT,LINK) %RECORDARRAY ABTA(1:MAXABT)(ABTF) %RECORDNAME ABT(ABTF) %RECORDFORMAT EPF(%BYTEINTEGER ST,X,LINK) %RECORDARRAY EPA(1:MAXEPAGES)(EPF) %RECORDNAME EP(EPF) %INTEGER ABTT,ABTB,ABTASL,EPASL %BYTEINTEGER PTP !----------------------------------------------------------------------- ! LOCAL STACKS INFORMATION %BYTEINTEGERARRAY LSTKSSN(1:LSTKN) !----------------------------------------------------------------------- ! CATEGORY INFORMATION %INTEGER EPLIM,EPN,RTLIM,RTN,ABTN !----------------------------------------------------------------------- %INTEGERFNSPEC CHECK RES(%INTEGER WRITE,LEN,AD) %ROUTINESPEC CONNECT(%INTEGER SEG,DA,LEN,ACC) %ROUTINESPEC PUSHEP(%BYTEINTEGERNAME LP,%INTEGER X) %ROUTINESPEC POPEP(%BYTEINTEGERNAME LP) %ROUTINESPEC ABTOUT(%INTEGER ABTX) %ROUTINESPEC STROBE(%INTEGER KEEPUSE) %ROUTINESPEC WORKSET %ROUTINESPEC CLEAR ACCESSED BITS %ROUTINESPEC RETURN PTS %INTEGERFNSPEC FIND PROCESS %INTEGERFNSPEC CURSSN %STRING(255)%FNSPEC VSINT %STRING(255)%FNSPEC PROGERR %ROUTINESPEC WAIT(%INTEGER DACT,N) %ROUTINESPEC PMON(%STRING(63) S) !----------------------------------------------------------------------- %RECORDNAME PROC(PROCF) %RECORDNAME SERV0,SERV,SERV3(SERVF) %RECORD POUT(PARMF) %RECORDNAME PA(PARMAF) %RECORDNAME SSNP1(SSNP1F) %LONGINTEGERARRAYNAME LST %INTEGERARRAYNAME PT %INTEGER PROCESS,ME,LSN3,PTAD,VSPARM,PEPARM,VSSEG,VSEPAGE,AMTX,EPX,I,J,K %INTEGER PROCMON,PMONEN,NEWSTK,STOREX,ABTX,CBTX,DEST,SRCE,SUSP,DIROUTPAD %INTEGER WSN,STEP,XSTROBE,SEGLEN,PTEPS,ABTDESTROY,PARTALLOC %INTEGER PROCSTACK1,PROCSTACK2,HIGHSEG,SCTI0,SCTJ30,LOCKST,LOCKSTX,LTAD %STRING(15) INTMESS %SWITCH ACTIVITY(1:16),VSCAUSE(0:4),ASYN0(1:3),AMTXSW(-3:0) %CONSTINTEGER MAXDIROUT=26 %SWITCH DIROUT(0:MAXDIROUT) %CONSTINTEGER MAXOUTACR=6 ;! UP TO SUB-SYSTEM LEVEL %CONSTSTRING(2)%ARRAY EPUSE(0:3)="","W","R","RW" %BYTEINTEGERNAME EPL %STRING(3) STRSEG %CONSTBYTEINTEGERARRAY PAGEOUT DELAY(0:10)=1,2,4,8,15(7) ! TOTAL DELAY>120 SECS TO ALLOW TIME TO AUTOLOAD DFC ! %CONSTSTRING(6)%ARRAY STRPART(0:1)="","(PART)" !----------------------------------------------------------------------- ! INITIAL PROCESS CREATE ENTRY ONLY *LSS_OLDLNB *ST_(%LNB+0) ;! TO FRIG %MONITOR PROCESS=P_P1 PROC==PROCA(PROCESS) ME=(PROCESS+LOCSN0)<<16 LSN3=PROCESS+LOCSN3 SERV0==SERVA(PROCESS+LOCSN0) SERV3==SERVA(LSN3) !----------------------------------------------------------------------- ! INITIALISE CLAIMED BLOCK TABLES %CYCLE I=0,1,LSTLEN-1 SST(I)=255 ;! ALL SEGMENTS UNCONNECTED %REPEAT %CYCLE I=0,1,254 CBTA(I)_LINK=I+1 %REPEAT CBTASL=0 %CYCLE I=1,1,MAXABT ;! LAST LINK NOT USED !! ABTA(I)_LINK=I+1 %REPEAT ABTASL=1 ABTT=255 ABTB=255 ABTN=0 %CYCLE I=1,1,MAXEPAGES ;! LAST LINK NOT USED !! EPA(I)_LINK=I+1 %REPEAT EPASL=1 EPN=0 ;! NO EPAGES USED SO FAR PTP=255 PROCSTACK1=X'28000001' PROCSTACK2=ADDR(PROC_STACK) ;! %INTEGERNAME DESCRIPTOR DIROUTPAD=ADDR(DIROUTP) PROCMON=0 PMONEN=0 ;! PROCMON NOT ENABLED SUSP=0 ABTDESTROY=0 SCTI0=ADDR(SCTI(0))&X'FFFFFFF8' ;! DBLE-WORD ALIGNED SCTJ30=ADDR(SCTJ3(0))&X'FFFFFFF8' ! FILL IN SCTI(3)[ALIGNED] INTEGER(SCTI0+24)=X'38000004' INTEGER(SCTI0+28)=SCTJ30 LONG INTEGER(SCTJ30)=0 LONG INTEGER(SCTJ30+8)=0 ! REQUEST INPUT LONG INTEGER(SCTJ30+16)=X'80F0000000140001' LONG INTEGER(SCTJ30+24)=RTDR(REQUEST INPUT); ! YIELDS DESCR-DESCR ! REQUEST OUTPUT LONG INTEGER(SCTJ30+32)=X'80F0000000140001' LONG INTEGER(SCTJ30+40)=RTDR(REQUEST OUTPUT); ! YIELDS DESCR-DESCR ! CHANGE CONTEXT LONG INTEGER(SCTJ30+48)=X'80F0000000140001' LONG INTEGER(SCTJ30+56)=RTDR(CHANGE CONTEXT) !----------------------------------------------------------------------- ! INITIALIZE LOCAL STACKS INFO LST==ARRAY(0,LSTF) ;! LOCAL SEG TABLE IN SEG 0 LSTKSSN(1)=4 ;! DIRECTOR/USER STACK SEGMENT LST(5)=LST(1)+X'80' LSTKSSN(2)=6 ;! SIGNAL STACK LST(7)=LST(1)+X'100' %CYCLE I=3,1,LSTKN LSTKSSN(I)=0 %REPEAT ! CONNECT DIRECTOR FILES CONNECT(2,P_P2,SEGEPSIZE,X'100'!DIRACR) ;! CODE CONNECT(3,P_P3,MAXBLOCK,DIRACR<<4!DIRACR) ;! GLA CONNECT(4,P_P4,SEGEPSIZE-1,X'FF') ;! STACK !----------------------------------------------------------------------- %IF PROCESS=1 %THEN %START ;! SET UP IST ENTRIES ONCE ONLY ! SET UP DUMMY IST VECTOR *STLN_I ISTDUM_LNB=I ISTDUM_PSR=X'00140001' ISTDUM_PC=0 ISTDUM_SSR=X'01800EFE' ;! ONLY OUT & SYSERR *STSF_I ISTDUM_SF=I ISTDUM_IT=MAXIT ISTDUM_IC=MAXIT ISTDUM_SP=0 ! SET VS ERROR IST ENTRY TO ENTER LOCAL ISTP==RECORD(ISTAD+X'80') ISTP=ISTDUM *JLK_ ; *LSS_%TOS ; *ST_I ISTP_PC=I ! SET INTERVAL TIMER IST ENTRY TO ENTER LOCAL ISTP==RECORD(ISTAD+X'A0') ISTP=ISTDUM *JLK_ ; *LSS_%TOS ; *ST_I ISTP_PC=I ! SET PROG ERROR IST ENTRY TO ENTER LOCAL ISTP==RECORD(ISTAD+X'C0') ISTP=ISTDUM *JLK_ ; *LSS_%TOS ; *ST_I ISTP_PC=I ! SET SYSTEM CALL IST ENTRY ISTP==RECORD(ISTAD+X'E0') ISTP_LNB=0 ISTP_PSR=X'00140001' ISTP_PC=SCASSPC ISTP_SF=ADDR(PROCSTACK1) ISTP_IT=ADDR(ACTW0) ISTP_IC=X'30000004' ;! 64 BIT VECTOR DESCRIPTOR TO SCTI ISTP_SP=SCTI0 ! SET UP OUT IST ENTRY ISTP==RECORD(ISTAD+X'100') ISTP=ISTDUM *JLK_ ; *LSS_%TOS ; *ST_I ISTP_PC=I ! SET EVENT PENDING IST ENTRY ISTP==RECORD(ISTAD+X'140') ISTP=ISTDUM *JLK_ ; *LSS_%TOS ; *ST_I ISTP_PC=I ! SET INSTRUCTION COUNTER IST ENTRY ISTP==RECORD(ISTAD+X'160') ISTP=ISTDUM *JLK_ ; *LSS_%TOS ; *ST_I ISTP_PC=I ! SET UP LOCAL CONTROLLER REACTIVATE CONTEXT *STLN_I LSSNP1_LNB=I LSSNP1_PSR=X'00140001' *JLK_ ; *LSS_%TOS ; *ST_I LSSNP1_PC=I LSSNP1_SSR=X'01800FFE' *STSF_I LSSNP1_SF=I LSSNP1_IT=MAXIT LSSNP1_IC=MAXIT LSSNP1_SP=0 %FINISH !----------------------------------------------------------------------- ! SET UP DIRECTOR CONTEXT NEWSTK=LSTKSSN(1)<<18 SSNP1==RECORD(NEWSTK!X'40000') SSNP1=0 SSNP1_LNB=NEWSTK SSNP1_PSR=X'00140001' ;! PROG ERRORS UNMASKED SSNP1_PC=X'00080010' ;! TO M-C CODE DIRLOADER SSNP1_SSR=X'01800000' ;! ALL INTS ALLOWED SSNP1_SF=NEWSTK!X'14' ;! 5 WORDS ON FROM LNB SSNP1_IT=0 SSNP1_IC=MAXIT SSNP1_B=DIROUTPAD SSNP1_DR0=X'B1000000' ;! DESCRIPTOR DESCRIPTOR TO ENTRY DESCRIPTOR SSNP1_DR1=X'000C0000' ;! I.E. START OF GLA ! DIRECTOR STACK ON INITIAL ENTRY PROC_STACK=NEWSTK !----------------------------------------------------------------------- ! THE FOLLOWING RECORDS ARE SQUEEZED INTO THE SPARE WORDS OF SEGMENT 5 ! IOSTAT : WORDS 18 - 26 ! ICREVS : WORD 27 ! ACNT : WORDS 28 - 30 ! DIROUTPAD : WORD 31 ! THERE IS NO MORE SPACE LEFT !!!! IOSTAT==RECORD(NEWSTK!X'40048') IOSTAT=0 ACNT==RECORD(NEWSTK!X'40070') ACNT=0 ICREVS==INTEGER(NEWSTK!X'4006C') ICREVS=X'12345678' INTEGER(NEWSTK!X'4007C')=DIROUTPAD !----------------------------------------------------------------------- ! SET UP SIGNAL CONTEXT NEWSTK=LSTKSSN(2)<<18 SSNP1==RECORD(NEWSTK!X'40000') SSNP1=0 SSNP1_LNB=NEWSTK SSNP1_PSR=X'0014FF01' ;! PROGRAM ERRORS MASKED SSNP1_PC=X'00080010' ;! TO M-C CODE DIRLOADERRY POINT SSNP1_SSR=X'01800800' ;! NO INSTRUCTION COUNTER INTS SSNP1_SF=NEWSTK!X'14' SSNP1_IT=0 SSNP1_IC=MAXIT SSNP1_B=0 ;! ZERO DISTINGUISHES SIGNAL ENTRY !!!!! SSNP1_DR0=X'B1000000' SSNP1_DR1=X'000C0000' ! THE FOLLOWING WORDS ARE SQUEEZED INTO SPARE WORDS OF SEGMENT 7 ! IE SSN+1 OF THE SIGNAL STACK ! WORD18 = SEMAHELD SET BY DIRECTOR WHEN A SEMAPHORE IS HELD ! SEMAHELD==INTEGER(NEWSTK!(X'40000'+4*18)) !----------------------------------------------------------------------- ! INITIALISATIONS FOR DIRECTOR STRING(DIROUTPAD)=SUPID DIROUTP_SRCE=EPAGESIZE<<16!MAXBLOCK DIROUTP_P1=PROCESS STRING(ADDR(DIROUTP_P2))=PROC_USER DIROUTP_P4=ADDR(SIGOUTP) DIROUTP_P5=SCTI0 DIROUTP_P6=0 SIGOUTP_DEST=LSTLEN SIGOUTP_SRCE=ADDR(SST(0)) SIGOUTP_P1=ADDR(CBTASL) SIGOUTP_P2=ADDR(CBTA(0)) SIGOUTP_P3=ADDR(ACNT) SIGOUTP_P4=ADDR(ICREVS) SIGOUTP_P5=ADDR(IOSTAT) !----------------------------------------------------------------------- ! REPLY TO SCHEDULE POUT=0 POUT_DEST=X'30002' ;! SCHEDULE/CREATED POUT_SRCE=ME POUT_P1=PROCESS PON(POUT) !----------------------------------------------------------------------- RETURN:! OUT BACK TO KERNEL KSSNP1P=KSSNP1 ;! KERNEL REACTIVATE CONTEXT *LSS_X'01800FFF' ;! NO SYSTEM ERROR INTS *ST_(3) LSSNP1P=LSSNP1 ;! LOCAL CONTROLLER REACTIVATE CONTEXT ACTW3=KSTACK ? *LSS_(6) ;? *ST_IC ;? *LSS_(5) ;? *ST_IT ? LCIC=LCIC+MAXIT-IC ? LCIT=LCIT+MAXIT-IT *ACT_ACTW0 ;! REACTIVATE BACK TO KERNEL !----------------------------------------------------------------------- ENTERI:*JLK_%TOS ! NORMAL LOCAL CALLS ENTER HERE ! PARAMETER RECORD P (GLOBAL) ENTER:->ACTIVITY(P_DEST&X'FFFF') !----------------------------------------------------------------------- ACTIVITY(1):! START RESIDENCE PERIOD ! P_P1=EPAGE LIMIT ! P_P2=RESIDENCE TIME LIMIT ! P_P3=ACTIVE EPAGES LIMIT EPLIM=P_P1 RTLIM=P_P2 PARTALLOC=P_P3 ;! PARTIAL ALLOCATION IF #0 %IF PROCMON#0 %THEN PMON("CATEGORY ".STRINT(EPLIM). %C STRPART(PARTALLOC)."/".STRINT(RTLIM)." ") ! SET UP SSN+1 CONTEXT ADDRESSES %CYCLE I=1,1,LSTKN %IF LSTKSSN(I)#0 %THEN LST(LSTKSSN(I)+1)=LST(1)+I*X'80' %REPEAT SEMAHELD=0 PROC_STATUS=PROC_STATUS&X'FFFFFFFE' SSNP1==RECORD(PROC_STACK!X'40000') ;! PROCESS CONTEXT %IF SSNP1_IT&X'FF800000'=0 %THEN LPIT=LPIT-SSNP1_IT %AND %C ACNT_LTIME=ACNT_LTIME-COM_ITINT*SSNP1_IT ;! UNUSED TIME SSNP1_IT=TIMESLICE ;! START NEW TIMESLICE LPIT=LPIT+TIMESLICE ACNT_LTIME=ACNT_LTIME+COM_ITINT*TIMESLICE XSTROBE=0 PTEPS=0 RTN=0 HIGHSEG=2 %IF SERV3_P<<1#0 %AND PROC_STACK#LSTKSSN(2)<<18 %THEN ->ASYNCH %IF SUSP#0 %THEN ->DIRPONREPLY ACT:%IF KERNELQ#0 %THEN ->ONFRUNQ ;! DO ANY KERNEL SERVICES ? LPN=LPN+1 ;! NO OF ACTIVATIONS TO PROCESSES ACTW3=PROC_STACK ? *LSS_(6) ;? *ST_IC ;? *LSS_(5) ;? *ST_IT ? LCIC=LCIC+MAXIT-IC ? LCIT=LCIT+MAXIT-IT *ACT_ACTW0 !----------------------------------------------------------------------- ACTIVITY(2):! CONTINUE WITH CORE RESIDENCE ACTIVATE:! CHECK ASYNCH MESSAGE %IF SERV3_P<<1=0 %OR PROC_STACK=LSTKSSN(2)<<18 %THEN ->ACT !----------------------------------------------------------------------- ASYNCH:! ASYNCHRONOUS MESSAGE SUPPOFF(SERV3,P) I=P_DEST&X'FFFF' %IF I=0 %THEN ->ASYN0(P_P1) %IF I=X'FFFF' %THEN OPMESS("PROCESS ".STRINT(PROCESS). %C " TERMINATED") %AND NEWSTK=PROC_STACK %AND ->TERMINATE %UNLESS I=1 %THEN ->SIGINT INTMESS=STRING(ADDR(P_P3)) %IF LENGTH(INTMESS)=1 %THEN %START %IF P_P2>=0 %AND IOSTAT_IAD#P_P2 %THEN IOSTAT_IAD=P_P2 SIGINT:SIGOUTP<-P SIGOUTP_TYPE=3 SIGOUTP_SSN=CURSSN SIGOUTP_SSNAD=PROC_STACK SIGOUTP_SUSP=SUSP ;! PRESERVE SUSPEND STATUS SUSP=0 NEWSTK=LSTKSSN(2)<<18 ! SWOP IT & IC LONG INTEGER(NEWSTK!X'40014')=LONG INTEGER(PROC_STACK!X'40014') PROC_STACK=NEWSTK SSNP1==RECORD(NEWSTK!X'40000') %IF SSNP1_LNB>>18#NEWSTK>>18 %OR SSNP1_LNB>>18#SSNP1_SF>>18 %C %OR SSNP1_PSR&3=0 %THEN PRINT STRING(" ACTIVATE CONTEXT INVALID") %AND ->TERMINATE ->ACTIVATE %FINISH %ELSE %START %IF LENGTH(INTMESS)>1 %THEN IOSTAT_INTMESS=INTMESS %IF P_P2>=0 %AND IOSTAT_IAD#P_P2 %THEN %START IOSTAT_IAD=P_P2 %IF SUSP<0 %THEN SUSP=0 %FINISH RESUSP:%IF SERV3_P<<1#0 %THEN ->ASYNCH %IF SUSP=0 %THEN ->ACT ! AVOID RESUSPENDING IF UNNECESSARY %IF SUSP&X'7FFFFFFF'<=LOCSN3 %THEN %START SERV==SERVA(SUSP) %IF SERV_P<<1#0 %THEN ->DPR ;! DIRPONREPLY %FINISH SRCE=SUSP ->SUSPWS ;! MAY JUST HAVE SWAPPED STACK ! %FINISH !----------------------------------------------------------------------- ASYN0(2):! RELEASE ACTIVE BLOCKS %WHILE ABTB#255 %THEN ABTOUT(ABTB) ->RESUSP !----------------------------------------------------------------------- ASYN0(3):! PROCMON PAGE-IN FAILURE PROCMON=0 ->RESUSP !----------------------------------------------------------------------- VSERRI:*JLK_%TOS ! VIRTUAL STORE INTERRUPTS ENTER HERE *LSS_%TOS *LSS_%TOS ;! PARAMETER *ST_VSPARM %IF PROCMON#0 %THEN PMON(VSINT) %IF VSPARM<0 %THEN PEPARM=9 %AND ->PE VSSEG=VSPARM>>18 VSEPAGE=(VSPARM>>10&X'FF')//EPAGESIZE ->VSCAUSE(VSPARM&7) !----------------------------------------------------------------------- VSCAUSE(0):VSCAUSE(2):VSCAUSE(3):VSE:! VS ERRORS SIGOUTP_P1=VSPARM SIGOUTP_P2=PROC_STACK SIGOUTP_TYPE=1 SIGOUTP_SSN=CURSSN SIGOUTP_SSNAD=PROC_STACK SIGOUTP_SUSP=0 NEWSTK=LSTKSSN(2)<<18 %IF PROC_STACK=NEWSTK %THEN %START PRINT STRING(VSINT."VS ERROR ON SIGNAL STACK ") ->TERMINATE %FINISH LONG INTEGER(NEWSTK!X'40014')=LONG INTEGER(PROC_STACK!X'40014') PROC_STACK=NEWSTK SSNP1==RECORD(NEWSTK!X'40000') %IF SSNP1_LNB>>18#NEWSTK>>18 %OR SSNP1_LNB>>18#SSNP1_SF>>18 %C %OR SSNP1_PSR&3=0 %THEN PRINT STRING(" ACTIVATE CONTEXT INVALID") %AND ->TERMINATE ->ACTIVATE !----------------------------------------------------------------------- VSCAUSE(1):! SEGMENT NOT AVAILABLE %IF SST(VSSEG)=255 %THEN ->VSE ;! NO CONNECTION SEGLEN=LST(VSSEG)>>42&X'FF'//EPAGESIZE+1 ! FUDGE A PAGE NO>LIMIT ERROR IF NECESSARY %IF VSEPAGE>=SEGLEN %THEN VSPARM=VSPARM!3 %AND ->VSE %IF SEGLEN<=PTEPS %THEN ->NEWPT %IF EPN>=EPLIM %THEN ->NOPAGES POUT_DEST=X'50000' POUT_SRCE=ME!X'80000009' POUT_P2=0 ;! CLEAR TO ZERO ? *LSS_(6) ;? *ST_IC ;? *LSS_(5) ;? *ST_IT GET EPAGE(POUT) ? *LSS_(5) ;? *ST_ITT ;? *LSS_(6) ;? *ST_ICC ? GETIT=GETIT+IT-ITT ;? LCIT=LCIT-IT+ITT ? GETIC=GETIC+IC-ICC ;? LCIC=LCIC-IC+ICC ? GETCALLN=GETCALLN+1 %IF POUT_DEST#0 %THEN STOREX=POUT_P2 %AND ->ACT9 ->RETURN !----------------------------------------------------------------------- ACTIVITY(9):! REPLY FROM GET EPAGE FOR PT STOREX=P_P2 %IF STOREX=0 %THEN ->DEAD ;! DEADLY EMBRACE RECOVERY ACT9:PUSHEP(PTP,STOREX) ;! REMEMBER PAGE TABLE EPAGE STOREX PTAD=STORE(STOREX)_REALAD PTEPS=256 NEWPT:LST(VSSEG)=LST(VSSEG)!X'0000000080000001'!PTAD %IF VSSEG>HIGHSEG %THEN HIGHSEG=VSSEG PTEPS=PTEPS-SEGLEN PTAD=PTAD+((SEGLEN*EPAGESIZE+1)//2)<<3 ! RUN STRAIGHT ON INTO A VSCAUSE(4) !----------------------------------------------------------------------- VSCAUSE(4):! PAGE NOT AVAILABLE %IF EPN>=EPLIM %THEN ->NOPAGES CBTP=SST(VSSEG) CBT==CBTA(CBTP) EPX=VSEPAGE %WHILE EPX>CBT_TAGS&X'F' %CYCLE CBTP=CBT_LINK EPX=EPX-CBT_TAGS&X'F'-1 CBT==CBTA(CBTP) %REPEAT %IF CBT_TAGS&X'20'=0 %THEN %START ;! NO ABT SLOT ALLOCATED YET %IF ABTN=MAXABT %THEN %START ? MAXABTN=MAXABTN+1 ABTOUT(ABTB) %FINISH !GET RID OF LRU ACTIVE BLOCK POUT_DEST=X'80001' ;! GET AMTX POUT_SRCE=0 POUT_P1=PROCESS POUT_P2=CBT_DA POUT_P3=CBT_ABTX<<24!CBT_MASK2<<16!CBT_TAGS %IF PROCMON#0 %THEN PMON("GET AMTX ".STRHEX(POUT_P2)." ") ? *LSS_(6) ;? *ST_IC ;? *LSS_(5) ;? *ST_IT ACTIVE MEM(POUT) ? *LSS_(5) ;? *ST_ITT ;? *LSS_(6) ;? *ST_ICC ? AMIT=AMIT+IT-ITT ;? LCIT=LCIT-IT+ITT ? AMIC=AMIC+IC-ICC ;? LCIC=LCIC-IC+ICC ? AMCALLN=AMCALLN+1 AMTX=POUT_P2 %IF AMTX<=0 %THEN ->AMTXSW(AMTX) ! PUSHDOWN ABT ABTX=ABTASL ABT==ABTA(ABTX) ABTASL=ABT_LINK ABT_LINK=255 ABT_AMTX=AMTX ABT_CBTX=CBTP ABT_SEG=VSSEG ABT_STEP=VSEPAGE-EPX ABT_PREV=255 ABT_NEXT=ABTT %IF ABTT=255 %THEN ABTB=ABTX %ELSE ABTA(ABTT)_PREV=ABTX ABTT=ABTX ABTN=ABTN+1 CBT_ABTX=ABTX CBT_TAGS=CBT_TAGS!X'20' %FINISH %ELSE ABT==ABTA(CBT_ABTX) %AND AMTX=ABT_AMTX POUT_DEST=X'40001' ;! PAGETURN/PAGE-IN POUT_SRCE=ME!X'8000000A' ;! REPLY TO ACTIVITY 10 POUT_P1=AMTX<<16!EPX ! P2 : IDENT NOT USED ? *LSS_(6) ;? *ST_IC ;? *LSS_(5) ;? *ST_IT PAGETURN(POUT) ? *LSS_(5) ;? *ST_ITT ;? *LSS_(6) ;? *ST_ICC ? PTIT=PTIT+IT-ITT ;? LCIT=LCIT-IT+ITT ? PTIC=PTIC+IC-ICC ;? LCIC=LCIC-IC+ICC ? PTCALLN=PTCALLN+1 %IF POUT_DEST#0 %THEN J=X'80000001'!POUT_P2 %AND ->ACT10 ->RETURN !----------------------------------------------------------------------- AMTXSW(0):! CHANGE BLOCK SIZE IN SITU ? DELAY:WAIT(2,1) ;! TRY AGAIN IN 1 SEC ->RETURN AMTXSW(-1):! NO AMT CELLS AVAILABLE %IF ABTB=255 %THEN ->DELAY ;! NO ACTIVE BLOCKS TO THROW AWAY ABTOUT(ABTB) ->ACTIVATE AMTXSW(-2):! NOT ENOUGH GARBAGE %WHILE ABTB#255 %THEN ABTOUT(ABTB) ->DELAY AMTXSW(-3):! CHANGE BLOCK SIZE WHEN STILL IN USE PEPARM=19 ->PE !----------------------------------------------------------------------- ACTIVITY(10):! EPAGE HERE ! P_P1=RUBBISH IDENT ! P_P2=STORE(EPAGE)_REALAD ! VSSEG & VSEPAGE STILL INTACT !! EPH:J=X'80000001'!P_P2 ACT10:PUSHEP(ABT_LINK,EPX) ACNT_PTURNS=ACNT_PTURNS+1 !PT==ARRAY(VIRTAD!LST(VSSEG)&X'0FFFFFF8'+VSEPAGE*EPAGESIZE<<2,PTF) !%CYCLE I=0,1,EPAGESIZE-1 ! PT(I)=J+I<<10 !%REPEAT ! ASSUMES EPAGESIZE=4 I=VIRTAD!LST(VSSEG)&X'0FFFFFF8'+VSEPAGE*16 *LXN_I *LSS_J *ST_(%XNB+0) *IAD_1024 *ST_(%XNB+1) *IAD_1024 *ST_(%XNB+2) *IAD_1024 *ST_(%XNB+3) ->ACTIVATE !-------------------------------------------- ACTIVITY(11):! PAGE READ FAILURE %IF P_P3<0 %THEN ->DEAD POUT_DEST=LSN3<<16 POUT_P1=1 POUT_P2=VSSEG<<18!VSEPAGE*EPAGESIZE<<10 PON(POUT) ->EPH !----------------------------------------------------------------------- ! DEADLOCK RECOVERY DEAD:WORKSET POUT_DEST=X'3000E' POUT_P1=PROCESS PON(POUT) ->RETURN !----------------------------------------------------------------------- ITIMERI:*JLK_%TOS ! INTERVAL TIMER INTERRUPTS ENTER HERE *LSS_%TOS ; *LSS_%TOS ! ! IF A SEMA HELD GIVE A SMALL AMOUNT MORE TIME WITHOUT LETTING NEXT ! PERSON ON RUNQ GET THE CPU AS HE MIGHT ALSO WANT THE SEMA ! %IF SEMAHELD#0 %START SEMAHELD=0 SSNP1==RECORD(PROC_STACK!X'40000') SSNP1_IT=TIMESLICE>>3; ! EIGTH OF TIME SLICE LPIT=LPIT+TIMESLICE>>3 ACNT_LTIME=ACNT_LTIME+COM_ITINT*(TIMESLICE>>3) ->ACT %FINISH %IF PROCMON#0 %THEN PMON("TIME-SLICE ") RTN=RTN+1 %IF RTN=1 %THEN %START PROC_RUNQ=CATTAB(PROC_CATEGORY)_RQTS2 ? UPDISP(PROCESS,11,"R".TOSTRING(PROC_RUNQ+'0')) %FINISH %ELSE %START %IF RTN=RTLIM %THEN %START %IF PROCMON#0 %THEN PMON("RESIDENCE LIMIT ") POUT_DEST=X'3000B' ;! MORE TIME ON THE FLY ? POUT_SRCE=0 POUT_P1=PROCESS POUT_P2=EPN SCHEDULE(POUT) %IF POUT_P1=0 %THEN %START WORKSET POUT_DEST=X'30004' ;! OUT OF TIME POUT_SRCE=ME!1 POUT_P1=PROCESS POUT_P2=WSN ;! EPAGES USED SO FAR PON(POUT) ->RETURN %FINISH EPLIM=POUT_P1 RTLIM=POUT_P2 PARTALLOC=POUT_P3 %IF PROCMON#0 %THEN PMON("CATEGORY ".STRINT(EPLIM)."/". %C STRINT(RTLIM)."(ON FLY) ") RTN=0 %FINISH %ELSE %START %IF (RTN-4)&7=0 %THEN STROBE(0) ;! 4,12,20,28 %FINISH %FINISH SSNP1==RECORD(PROC_STACK!X'40000') SSNP1_IT=TIMESLICE LPIT=LPIT+TIMESLICE ACNT_LTIME=ACNT_LTIME+COM_ITINT*TIMESLICE POUT_DEST=ME!2 PON(POUT) ->RETURN !----------------------------------------------------------------------- ONFRUNQ:! PUT ON FRONT OF RUNQ POUT_DEST=ME!2 ONFRUNQA:I=RUNQ PON(POUT) %UNLESS I=0 %THEN RUNQ=I ->RETURN !----------------------------------------------------------------------- NOPAGES:%IF PARTALLOC#0 %THEN %START POUT_DEST=X'3000C' ;! GET MORE POUT_P1=PROCESS SCHEDULE(POUT) %IF POUT_P1>EPN %THEN %START ;! GOT SOME MORE EPLIM=POUT_P1 PARTALLOC=POUT_P2 %IF PROCMON#0 %THEN PMON("MORE ALLOC ".STRINT(EPLIM)." ") ->ACTIVATE %FINISH POUT_DEST=X'3000D' ;! WAIT FOR MORE POUT_P1=PROCESS SCHEDULE(POUT) %IF POUT_P1=0 %THEN ->RETURN %ELSE ->DEAD %FINISH %IF PROCMON#0 %THEN PMON("EPAGES LIMIT ") %IF XSTROBE=0 %THEN %START STROBE(1) ? XSTRN=XSTRN+1 ? XSTREP=XSTREP+EPLIM-EPN %IF EPNACTIVATE ;! GOT SOME BACK ! %FINISH %IF EPLIM#MAXEPAGES %THEN %START POUT_DEST=X'3000A' ;! MORE EPAGES ON THE FLY ? POUT_SRCE=0 POUT_P1=PROCESS POUT_P2=RTN SCHEDULE(POUT) %IF POUT_P1#0 %THEN %START EPLIM=POUT_P1 RTLIM=POUT_P2 %IF PROCMON#0 %THEN PMON("CATEGORY ".STRINT(EPLIM)."/". %C STRINT(RTLIM)."(ON FLY) ") RTN=0 ->ACTIVATE %FINISH %FINISH WORKSET POUT_DEST=X'30003' ;! OUT OF EPAGES POUT_SRCE=ME!1 POUT_P1=PROCESS POUT_P2=RTN ;! TIMESLICES USED SO FAR PON(POUT) ->RETURN !----------------------------------------------------------------------- ACTIVITY(7):! MORE ALLOCATION AVAILABLE EPLIM=P_P1 PARTALLOC=P_P2 %IF PROCMON#0 %THEN PMON("WAIT ALLOC ".STRINT(EPLIM)." ") ->ACTIVATE !----------------------------------------------------------------------- PROGERRI:*JLK_%TOS ! PROGRAM ERROR INTERRUPTS ENTER HERE *LSS_%TOS *LSS_%TOS *ST_PEPARM PE:%IF PROCMON#0 %THEN PMON(PROGERR) SIGOUTP_P1=PEPARM SIGOUTP_P2=PROC_STACK SIGOUTP_TYPE=2 SIGOUTP_SSN=CURSSN SIGOUTP_SSNAD=PROC_STACK SIGOUTP_SUSP=0 NEWSTK=LSTKSSN(2)<<18 %IF PROC_STACK=NEWSTK %THEN %START PRINT STRING(PROGERR."PROGRAM ERROR ON SIGNAL STACK ") ->TERMINATE %FINISH LONG INTEGER(NEWSTK!X'40014')=LONG INTEGER(PROC_STACK!X'40014') PROC_STACK=NEWSTK SSNP1==RECORD(NEWSTK!X'40000') %IF SSNP1_LNB>>18#NEWSTK>>18 %OR SSNP1_LNB>>18#SSNP1_SF>>18 %C %OR SSNP1_PSR&3=0 %THEN PRINT STRING(" ACTIVATE CONTEXT INVALID") %AND ->TERMINATE ->ACTIVATE !----------------------------------------------------------------------- OUTI:*JLK_%TOS ! LOCAL OUTS ENTER HERE *LSS_%TOS *ST_J *LSS_%TOS *ST_I %IF 0<=I<=MAXDIROUT %THEN %START %IF INTEGER(J!X'40004')>>20&X'F'<=MAXOUTACR %THEN ->DIROUT(I) %FINISH FREACT:DIROUTP_DEST=-1 ;! OUT INVALID ->ACTIVATE REACT:DIROUTP_DEST=0 ;! OUT VALID ->ACTIVATE !----------------------------------------------------------------------- TERMINATE:DUMP TABLE(PROCESS,NEWSTK!X'40000',72) ! CREATE DUMMY STOPPING MESSAGE TO DIRECT DIROUTP_P1=PROCESS DIROUTP_P2=PROC_INCAR STRING(ADDR(DIROUTP_P3))=PROC_USER DIROUT(0):%IF PROCMON#0 %THEN PMON( %C "STOPPED ") %WHILE ABTT#255 %THEN ABTOUT(ABTT) ;! RETURN ALL ABTS RETURN PTS DIROUTP_DEST=(LOCSN1+1)<<16!X'17' ;! DIRECT=PROCESS 1 ! X'17' NOT YET PARAMETERISED !!! PON(DIROUTP) POUT_DEST=X'30008' ;! SCHEDULE/DESTROY POUT_SRCE=ME POUT_P1=PROCESS PON(POUT) ->RETURN !----------------------------------------------------------------------- DIROUT(1):! PRINT STRING FOR DIRECTOR %IF DIROUTP_DEST>>24>31 %THEN ->FREACT PRINT STRING(STRING(ADDR(DIROUTP_DEST))) ->REACT !----------------------------------------------------------------------- DIROUT(2):! INPUT REQUEST MESSAGE %IF DIROUTP_P3#IOSTAT_IAD %THEN ->ACTIVATE ;! INPUT ALREADY HERE POUT=DIROUTP POUT_DEST=X'00370006' POUT_SRCE=LSN3<<16!1 PON(POUT) SRCE=X'80000000'!LSN3 ;! TOP BIT SET FOR INPUT WAIT ->SUSPWS !----------------------------------------------------------------------- DIROUT(3):! DISCONNECT SEGMENT, DIROUTP_P1=SEG, P2#0 DESTROY VSSEG=DIROUTP_P1 ->FREACT %UNLESS 0<=VSSEGFREACT %IF CBTX=255 %IF DIROUTP_P2#0 %THEN ABTDESTROY=1 %UNTIL CBTX=255 %CYCLE CBT==CBTA(CBTX) %IF CBT_TAGS&X'20'#0 %THEN ABTOUT(CBT_ABTX) CBTX=CBT_LINK %REPEAT ABTDESTROY=0 LST(VSSEG)=LST(VSSEG)&X'FFFFFFFF00000000' ->REACT !----------------------------------------------------------------------- DIROUT(4):! DISCONNECT BLOCK, DIROUTP_P1=CBTX CBTX=DIROUTP_P1 ->FREACT %UNLESS 0<=CBTX<=254 CBT==CBTA(CBTX) ->FREACT %UNLESS CBT_TAGS&X'20'#0 ABTOUT(CBT_ABTX) ->REACT !----------------------------------------------------------------------- DIROUT(5):! PON FOR DIRECTOR SRCE=PROCESS+LOCSN1 ! USE BYTEINTEGER TO AVOID UNASSIGNED CHECKS DIRPONS:DEST=BYTEINTEGER(DIROUTPAD)<<8!BYTEINTEGER(DIROUTPAD+1) %IF DEST=X'FFFF' %THEN %START ;! RELAY MESSAGE %IF FIND PROCESS=0 %THEN ->ACTIVATE ;! NOT LOGGED ON %FINISH %ELSE %START %UNLESS 0<=DEST<=MAXSERV %THEN ->FREACT %FINISH %IF DEST#0 %THEN %START I=BYTE INTEGER(DIROUTPAD+6)<<8!BYTE INTEGER(DIROUTPAD+7) %IF SRCE=LSN3 %AND (I=0 %OR I=X'FFFF') %THEN ->FREACT DIROUTP_SRCE=SRCE<<16!I PON(DIROUTP) %FINISH POUT_DEST=ME!12 ->ONFRUNQA !----------------------------------------------------------------------- ACTIVITY(12):! RE-ENTRY AFTER DIRECTOR PON %IF SRCE>LOCSN3 %THEN %START %IF SERV3_P<<1#0 %THEN ->ASYNCH %FINISH %ELSE %START SERV==SERVA(SRCE) %IF SERV_P<<1#0 %THEN SUPPOFF(SERV,DIROUTP) %AND ->ACTIVATE %FINISH SUSPWS:WORKSET POUT_DEST=X'30005' ;! SUSPEND POUT_SRCE=SRCE&X'7FFFFFFF' ;! TO UNINHIBIT SRCE IN "SCHEDULE" POUT_P1=PROCESS POUT_P2=WSN ;! EPAGES USED SO FAR PON(POUT) SUSP=SRCE %IF PROC_STACK=LSTKSSN(2)<<18 %THEN PRINT STRING(" SUSPENDED IN SIGNAL STATE") %AND NEWSTK=LSTKSSN(2)<<18 %AND ->TERMINATE ->RETURN !----------------------------------------------------------------------- DIRPONREPLY:! REPLY HAS WOKEN PROCESS UP SERV==SERVA(SUSP) DPR:SUPPOFF(SERV,DIROUTP) SUSP=0 ->ACTIVATE !----------------------------------------------------------------------- DIROUT(6):! PON & CONTINUE SRCE=PROCESS+LOCSN1 DIRPONC:DEST=BYTEINTEGER(DIROUTPAD)<<8!BYTEINTEGER(DIROUTPAD+1) %IF DEST=X'FFFF' %THEN %START %IF FIND PROCESS=0 %THEN ->ACTIVATE %FINISH %ELSE %START %UNLESS 0<=DEST<=MAXSERV %THEN ->FREACT %FINISH %IF DEST#0 %THEN %START %IF DIROUTP_DEST=X'00810017' %THEN ->ACTIVATE ;! THROW AWAY I=BYTE INTEGER(DIROUTPAD+6)<<8!BYTE INTEGER(DIROUTPAD+7) %IF SRCE=LSN3 %AND (I=0 %OR I=X'FFFF') %THEN ->FREACT DIROUTP_SRCE=SRCE<<16!I PON(DIROUTP) ->ONFRUNQ %FINISH ! TOFF %IF SRCE>LOCSN3 %THEN %START %IF SERV3_P<<1#0 %THEN ->ASYNCH %ELSE DIROUTP_DEST=0 %FINISH %ELSE %START SERV==SERVA(SRCE) %IF SERV_P<<1#0 %THEN SUPPOFF(SERV,DIROUTP) %ELSE DIROUTP_DEST=0 %FINISH ->ACTIVATE !---------------------------------------------------------------------- DIROUT(7):! ALTERNATE PON FOR DIRECTOR SRCE=PROCESS+LOCSN2 ->DIRPONS !----------------------------------------------------------------------- DIROUT(8):! ALT PON & CONTINUE SRCE=PROCESS+LOCSN2 ->DIRPONC !----------------------------------------------------------------------- DIROUT(9):! ASYNCHRONOUS REPLY PON & SUSPEND SRCE=LSN3 ->DIRPONS !----------------------------------------------------------------------- DIROUT(10):! ASYNCHRONOUS REPLY PON & CONTINUE SRCE=LSN3 ->DIRPONC !----------------------------------------------------------------------- DIROUT(11):! PON & WAIT PONWAIT:DEST=BYTE INTEGER(DIROUTPAD)<<8!BYTE INTEGER(DIROUTPAD+1) %UNLESS 0FREACT SRCE=DIROUTP_SRCE DIROUTP_SRCE=ME!13 PON(DIROUTP) ->RETURN ;! WAIT IN STORE FOR REPLY !----------------------------------------------------------------------- ACTIVITY(13):! PON & WAIT REPLY DIROUTP=P DIROUTP_DEST=SRCE I=PROC_STACK+X'40014' INTEGER(I)=INTEGER(I)-OUT18CHARGE INTEGER(I+4)=INTEGER(I+4)-OUT18INS %IF PROCMON#0 %THEN PMON("PON&WAITREPLY:") %C %AND PTREC(DIROUTP) ->ACTIVATE !----------------------------------------------------------------------- DIROUT(12):! NOMINATE STACK SSN I=DIROUTP_P1 ;! STACK NO J=DIROUTP_P2 ;! SSN %UNLESS 1<=I<=LSTKN %AND LSTKSSN(I)=0 %AND 4<=JFREACT LSTKSSN(I)=J LST(J!1)=LST(1)+I*X'80' ->REACT !----------------------------------------------------------------------- DIROUT(13):! DENOMINATE STACK I=DIROUTP_P1 ;! STACK NO %UNLESS 1<=I<=LSTKN %THEN ->FREACT J=LSTKSSN(I) ;! SSN %UNLESS 0#J#PROC_STACK>>18 %THEN ->FREACT LST(J!1)=X'1FF3FF8000000000' LSTKSSN(I)=0 ->REACT !----------------------------------------------------------------------- DIROUT(14):! SWOP STACK I=DIROUTP_P1 ;! NEW LOCAL STACK NO K=DIROUTP_P2 SWOPST:%UNLESS 1<=I<=LSTKN %THEN ->FREACT J=LSTKSSN(I) %UNLESS 0#J#PROC_STACK>>18 %THEN ->FREACT SSNP1==RECORD((J!1)<<18) %IF SSNP1_LNB>>18#J %OR SSNP1_LNB>>18#SSNP1_SF>>18 %OR %C SSNP1_PSR&3=0 %THEN ->FREACT NEWSTK=J<<18 ! SWOP IT & IC LONG INTEGER(NEWSTK!X'40014')=LONG INTEGER(PROC_STACK!X'40014') PROC_STACK=NEWSTK SUSP=K ;! GO BACK TO CORRECT SUSPEND STATUS ->RESUSP !----------------------------------------------------------------------- DIROUT(15):! SYSTEM CALL ERROR (AFTER STACK SWITCH) PEPARM=INTEGER(PROC_STACK!X'40020')<<6!16 ;! SUB-IDENT. IN OLD XNB ->PE !----------------------------------------------------------------------- DIROUT(16):! INSTRUCTION COUNTER INTERRUPT (AFTER STACK SWITCH) PEPARM=17 ;! TREAT AS PROGRAM ERROR ->PE !----------------------------------------------------------------------- DIROUT(17):! CHECK FOR ACTIVE BLOCKS ON FILE DESTROY J=0 PA==DIROUTP %CYCLE I=0,1,7 RECHECK:K=PA_P(I) %IF K=0 %THEN %EXIT POUT_DEST=X'80005' POUT_P1=K ACTIVE MEM(POUT) %IF POUT_DEST#0 %THEN %START %IF J=10 %THEN MONITOR("BLOCK PAGE-OUTS ?") WAIT(14,PAGEOUT DELAY(J)) ->RETURN %FINISH %REPEAT ->REACT !----------------------------------------------------------------------- ACTIVITY(14):! REPLY FROM DESTROY CHECK J=J+1 ->RECHECK !----------------------------------------------------------------------- DIROUT(18):! CHECK & FORWARD PRIVATE I-O REQUEST ! P5=WRIT<<31!ACR<<24!LEN ! P6=ADDRESS %IF CHECK RES(DIROUTP_P5>>31,DIROUTP_P5&X'FFFFFF',DIROUTP_P6)#0 %C %THEN ->FREACT ;! NOT RESIDENT DIROUTP_P5=ACTW0!DIROUTP_P5<<4>>28 ;! LSTBR!ACR DIROUTP_P6=ACTW1 ->PONWAIT !------------------------------------------------------------------- DIROUT(19):! SWOP STACK FROM SIGNAL STACK I=SIGOUTP_P1 K=SIGOUTP_P2 ->SWOPST !----------------------------------------------------------------------- DIROUT(20):! PROCMON ENABLE ! P1=DISC ADDRESS ! P2=K BYTES FILE LENGTH %IF PMONEN#0 %THEN ->FREACT POUT_DEST=X'E0001' POUT_SRCE=PROCESS POUT_P1=DIROUTP_P1 POUT_P2=(DIROUTP_P2-1)//EPAGESIZE+1 PROCMON CONTROL(POUT) %IF POUT_P2<=0 %THEN ->FREACT %ELSE PMONEN=1 %AND ->REACT !----------------------------------------------------------------------- DIROUT(21):! DISABLE PROCMON %IF PMONEN=0 %THEN ->FREACT PROCMON=0 POUT_DEST=X'E0003' POUT_SRCE=PROCESS PROCMON CONTROL(POUT) %IF POUT_DEST=0 %THEN ->RETURN ;! WAIT FOR DISABLE COMPLETION ! RUN ON IF ALREADY COMPLETED !----------------------------------------------------------------------- ACTIVITY(16):! DISABLE COMPLETED PMONEN=0 ->REACT !----------------------------------------------------------------------- DIROUT(22):! PROCMON ON %IF PMONEN=0 %THEN ->FREACT %ELSE PROCMON=1 %AND ->REACT !----------------------------------------------------------------------- DIROUT(23):! PROCMON OFF PROCMON=0 ->REACT !----------------------------------------------------------------------- DIROUT(24):! PROCMON INSERT TEXT ! STRING(ADDR(P1))=TEXT %IF PMONEN=0 %THEN ->FREACT PMON(STRING(ADDR(DIROUTP_P1))) ->REACT !----------------------------------------------------------------------- DIROUT(25):! LOCK IO AREA AND RETURN SEG TABLE. P_P5/P_P6=DESCR TO AREA. DIROUTP_P5=DIROUTP_P5&X'FFFFFF'; ! P_P1=1 LOCK ,=-1 UNLOCK %IF CHECK RES(0,DIROUTP_P5,DIROUTP_P6)#0 %THEN ->FREACT %IF LOCKST=0 %THEN %START; ! NO SEG TABLE AROUND ->FREACT %UNLESS DIROUTP_P1>0 POUT_DEST=X'50001' ;! LOW PRIORITY POUT_SRCE=ME!X'8000000F' POUT_P2=0 ;! CLEAR TO ZERO ? *LSS_(6) ;? *ST_IC ;? *LSS_(5) ;? *ST_IT GET EPAGE(POUT) ? *LSS_(5) ;? *ST_ITT ;? *LSS_(6) ;? *ST_ICC ? GETIT=GETIT+IT-ITT ;? LCIT=LCIT-IT+ITT ? GETIC=GETIC+IC-ICC ;? LCIC=LCIC-IC+ICC ? GETCALLN=GETCALLN+1 %IF POUT_DEST#0 %THEN STOREX=POUT_P2 %AND ->ACTF %ELSE ->RETURN !----------------------------------------------------------------------- ACTIVITY(15):! REPLY FROM GET EPAGE FOR LOCKED SEG TABLE STOREX=P_P2 ACTF:LOCKSTX=STOREX LOCKST=STORE(STOREX)_REALAD K=LOCKST!VIRTAD J=8*LSTLEN; ! USE REST OF EPAGE AS PAGETABLES INTEGER(K+4)=J; ! HEAD OF PT LIST(F BIT NOT SET!) %WHILE J<=1024*(EPAGESIZE-2) %CYCLE INTEGER(K+J)=J+1024 J=J+1024 %REPEAT %FINISH %ELSE K=LOCKST&X'0FFFFFF0'!VIRTAD VSSEG=DIROUTP_P6>>18 %IF DIROUTP_P1>0 %START; ! LOCK AREA %IF LONGINTEGER(K+8*VSSEG)#0 %THEN ->FREACT;! SEG LOCKED ALREADY %IF INTEGER(K+4)=0 %THEN ->FREACT;! ALL PAGETABLES USED LTAD=K+INTEGER(K+4); ! VIRT AD OF PAGETABLE INTEGER(K+4)=INTEGER(LTAD) LOCKST=LOCKST+(1<<28); ! KEEP COUNT IN TOP 4 BITS LONGINTEGER(K+8*VSSEG)=LST(VSSEG)&X'FFFFFFFF80000001' %C !(LTAD&X'00FFFFF0') %FINISH %ELSE %START; ! UNLOCK AREA %IF LONGINTEGER(K+8*VSSEG)=0 %THEN ->FREACT LTAD=(INTEGER(K+8*VSSEG+4)&X'0FFFFFF0'!VIRTAD) INTEGER(LTAD)=INTEGER(K+4) INTEGER(K+4)=LTAD-K LONGINTEGER(K+8*VSSEG)=0 LOCKST=LOCKST-1<<28 %IF LOCKST>>28=0 %START POUT_P2=LOCKSTX P_SRCE=ME!15 RETURN EPAGE(POUT) LOCKST=0 %FINISH %FINISH PT==ARRAY(VIRTAD!LST(VSSEG)&X'0FFFFFF8',PTF) J=DIROUTP_P6-VSSEG<<18 %CYCLE I=J>>10,1,(J+DIROUTP_P5-1)>>10 %IF DIROUTP_P1>0 %THEN K=PT(I) %ELSE K=0 INTEGER(LTAD+4*I)=K %REPEAT %CYCLE VSEPAGE=(J>>10)//EPAGESIZE,1,((J+DIROUTP_P5-1)>>10)//EPAGESIZE CBTP=SST(VSSEG) CBT==CBTA(CBTP) EPX=VSEPAGE %WHILE EPX>CBT_TAGS&X'F' %CYCLE CBTP=CBT_LINK EPX=EPX-CBT_TAGS&X'F'-1 CBT==CBTA(CBTP) %REPEAT ABT==ABTA(CBT_ABTX) %IF DIROUTP_P1>0 %START POUT_DEST=X'40001'; ! PAGE IN AGAIN TO LOCK POUT_SRCE=ME!X'8000000A' POUT_P3=0 %FINISH %ELSE %START POUT_DEST=X'40002'; ! PAGE OUT TO UNLOCK POUT_SRCE=0 POUT_P2=8+4; ! WRITTEN TO+UPDATE DRUM %FINISH POUT_P1=ABT_AMTX<<16!EPX PAGETURN(POUT) %IF POUT_DEST=0 %AND DIROUTP_P1>0 %THEN MONITOR("LOCK GOES WRONG?") %REPEAT DIROUTP_P5=ACTW0 DIROUTP_P6=LOCKST&X'0FFFFFF0' ->REACT !----------------------------------------------------------------------- DIROUT(26):! CHANGE CONTEXT CLEAR ACCESSED BITS XSTROBE=0 ->ACTIVATE !----------------------------------------------------------------------- EPI:*JLK_%TOS ! EVENT PENDING INTERRUPTS ENTER HERE - FROM 'SYSTEM ERROR' PEPARM=20 ->PE !----------------------------------------------------------------------- ICOUNTERI:*JLK_%TOS ! INSTRUCTION COUNTER INTERRUPTS ENTER HERE - STACK NOT SWITCHED YET !!! ! ICREVS=ICREVS-1 ! %IF ICREVS<0 %THEN PROGERR(17) *STXN_%TOS ;! SAVE XNB *LXN_X'14006C' ;! ADDR(ICREVS) *SLB_(%XNB+0) ;! SAVE B & LOAD ICREVS *SBB_1 *STB_(%XNB+0) *CPB_0 *LB_%TOS ;! RESTORE B & XNB *LXN_%TOS *JCC_11, ;! JUMP IF B>=0 *OUT_16 ;! TO SWITCH STACKS OUT16:*EXIT_-1 ;! TO RESTORE PM,CC,ACS ETC. ! SIGNAL MECHANISM INVOKED AT DIROUT(16): !----------------------------------------------------------------------- %INTEGERFN CHECK RES(%INTEGER WRIT,LEN,AD) %INTEGER I,J %INTEGERARRAYNAME PT %CYCLE I=AD>>10,1,(AD+LEN-1)>>10 PT==ARRAY(VIRTAD!(LST(I>>8)&X'0FFFFFF8'),PTF) J=I&X'FF' %IF PT(J)&1=0 %THEN %RESULT=1 PT(J)=PT(J)!WRIT<<28 %REPEAT %RESULT=0 %END !----------------------------------------------------------------------- %ROUTINE CONNECT(%INTEGER SEG,DA,LEN,ACC) ! FILE ASSUMED "NEW" IF NOT EXECUTE ACCESS !! %LONGINTEGER LL %INTEGER CELL,L,X SST(SEG)=CBTASL LL=X'40000380'!ACC<<20!(LEN*EPAGESIZE-1)<<10 LST(SEG)=LL<<32 X=ACC>>8 %WHILE LEN>0 %CYCLE CELL=CBTASL CBT==CBTA(CELL) CBTASL=CBT_LINK CBT_DA=DA DA=DA+MAXBLOCK %IF LEN>MAXBLOCK %THEN L=MAXBLOCK %ELSE L=LEN LEN=LEN-MAXBLOCK %IF X=0 %THEN CBT_ABTX=X'FF' %AND CBT_MASK2=X'FF' %C %ELSE CBT_ABTX=0 %AND CBT_MASK2=0 CBT_TAGS=X<<4!(L-1) CBT_LINK=CBTASL %REPEAT CBT_LINK=255 %END !----------------------------------------------------------------------- %ROUTINE PUSHEP(%BYTEINTEGERNAME LP,%INTEGER X) %RECORDNAME EP(EPF) %INTEGER CELL CELL=EPASL EP==EPA(CELL) EPASL=EP_LINK EP_ST=X>>8 EP_X=X&X'FF' EP_LINK=LP LP=CELL EPN=EPN+1 %END !----------------------------------------------------------------------- %ROUTINE POPEP(%BYTEINTEGERNAME LP) %RECORDNAME EP(EPF) %INTEGER CELL CELL=LP EP==EPA(CELL) LP=EP_LINK EP_LINK=EPASL EPASL=CELL EPN=EPN-1 %END !----------------------------------------------------------------------- %ROUTINE ABTOUT(%INTEGER ABTX) %RECORDNAME CBT(CBTF) %RECORDNAME ABT(ABTF) %RECORDNAME EP(EPF) %INTEGERARRAYNAME PT %INTEGER PAGE,MARK,STEP,AMTX,MASK,SEPX,POFL,I %STRING(3) STRSEG,STRU ABT==ABTA(ABTX) %IF PROCMON#0 %THEN PMON("RETURN AMTX ".STRHEX(CBTA(ABT_CBTX)_DA)." ") PT==ARRAY(VIRTAD!LST(ABT_SEG)&X'0FFFFFF8',PTF) STEP=ABT_STEP AMTX=ABT_AMTX %WHILE ABT_LINK#255 %CYCLE EP==EPA(ABT_LINK) SEPX=STEP+EP_X PAGE=SEPX*EPAGESIZE !MARK=0 !%CYCLE I=PAGE,1,PAGE+EPAGESIZE-1 ! MARK=MARK!PT(I) ;! GANG MARKERS TOGETHER ! PT(I)=0 ;! MARK PAGE AS UNAVAILABLE !%REPEAT ! ASSUMES EPAGESIZE=4 I=ADDR(PT(PAGE)) *LXN_I *LSS_(%XNB+0) *OR_(%XNB+1) *OR_(%XNB+2) *OR_(%XNB+3) *ST_MARK *LDTB_X'38000001' *LDA_I *LSQ_0 *ST_(%DR) %IF ABTDESTROY=0 %THEN POFL=MARK<<3>>31<<3 %ELSE POFL=0 %IF PROCMON#0 %THEN %START STRSEG=STRINT(ABT_SEG) STRU=EPUSE(MARK>>28&3) PMON(" ".STRSEG."/".STRINT(SEPX).STRU) %FINISH POUT_DEST=X'40002' ;! PAGETURN/PAGE-OUT POUT_P1=AMTX<<16!EP_X POUT_P2=POFL ? *LSS_(6) ;? *ST_IC ;? *LSS_(5) ;? *ST_IT PAGETURN(POUT) ? *LSS_(5) ;? *ST_ITT ;? *LSS_(6) ;? *ST_ICC ? PTIT=PTIT+IT-ITT ;? LCIT=LCIT-IT+ITT ? PTIC=PTIC+IC-ICC ;? LCIC=LCIC-IC+ICC ? PTCALLN=PTCALLN+1 %IF MARK>>28&1#0 %THEN ACNT_PTURNS=ACNT_PTURNS+1 POPEP(ABT_LINK) %REPEAT POUT_DEST=X'80002' ;! RETURN AMTX POUT_SRCE=0 POUT_P1=PROCESS POUT_P2=AMTX ? *LSS_(6) ;? *ST_IC ;? *LSS_(5) ;? *ST_IT ACTIVE MEM(POUT) ? *LSS_(5) ;? *ST_ITT ;? *LSS_(6) ;? *ST_ICC ? AMIT=AMIT+IT-ITT ;? LCIT=LCIT-IT+ITT ? AMIC=AMIC+IC-ICC ;? LCIC=LCIC-IC+ICC ? AMCALLN=AMCALLN+1 MASK=POUT_P1 ;! RETAIN "NEW" BIT MASK CBT==CBTA(ABT_CBTX) CBT_ABTX=MASK>>24 CBT_MASK2=MASK>>16&X'FF' CBT_TAGS=CBT_TAGS&X'DF' ! REMOVE ABT %UNLESS ABT_PREV=255 %THEN ABTA(ABT_PREV)_NEXT=ABT_NEXT %C %ELSE ABTT=ABT_NEXT %UNLESS ABT_NEXT=255 %THEN ABTA(ABT_NEXT)_PREV=ABT_PREV %C %ELSE ABTB=ABT_PREV ABT_LINK=ABTASL ;! RETURN ABT CELL ABTASL=ABTX ABTN=ABTN-1 %IF PROCMON#0 %THEN PMON(" ") %END !----------------------------------------------------------------------- %ROUTINE STROBE(%INTEGER KEEPUSE) %RECORDNAME ABT(ABTF) %RECORDNAME EP(EPF) %INTEGERARRAYNAME PT %INTEGER ABTX,PAGE,STEP,AMTX,MARK,POFL,SEPX,USEMASK,I %STRING(3) STRSEG,STRU %BYTEINTEGERNAME EPL %IF PROCMON#0 %THEN PMON("STROBE-OUT:") %IF KEEPUSE=0 %THEN USEMASK=X'DFFFFFFF' %ELSE USEMASK=X'FFFFFFFF' ABTX=ABTT %WHILE ABTX#255 %CYCLE ;! FOR EACH ACTIVE BLOCK ABT==ABTA(ABTX) PT==ARRAY(VIRTAD!LST(ABT_SEG)&X'0FFFFFF8',PTF) STEP=ABT_STEP AMTX=ABT_AMTX EPL==ABT_LINK %WHILE EPL#255 %CYCLE ;! FOR EACH ACTIVE PAGE EP==EPA(EPL) SEPX=STEP+EP_X PAGE=SEPX*EPAGESIZE !MARK=0 !%CYCLE I=PAGE,1,PAGE+EPAGESIZE-1 ! MARK=MARK!PT(I) ;! GANG MARKERS TOGETHER ! PT(I)=PT(I)&USEMASK !%REPEAT ! ASSUMES EPAGESIZE=4 I=ADDR(PT(PAGE)) *LXN_I *LSS_(%XNB+0) *OR_(%XNB+1) *OR_(%XNB+2) *OR_(%XNB+3) *ST_MARK *LSS_(%XNB+0) *AND_USEMASK *ST_(%XNB+0) *LSS_(%XNB+1) *AND_USEMASK *ST_(%XNB+1) *LSS_(%XNB+2) *AND_USEMASK *ST_(%XNB+2) *LSS_(%XNB+3) *AND_USEMASK *ST_(%XNB+3) POFL=MARK<<3>>31<<3!1<<2 %IF MARK>>29&1=0 %THEN %START ;! STROBE OUT %IF PROCMON#0 %THEN %START STRSEG=STRINT(ABT_SEG) STRU=EPUSE(MARK>>28&3) PMON(" ".STRSEG."/".STRINT(SEPX).STRU) %FINISH POUT_DEST=X'40002' ;! PAGETURN/PAGE-OUT POUT_P1=AMTX<<16!EP_X POUT_P2=POFL ? *LSS_(6) ;? *ST_IC ;? *LSS_(5) ;? *ST_IT PAGETURN(POUT) ? *LSS_(5) ;? *ST_ITT ;? *LSS_(6) ;? *ST_ICC ? PTIT=PTIT+IT-ITT ;? LCIT=LCIT-IT+ITT ? PTIC=PTIC+IC-ICC ;? LCIC=LCIC-IC+ICC ? PTCALLN=PTCALLN+1 %IF MARK>>28&1#0 %THEN ACNT_PTURNS=ACNT_PTURNS+1 !%CYCLE I=PAGE,1,PAGE+EPAGESIZE-1 ! PT(I)=0 !%REPEAT ! ASSUMES EPAGESIZE=4 I=ADDR(PT(PAGE)) *LDTB_X'38000001' *LDA_I *LSQ_0 *ST_(%DR) POPEP(EPL) %FINISH %ELSE EPL==EP_LINK %REPEAT ABTX=ABT_NEXT %REPEAT XSTROBE=1 %IF PROCMON#0 %THEN PMON(" ") %END !----------------------------------------------------------------------- %ROUTINE WORKSET %RECORDNAME ABT(ABTF) %RECORDNAME EP(EPF) %INTEGERARRAYNAME PT %INTEGER ABTX,PAGE,MARK,STEP,AMTX,POFL,SEPX,I %STRING(3) STRSEG,STRU %BYTEINTEGERNAME EPL %IF PROCMON#0 %THEN PMON("PAGE-OUT:") WSN=EPN ABTX=ABTT %WHILE ABTX#255 %CYCLE ABT==ABTA(ABTX) PT==ARRAY(VIRTAD!LST(ABT_SEG)&X'0FFFFFF8',PTF) STEP=ABT_STEP AMTX=ABT_AMTX EPL==ABT_LINK %WHILE EPL#255 %CYCLE EP==EPA(EPL) SEPX=STEP+EP_X PAGE=SEPX*EPAGESIZE !MARK=0 !%CYCLE I=PAGE,1,PAGE+EPAGESIZE-1 ! MARK=MARK!PT(I) ;! GANG MARKERS TOGETHER !%REPEAT ! ASSUMES EPAGESIZE=4 I=ADDR(PT(PAGE)) *LXN_I *LSS_(%XNB+0) *OR_(%XNB+1) *OR_(%XNB+2) *OR_(%XNB+3) *ST_MARK POFL=MARK<<3>>31<<3!1<<2 ;! WRIT & UPDATE DRUM %IF PROCMON#0 %THEN %START STRSEG=STRINT(ABT_SEG) STRU=EPUSE(MARK>>28&3) PMON(" ".STRSEG."/".STRINT(SEPX).STRU) %FINISH POUT_DEST=X'40002' ;! PAGETURN/PAGE-OUT POUT_P1=AMTX<<16!EP_X POUT_P2=POFL ? *LSS_(6) ;? *ST_IC ;? *LSS_(5) ;? *ST_IT PAGETURN(POUT) ? *LSS_(5) ;? *ST_ITT ;? *LSS_(6) ;? *ST_ICC ? PTIT=PTIT+IT-ITT ;? LCIT=LCIT-IT+ITT ? PTIC=PTIC+IC-ICC ;? LCIC=LCIC-IC+ICC ? PTCALLN=PTCALLN+1 %IF MARK>>28&1#0 %THEN ACNT_PTURNS=ACNT_PTURNS+1 %IF MARK>>29&1=0 %THEN WSN=WSN-1 POPEP(EPL) %REPEAT I=ABT_NEXT ! MOVE ABT TO TOP OF LIST IF ANY PAGES IN WS %UNLESS ABT_LINK=255 %OR ABT_PREV=255 %THEN %START ABTA(ABT_PREV)_NEXT=ABT_NEXT %UNLESS ABT_NEXT=255 %THEN ABTA(ABT_NEXT)_PREV=ABT_PREV %C %ELSE ABTB=ABT_PREV ABT_PREV=255 ABT_NEXT=ABTT ABTA(ABTT)_PREV=ABTX ABTT=ABTX %FINISH ABTX=I %REPEAT %IF SEMAHELD#0 %START; ! DEPARTING HOLDING A SEMA PROC_STATUS=PROC_STATUS!1; ! REQUEST PRIORITY ON QS SEMAHELD=0 %FINISH ! REMOVE PT ADDRS !%CYCLE I=2,1,HIGHSEG ! LST(I)=LST(I)&X'FFFFFFFF00000000' !%REPEAT *LD_X'2800000100000014' *LSS_0 *LB_HIGHSEG *SBB_1 RPA:*ST_(%DR) *INCA_8 *DEBJ_ RETURN PTS %IF PROCMON#0 %THEN PMON(" ") %END !----------------------------------------------------------------------- %ROUTINE CLEAR ACCESSED BITS %RECORDNAME ABT(ABTF) %RECORDNAME EP(EPF) %INTEGERARRAYNAME PT %INTEGER ABTX,PAGE,STEP,SEPX,EPL,USEMASK,I %IF PROCMON#0 %THEN PMON("CHANGE CONTEXT ") USEMASK=X'DFFFFFFF' ;! ALL BUT ACCESSED BIT ABTX=ABTT %WHILE ABTX#255 %CYCLE ;! FOR EACH ACTIVE BLOCK ABT==ABTA(ABTX) PT==ARRAY(VIRTAD!LST(ABT_SEG)&X'0FFFFFF8',PTF) STEP=ABT_STEP EPL=ABT_LINK %WHILE EPL#255 %CYCLE ;! FOR EACH ACTIVE PAGE EP==EPA(EPL) SEPX=STEP+EP_X PAGE=SEPX*EPAGESIZE !%CYCLE I=PAGE,1,PAGE+EPAGESIZE-1 ! PT(I)=PT(I)&USEMASK !%REPEAT ! ASSUMES EPAGESIZE=4 I=ADDR(PT(PAGE)) *LXN_I *LSS_(%XNB+0) *AND_USEMASK *ST_(%XNB+0) *LSS_(%XNB+1) *AND_USEMASK *ST_(%XNB+1) *LSS_(%XNB+2) *AND_USEMASK *ST_(%XNB+2) *LSS_(%XNB+3) *AND_USEMASK *ST_(%XNB+3) EPL=EP_LINK %REPEAT ABTX=ABT_NEXT %REPEAT %END !----------------------------------------------------------------------- %ROUTINE RETURN PTS %RECORDNAME EP(EPF) %WHILE PTP#255 %CYCLE EP==EPA(PTP) POUT_P2=(EP_ST<<8!EP_X)&X'FFF' RETURN EPAGE(POUT) POPEP(PTP) %REPEAT %END !----------------------------------------------------------------------- %INTEGERFN FIND PROCESS %STRING(6) USER %INTEGER I,J,K,DACT USER=STRING(PROC_STACK!X'40030') ;! IN OLD ACC J=INTEGER(PROC_STACK!X'4003C') %IF 1<=J<=3 %THEN %START %IF J=1 %THEN K=LOCSN1 %ELSE %START %IF J=2 %THEN K=LOCSN2 %ELSE K=LOCSN3 %FINISH DACT=BYTE INTEGER(DIROUTPAD+2)<<8!BYTE INTEGER(DIROUTPAD+3) %UNLESS J=3 %AND (DACT=0 %OR DACT=X'FFFF') %THEN %START %CYCLE I=1,1,MAXPROCS %IF USER=PROCA(I)_USER %THEN DIROUTP_DEST=(I+K)<<16!DACT %C %AND %RESULT=I %REPEAT %FINISH %FINISH DIROUTP_DEST=0 %RESULT=0 %END !----------------------------------------------------------------------- %INTEGERFN CURSSN %INTEGER I,J J=PROC_STACK>>18 %CYCLE I=1,1,LSTKN %IF J=LSTKSSN(I) %THEN %RESULT=I %REPEAT MONITOR("CURRENT STACK ?") %END !----------------------------------------------------------------------- %STRING(255)%FN VSINT %CONSTSTRING(1)%ARRAY ACC(0:3)="W"(2),"R","E" %CONSTSTRING(11)%ARRAY CAUSE(0:7)="SEG>LIMIT ","SEG-FLT ","SEG LIMIT ", "PAGE>LIMIT ","PAGE-FLT ","??? "(3) %CONSTSTRING(4)%ARRAY APF(0:1)=""," APF" %CONSTSTRING(4)%ARRAY INT(0:1)=""," INT" %RESULT=CAUSE(VSPARM&7).STRINT(VSPARM>>18). %C "/".STRINT((VSPARM>>10&X'FF')//EPAGESIZE).ACC(VSPARM>>5&3). %C APF(VSPARM>>4&1).INT(VSPARM>>3&1)." " %END !----------------------------------------------------------------------- %STRING(255)%FN PROGERR %CONSTSTRING(23)%ARRAY CAUSE(0:20)="FLOATING PT OVERFLOW", "FLOATING PT UNDERFLOW","FIXED PT OVERFLOW","DECIMAL OVERFLOW", "ZERO DIVIDE","BOUND CHECK","SIZE","B OVERFLOW","STACK","PRIVILEGE", "DESCRIPTOR","STRING","INSTRUCTION","ACCUMULATOR","ESR ERRORS","???", "SYSTEM CALL","INSTRN COUNTER","DISC READ FAIL","CHANGE BLOCK SIZE", "SYSTEM ERROR" %CONSTSTRING(11)%ARRAY RES(0:1)=""," NO RESTART" %RESULT=CAUSE(PEPARM&X'1F')."/".STRINT(PEPARM>>8&X'FF').%C RES(PEPARM>>7&1)." " %END !----------------------------------------------------------------------- %ROUTINE WAIT(%INTEGER DACT,N) POUT_DEST=X'A0002' POUT_SRCE=0 POUT_P1=ME!DACT POUT_P2=N PON(POUT) %END !----------------------------------------------------------------------- %ROUTINE PMON(%STRING(63) S) %RECORD PMONP(PARMF) %INTEGER I,J I=1 %CYCLE J=I+22 %IF LENGTH(S)ACT(DACT) !----------------------------------------------------------------------- ACT(1):! ENABLE CHANNEL EPLEN=P_P2 GET AMTX(P_P1,X'FFFF0000'!(EPLEN-1)) %IF P_P2<=0 %THEN %RETURN CHAN(PROCESS)=NEWPPCELL CH==PARM(CHAN(PROCESS)) CH=0 CH_AMTX=P_P2 CH_LEN=EPLEN*EPAGESIZE<<10 CH_CUR=32 %RETURN !----------------------------------------------------------------------- ACT(2):! APPEND TEXT %IF CH_LINK#0 %THEN %START %IF CH_PPCS>=128 %THEN ->FAIL STRAD=ADDR(PARM(CH_LAST)_DEST) S=STRING(STRAD).STRING(ADDR(P_P1)) %IF LENGTH(S)<=31 %THEN STRING(STRAD)=S %ELSE %START STRING(STRAD)=FROMSTRING(S,1,31) PPC=NEWPPCELL PARM(CH_LAST)_LINK=PPC STRING(ADDR(PARM(PPC)_DEST))=FROMSTRING(S,32,LENGTH(S)) PARM(PPC)_LINK=0 CH_LAST=PPC CH_PPCS=CH_PPCS+1 %FINISH %RETURN %FINISH PPC=NEWPPCELL STRING(ADDR(PARM(PPC)_DEST))=STRING(ADDR(P_P1)) PARM(PPC)_LINK=0 CH_LINK=PPC CH_LAST=PPC CH_PPCS=1 NEXTPAGE:CH_EPX=CH_CUR//EPAGESIZE<<10 PAGEIN(CH_EPX,4) %IF P_DEST=0 %THEN %RETURN ACT(4):REALAD=P_P2 APPEND:PPC=CH_LINK S=STRING(ADDR(PARM(PPC)_DEST)) SPACE=(CH_EPX+1)*EPAGESIZE<<10-CH_CUR %IF LENGTH(S)>SPACE %THEN %START COPY(FROMSTRING(S,1,SPACE)) STRING(ADDR(PARM(PPC)_DEST))=FROMSTRING(S,SPACE+1,LENGTH(S)) PAGEOUT(CH_EPX) ->NEXTPAGE %FINISH COPY(S) CH_LINK=PARM(PPC)_LINK RETURNPPCELL(PPC) CH_PPCS=CH_PPCS-1 %IF LENGTH(S)=SPACE %OR CH_LINK=0 %THEN %START PAGEOUT(CH_EPX) %IF CH_LINK#0 %THEN ->NEXTPAGE CH_LAST=0 %IF CH_DISABLE#0 %THEN ->DISABLE %ELSE %RETURN %FINISH %ELSE ->APPEND !----------------------------------------------------------------------- ACT(3):! DISABLE CHANNEL CH_DISABLE=1 %IF CH_LINK#0 %THEN P_DEST=0 %AND CH_WAIT=1 %AND %RETURN DISABLE:PAGEIN(0,6) %IF P_DEST=0 %THEN CH_WAIT=1 %AND %RETURN ACT(6):HEADER==RECORD(VIRTAD!P_P2) HEADER_CURP=CH_LEN HEADER_DATA=32 HEADER_MAX=CH_LEN HEADER_CYCP=CH_CUR PAGEOUT(0) %IF CH_WAIT#0 %THEN %START P_DEST=(PROCESS+LOCSN0)<<16!16 P_SRCE=X'E0003' PON(P) %FINISH RETURN AMTX(CH_AMTX) RETURNPPCELL(CHAN(PROCESS)) CHAN(PROCESS)=0 P_DEST=1 %RETURN !----------------------------------------------------------------------- ACT(5):ACT(7):FAIL:! PAGE IN FAILURE P_DEST=(PROCESS+LOCSN0)<<16 P_P1=3 PON(P) ;! ASYNCH MESSAGE TO LOCAL CONTROLLER %UNTIL CH_LINK=0 %THEN PPC=PARM(CH_LINK)_LINK %AND %C RETURNPPCELL(CH_LINK) %AND CH_LINK=PPC PPC=NEWPPCELL STRING(ADDR(PARM(PPC)_DEST))="PROCMON PAGE-IN FAILURE" CH_LINK=PPC CH_LAST=PPC CH_PPCS=1 %RETURN !----------------------------------------------------------------------- %ROUTINE PAGEIN(%INTEGER EPX,SACT) P_DEST=X'40001' P_SRCE=X'800E0000'!SACT P_P1=CH_AMTX<<16!EPX P_P2=PROCESS PAGETURN(P) %END !----------------------------------------------------------------------- %ROUTINE PAGEOUT(%INTEGER EPX) P_DEST=X'40002' P_SRCE=X'800E0000' P_P1=CH_AMTX<<16!EPX P_P2=X'C' ;! WRIT & UPDATE DRUM PAGETURN(P) %END !----------------------------------------------------------------------- %ROUTINE GET AMTX(%INTEGER DA,TAGS) P_DEST=X'80001' P_SRCE=0 P_P1=0 P_P2=DA P_P3=TAGS ACTIVE MEM(P) %END !----------------------------------------------------------------------- %ROUTINE RETURN AMTX(%INTEGER AMTX) P_DEST=X'80002' P_SRCE=0 P_P1=0 P_P2=AMTX ACTIVE MEM(P) %END !----------------------------------------------------------------------- %ROUTINE COPY(%STRING(23) S) %INTEGER AD,I AD=VIRTAD!REALAD+CH_CUR-CH_EPX*EPAGESIZE<<10-1 %CYCLE I=1,1,LENGTH(S) BYTE INTEGER(AD+I)=CHARNO(S,I) %REPEAT CH_CUR=CH_CUR+LENGTH(S) %IF CH_CUR=CH_LEN %THEN CH_CUR=32 %END %END !----------------------------------------------------------------------- %END !----------------------------------------------------------------------- %RECORDFORMAT IOSTATF(%INTEGER IAD,%STRING(15) MESS, %C %INTEGER INBUFLEN,OUTBUFLEN,INSTREAM,OUTSTREAM) %RECORDFORMAT PARMF(%INTEGER DEST,SRCE,P1,P2,P3,P4,P5,P6) !----------------------------------------------------------------------- %EXTERNALINTEGERFN REQUEST INPUT(%INTEGER OUTPUT POSN,TRIGGER POSN) %RECORDNAME IOSTAT(IOSTATF) %RECORDNAME DIROUTP(PARMF) IOSTAT==RECORD(X'140048') DIROUTP==RECORD(INTEGER(X'14007C')) %UNLESS IOSTAT_OUTBUFLEN>0 %AND 0<=OUTPUT POSN0 %AND 0<=TRIGGER POSN0 %AND 0<=OUTPUT POSN