! ! 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 ! ! ! THESE CONST INTEGERS DEFINE SIZES AND LAYOUT OF IMPORTANT TABLES ! THEY HAVE TO BE HERE TO BE GLOBAL TO ALL ROUTINES INCLUDING IO ONES ! %CONSTINTEGER LSTLEN=192; ! LOCAL SEGMENT TABLE LENGTH %CONSTLONGINTEGER LCACR=1; ! ACR OF LOCAL CONTROLLER %CONSTINTEGER DIRCSEG=10; ! SEG NO OF DIRECTOR COMMS SEG %CONSTINTEGER DIRCSEGOFFSET=0; ! FOR ALIGNMENT IF NEEDED %CONSTINTEGER DIRCSEGAD=DIRCSEG<<18; ! VIRTUAL ADDRESS OF DIR COM SEG %CONSTINTEGER DIRCSEGL=2048+255+LSTLEN; ! SIZE OF SMAE ! MADE UP OF 2049 FOR CBT ! LSTLEN FOR SST ! 48+64 FOR 2 BITS OF SYTEMCALL TABLE ! 32+48 FOR DIROUTP&SIGOUT %CONSTINTEGER LSTACKLEN=3; ! LOCAL CONT. STACK ELEN %CONSTINTEGER LSTACKLENP=2; ! PAGED PART %CONSTINTEGER LSTKN=3; ! NO OF LOCAL STACKS %CONSTLONGINTEGER DIRACR=2; ! DIRECTOR ACR LEVEL %CONSTINTEGER MAXIT=X'FFFFFF' %CONSTINTEGER MINS INACTIVE=12; ! BEFORE BEING CHOPPED ! THESE CONST INTEGERS LAYOUT THE DIRECTOR COMMS SEGMENT(LOCAL 10) %CONSTINTEGER SCTIENTRIES=6; ! VALID I VALUES FOR SCT %CONSTINTEGER SCTI0=DIRCSEGAD+DIRCSEGOFFSET;! SYSTEMCALL INDEX TABLE %CONSTINTEGER SCTILEN=SCTIENTRIES*8; ! OF SCTIENTRIES DOUBLE WORDS %CONSTINTEGER SCTJ30=SCTI0+SCTILEN; ! 3RD BRANCH OF SC TABLE %CONSTINTEGER SCTJ3LEN=4*16; ! 4ENTRIES FOR 3 LC ROUTINES %CONSTINTEGER DIROUTPAD=SCTJ30+SCTJ3LEN;! ADDRESS OR DIROUTP %CONSTINTEGER DIROUTPLEN=32; ! ONE 32 BYTE RECORD %CONSTINTEGER SIGOUTPAD=DIROUTPAD+DIROUTPLEN;! ADDR SIGOUTP %CONSTINTEGER SIGOUTPLEN=48; ! ONE 48 BYTE RECORD %CONSTINTEGER CBTAD=SIGOUTPAD+SIGOUTPLEN;! CLAIMED BLOCK TABLE AD %CONSTINTEGER CBTLEN=255*8; ! OF 255 8BYTE ENTRIES %CONSTINTEGER SSTAD=CBTAD+CBTLEN; ! 2DRY SEG TABLE OF LSTLEN BYTES %CONSTINTEGER LSTVAD=0; ! VIRTUAL ADDRESS OF LOCAL SEG TABLE !----------------------------------------------------------------------- %RECORDFORMAT IOSTATF(%INTEGER IAD,%STRING(15) INTMESS, %C %INTEGER INBUFLEN,OUTBUFLEN,INSTREAM,OUTSTREAM) %RECORDFORMAT PARMF(%INTEGER DEST,SRCE,P1,P2,P3,P4,P5,P6) %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="25J" !----------------------------------------------------------------------- !* COMMUNICATIONS RECORD FORMAT - EXTANT FROM CHOPSUPE 20A ONWARDS * %RECORDFORMAT COMF(%INTEGER OCPTYPE,IPLDEV,SBLKS,SEPGS,NDISCS, %C DDTADDR,GPCTABSIZE,GPCA,SFCTABSIZE,SFCA,SFCK,DIRSITE, %C DCODEDA,SUPLVN,WASKLOKCORRECT,DATE0,DATE1,DATE2, %C TIME0,TIME1,TIME2,EPAGESIZE,USERS,CATTAD,DQADDR, %C %BYTEINTEGER NSACS,RESV1,SACPORT1,SACPORT0, %C NOCPS,RESV2,OCPPORT1,OCPPORT0, %C %INTEGER ITINT,CONTYPEA,GPCCONFA,FPCCONFA,SFCCONFA, %C BLKADDR,DPTADDR,SMACS,TRANS,%LONGINTEGER KMON, %C %INTEGER DITADDR,SMACPOS,SUPVSN,PSTVA,SECSFRMN,SECSTOCD, %C SYNC1DEST,SYNC2DEST,ASYNCDEST,MAXPROCS,INSPERSEC,ELAPHEAD, %C COMMSRECA,STOREAAD,PROCAAD,SFCCTAD,DRUMTAD,TSLICE,SP0,SP1, %C SP2,SP3,SP4,SP5,SP6,SP7,SP8, %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) %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 BAD DRUM PAGE(%INTEGER DTX) %INTEGER I,J,K,FSTASL,BSTASL,FREEEPAGES,UNALLOCEPS,OVERALLOC, %C DEADLOCKS,DRUMSIZE,DRUMTASL,MAXP4,NPQ, %C OLDLNB,IDLE,LCN,DRUMT ASL BTM, %C MPLEVEL,PAGEFREES,ISTAD, %C GETEPN,DRUMALLOC ?%INTEGER RECAPN,PTURNN,PSHAREN,IDLEN,NOWORKN,FLPN,BLPN %LONGINTEGER L %STRING(3) STRPROC !----------------------------------------------------------------------- %RECORDFORMAT SSNP1F(%INTEGER LNB,PSR,PC,SSR,SF,IT,IC,CTB,XNB,%C B,DR0,DR1,A0,A1,A2,A3,PEAD,II) %RECORDFORMAT ISTF(%INTEGER LNB,PSR,PC,SSR,SF,IT,IC,CTB) %RECORD LSSNP1I,LSSNP1,ISTDUM(ISTF) %RECORDNAME LSSNP1P(ISTF) %OWNLONGINTEGERARRAYFORMAT 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 %INTEGER SPSTOREX; ! FOR KEEPING EMERGENCY SPARE PAGE !----------------------------------------------------------------------- ! ACTIVE MEMORY TABLE DECLARATIONS ETC. %CONSTINTEGER MIN RESIDENCES=3,MAXRESIDENCES=12;! FOR AMT TIMEOUTS %OWNINTEGER RESIDENCES=MAXRESIDENCES;! ADJUSTED DOWN AS DRUM FILLS %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,SP0,SUSP,RQTS1,RQTS2,STROBEI,SP2) %OWNINTEGER MAXCAT MAXCAT=INTEGER(COM_CATTAD) %RECORDARRAYFORMAT CATTABAF(0:MAXCAT)(CATTABF) %RECORDARRAYNAME CATTAB(CATTABF) CATTAB==ARRAY(COM_CATTAD+4,CATTABAF) %OWNINTEGER MAXEPAGES MAXEPAGES=CATTAB(MAXCAT-1)_EPLIM ?%HALFINTEGERARRAY CATREC(0:MAXCAT,0:MAXCAT) ?%INTEGERARRAY STROBEN,STREPN,STROUT(0:MAXCAT) !----------------------------------------------------------------------- ! PON & POFF ETC. DECLARATIONS %EXTERNALROUTINESPEC PON(%RECORDNAME P) %EXTERNALINTEGERFNSPEC NEWPPCELL %EXTERNALROUTINESPEC RETURN PPCELL(%INTEGER PPCELL) !*SEM %EXTERNALROUTINESPEC SEMALOOP(%INTEGERNAME SEMA) %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 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 %EXTRINSICINTEGER KERNELQ,RUNQ1,RUNQ2 %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) !----------------------------------------------------------------------- ! TIMING INFORMATION DECS. ?%ROUTINESPEC TIMEOUT(%RECORDNAME P) %LONGINTEGERARRAY SERVIT,SERVIC(0:LOCSN0+3) %INTEGERARRAY SERVN(0:LOCSN0+3) %LONGINTEGER CLOCK0,IDLEIT,NOWORKIT,LCIT,LCIC,FLPIT,BLPIT ?%LONGINTEGER PTIT,PTIC,DRUMIT,DRUMIC,PDISCIT,PDISCIC,GETIT,GETIC, %C RETIT,RETIC,AMIT,AMIC ?%INTEGER PTCALLN,DRUMCALLN,PDISCCALLN,AMCALLN,GETCALLN,RETCALLN, %C IT,ITT,IC,ICC %INTEGERNAME KIT ;! IT IN KERNEL CONTEXT !----------------------------------------------------------------------- ! PROCESS INORMATION ARRAY DECS ETC. %RECORDFORMAT PROCF(%STRING(6) USER, %C %BYTEINTEGER INCAR, CATEGORY, WSN, RUNQ, ACTIVE, %C %INTEGER ACTW0, LSTAD, LAMTX, STACK, STATUS) %EXTERNALRECORDARRAY PROCA(0:MAXPROCS)(PROCF) %RECORDNAME PROC(PROCF) ! ! STATUS BIT IN PROCESS LIST SIGNIFY AS FOLLOWS ! 2**0 = HOLDS A SEMAPHORE ! 2**1 = ON A PAGE FAULT ! 2**2 = A BACKGROUND JOB ! 2**3 = PROCESS AWAKENED TO DEALLOCACE AMT (&DRUM) ONLY ! REMAINDER UNUSED !----------------------------------------------------------------------- ! LOCAL CONTROLLER DECS ETC. %ROUTINESPEC LOCAL CONTROL %ROUTINESPEC GLOBAL CONTROL %OWNLONGINTEGERARRAYFORMAT LSTF(0:LSTLEN-1) %OWNINTEGER TIMESLICE=X'4000'; ! 131072 MICROSECS %CONSTINTEGER OUT18CHARGE=X'400'; ! CHARGE FOR OUT18 =8 MILLESECS %OWNINTEGER OUT18INS; ! CHARGE *INS RATE %EXTERNALINTEGERFNSPEC SYSTEMCALL !----------------------------------------------------------------------- ! INTERRUPT ROUTINE SPECS %EXTERNALROUTINESPEC SYSERR(%INTEGER STK,IP) !----------------------------------------------------------------------- I=SYSTEM CALL; ! TO INITIALISE "COM" FILE ! ! CREATE LOCAL CONTROLLER CONTEXT ! LSSNP1I=0 LSSNP1I_LNB=LSTLEN*8+LSTKN*X'80'+(DIRCSEGL+1)+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'01800BFE' LSSNP1I_SF=LSTLEN*8+LSTKN*X'80'+(DIRCSEGL+1)+X'80';! 12 MORE WORDS AFTER LNB LSSNP1I_IT=MAXIT LSSNP1I_IC=MAXIT *LSS_(%LNB+5) ;! PRESERVE DISPLAY PTR *ST_I LSSNP1I_CTB=I COM_DCODEDA=COM_SUPLVN<<24!COM_DIRSITE ! ! SET UP CLOCK REGS ! I=COM_CLKZ *LB_I *LSS_13; ! 1 INTERRUPT EVERY 2 SECS (APPROX) *ST_(0+%B); ! Z-REG %IF COM_OCPTYPE=4 %THEN %START; ! 2980 ONLY I=X'80000000'>>COM_SACPORT0 *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_OCPPORT0 *LB_X'4012' *LSS_(0+%B) *OR_I *ST_(0+%B) %FINISH %FINISH OUT18INS=OUT18CHARGE*1000*COM_ITINT//COM_INSPERSEC %IF COM_TSLICE>0 %THEN TIMESLICE=COM_TSLICE//COM_ITINT GLOBAL CONTROL; ! DOES NOT RETURN !----------------------------------------------------------------------- LCCALL:*JLK_%TOS *STCT_(%LNB+5); ! DISPLAY PTR TO NEW STACK ! SO THAT THE LXN IN CALL SEQUENCE ! LINKS LOCAL TO GLOBAL CONTEXTS *STB_(%LNB+0); ! B HAS PROCESS NO IN IT PUTIN ! BY SCHEDULE AT CREATE ! AND IS PASSED ON BY THIS FRIG LOCAL CONTROL; ! INITIAL CALL(DOES NOT RETURN!) %ROUTINE GLOBAL CONTROL %INTEGER I,J,K,PORT,SEIP,SELN,SESTK,KSERVICE,LSERVICE, %C CURPROC1,CURPROC2,MY OCP PORT %SWITCH CONROUT(0:3) %SWITCH SERVROUT(1:LOCSN0) ;! KERNEL SERVICES, (1:LOCSN0) %RECORDNAME ISTP(ISTF) %INTEGERNAME RUNQ,CURPROC %RECORD P(PARMF) ! ! FIND WHICH OCP THIS ACTIVATION IS USING AND SET RELEVANT IST ! *LSS_(3); *USH_-26 *AND_3; *ST_ MY OCP PORT ISTAD=X'80000000'+MY OCP PORT<<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_CTB=0 %CYCLE I=ISTAD+X'20',X'20',ISTAD+X'160' RECORD(I)<-ISTP %REPEAT LSSNP1P==RECORD(X'40000') ! ! MASK SYSERR& UNMASK OUT ON SYSERR. INTERRUPT ! ISTP_SSR=X'01800EFF' ISTP_SF=ISTP_SF+X'1000'; ! SET SYSTEM ERROR SF TO DISTANT PLACE ! ! 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) ! ! 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 SPSTOREX=0 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//10 ;! 10% OVERALLOCATION UNALLOCEPS=FREEEPAGES+OVERALLOC CURPROC1=0 CURPROC2=0 NPQ=0 IDLE=0 KIT==INTEGER(X'80140014') !----------------------------------------------------------------------- ! INITIALISE ACTIVATE WORDS !----------------------------------------------------------------------- ! 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=8 ;! 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 TAKING CARE ITS INCARNATION IS 0 ! AND THAT ALL ITS TEMP SPACE IS IN X40 EPAGES(1 SEGMENT) P_DEST=X'30001' P_SRCE=0; ! NO REPLY WANTED P_P1=M'DIR'!6<<24 P_P2=M'ECT'<<8; ! ENSURE INCAR=0 P_P3=COM_SUPLVN<<24!X'400'; ! LSTACKDA(NEEDS 3 EPAGES ONLY) P_P4=0; ! USE DEFAULT DIRVSN P_P5=P_P3+LSTACKLEN; ! DSTACKDA(1SEG IN CBT BUT USES LESS) P_P6=P_P3+(X'40'-8); ! DGLADA (ALLOW LAST 8 PAGES) 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 ? %IF MPLEVEL!NPQ=0 %THEN NOWORKN=NOWORKN+1 %ELSE 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 PROC==PROCA(CURPROC) ? %IF PROC_STATUS&4#0 %THEN BLPN=BLPN+1 %ELSE FLPN=FLPN+1 I=ADDR(PROC_ACTW0) *LXN_I *ACT_(%XNB+0) ;! 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): TIMESLICE=P_P1; ->KEXIT SERVROUT(2):DEADLOCK; ->KEXIT 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): ->INVALID 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 ! ! MUST ROUND ROBIN HERE IN CASE OF PRE EMPTION ! %IF LSERVICE=RUNQ %THEN RUNQ=0 %ELSE %START LSERVQ==SERVA(RUNQ) LSERVQ_L=LSERV_L %FINISH LSERV_L=0 CURPROC=LSERVICE-LOCSN0 I=ADDR(PROCA(CURPROC)_ACTW0) ? LCN=LCN+1 ? *LSS_(6) ;? *ST_IC ;? *LSS_(5) ;? *ST_IT ? LCIC=LCIC+MAXIT-IC ? LCIT=LCIT+MAXIT-IT ! TO ACTIVATE TO LOCAL CONTROLLER USE THE ACTIVATE WORDS IN THE PROCESS ! LIST BUT SUBSTITUTE LC STACK NO(0) FOR PROCESS STACK NO ! *LXN_I *LSD_(%XNB+0) *SLSD_0; ! LC STACK NO NOT PARAMETERISED ! *ST_%TOS *ACT_%TOS !----------------------------------------------------------------------- ! EVENT PENDING (USED TO EXIT FROM LOCAL CONTROLLER) IST11I: *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 INTS (CLOCK) ENTER HERE *LSS_%TOS ; *ST_I *LSS_%TOS ; *ST_J %IF IDLE#0 %THEN %START %IF MPLEVEL!NPQ=0 %THEN NOWORKIT=NOWORK IT+MAXIT-KIT %ELSE %C IDLEIT=IDLEIT+MAXIT-KIT IDLE=0 %FINISH P_P1=I P_P2=J %IF COM_OCPTYPE=4 %START; ! 2980 CLOCK IS IN SAC I=COM_CLKX&X'FFF00000'!X'100'; ! SAC EXTERNAL INT REG *LB_I; ! MUST BE READ&CLEARED *LSS_(0+%B); ! OR INT WILL OCCUR AGAIN *ST_J P_P3=J %FINISH P_DEST=X'A0000' ELAPSEDINT(P) ? KSERVICE=10 ->KTIMES !----------------------------------------------------------------------- ! MULTIPROCESSOR IST3I:*JLK_%TOS *IDLE_X'F3' !----------------------------------------------------------------------- ! PERIPHERAL IST4I:*JLK_%TOS ! PERIPHERAL INTS ENTER HERE *LSS_%TOS; ! OLD STACK *LSS_%TOS; ! PARAMETER = SAC NUMBER<<20 *ST_I %IF IDLE#0 %THEN %START %IF MPLEVEL!NPQ=0 %THEN NOWORKIT=NOWORKIT+MAXIT-KIT %ELSE %C IDLEIT=IDLEIT+MAXIT-KIT IDLE=0 %FINISH !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' !----------------------------------------------------------------------- !----------------------------------------------------------------------- ! INSTRUCTION COUNTER (BEFORE PROCESS CREATE) IST12I:*JLK_%TOS ; *IDLE_X'FC' !----------------------------------------------------------------------- %END %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 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:16) ? %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=FREEEPAGES//2-LSTACKLEN %IF MAXEPAGES>I %THEN %START MAXEPAGES=I %CYCLE I=1,1,MAXCAT-2; ! DONT ADJUST TRASHING CAT %IF CATTAB(I)_EPLIM>MAXEPAGES %THEN CATTAB(I)_EPLIM=MAXEPAGES %REPEAT %FINISH MAXP4=UNALLOCEPS//(2*CATTAB(MAXCAT-2)_EPLIM) 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") ? %IF DRUMSIZE=0 %THEN DISPLAY TEXT(0,2,35,"POUTS") %RETURN !----------------------------------------------------------------------- ACTIVITY(16): ! CREATE BATCH JOB 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 PROC_STATUS=ACT>>2; ! SET 2**2 BIT FOR BATCH PROC_ACTW0=(LSTLEN-1)<<18 UPDISP(PROCESS,4,USER) %IF ACT=16 %THEN UPDISP(PROCESS,10,"*") 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 NEWCATSLOT=1+PROC_STATUS>>2&1; ! INITIAL CATEGORY =1 FORE =2BACKGROUND PROC_CATEGORY=NEWCATSLOT ->STOUT !----------------------------------------------------------------------- ACTIVITY(3): ! OUT OF EPAGES NEWCATSLOT=OLDCAT_MOREP PROC_CATEGORY=NEWCATSLOT ->STOUT !----------------------------------------------------------------------- ACTIVITY(10): ! MORE EPAGES ON THE FLY ? P_P1=0 %UNLESS PARTPROC=0 %THEN %RETURN; ! NO NEWCATSLOT=OLDCAT_MOREP NEWCAT==CATTAB(NEWCATSLOT) XEPS=NEWCAT_EPLIM-OLDCAT_EPLIM %UNLESS XEPS>0 %AND UNALLOCEPS>=XEPS %THEN %RETURN I=1; J=0; ! CHECK FOR HIGHER PRIORITY WK %WHILE ISTOUT !----------------------------------------------------------------------- ACTIVITY(11): ! MORE TIME ON THE FLY? P_P1=0 %IF 0#PARTPROC#PROCESS %THEN %RETURN %IF P4L>=MAXP4 %AND OLDCAT_PRIORITY=4 %THEN %RETURN NEWCATSLOT=OLDCAT_MORET NEWCAT==CATTAB(NEWCATSLOT) I=1; J=0 %WHILE I<=NEWCAT_PRIORITY %THEN J=J+PQN(I) %AND I=I+1 %IF J#0 %THEN %RETURN PARE EPAGES; ! AND MAP NEWCAT %IF PROCESS=PARTPROC %THEN %START %IF PARTALLOC>=NEWCAT_EPLIM %START;! NEW ALLOC ALREADY UNALLOCEPS=UNALLOCEPS+PARTALLOC-NEWCAT_EPLIM PARTPROC=0 P_P3=0 P_P1=NEWCAT_EPLIM %FINISH %ELSE %START ALLOCREST=ALLOCREST-OLDCAT_EPLIM+NEWCAT_EPLIM P_P3=1 ;! STILL PARTIAL ALLOCATION P_P1=PARTALLOC %FINISH %FINISH %ELSE %START UNALLOCEPS=UNALLOCEPS+OLDCAT_EPLIM-NEWCAT_EPLIM P_P3=0 P_P1=NEWCAT_EPLIM %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 %IF PROC_STATUS&8#0 %START; ! DELLOCATE AMT ONLY PROC_STATUS=PROC_STATUS!!8 PROC_ACTIVE=5 %FINISH NEWCATSLOT=OLDCAT_SUSP PARE EPAGES %IF NEWCAT_PRIORITY<4 %AND PROCESS>3 %AND PROC_STATUS&4=0 %THEN %C NPL4=NPL4+1 ->STOUT !----------------------------------------------------------------------- ACTIVITY(7):! UNSUSPEND ? SUSPN=SUSPN-1 PROC_ACTIVE=255 %IF OLDCAT_PRIORITY<4 %AND PROCESS>3 %AND PROC_STATUS&4=0 %THEN %C 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 ->DEALL !----------------------------------------------------------------------- STOUT: ! PAGE-OUT LOCAL CONTROLLER STACK ? CATREC(NEWCATSLOT,OLDCATSLOT)<-CATREC(NEWCATSLOT,OLDCATSLOT)+1 DEAD: ! DEADLOCK DISCOVERED MPLEVEL=MPLEVEL-1 %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 END "NEW" PAGETURN(P) ;! NO REPLIES %REPEAT %IF OLDCAT_PRIORITY=4 %THEN P4L=P4L-1 PROC_RUNQ=0 %UNLESS ACT=5 %THEN ONPQ DEALL:%IF PROCESS=PARTPROC %THEN %START PARTPROC=0 UNALLOCEPS=UNALLOCEPS+PARTALLOC+LSTACKLEN %FINISH %ELSE UNALLOCEPS=UNALLOCEPS+OLDCAT_EPLIM+LSTACKLEN !----------------------------------------------------------------------- ! COMPLETE ANY PARTIAL ALLOCATIONS FIRST 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 ! LOAD AS MANY AS POSSIBLE %CYCLE %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 %IF GETEPN>=MPLEVEL-1 %OR PROCESS#PARTPROC %THEN P_P1=1 %ELSESTART P_P1=0 PARTWAIT=1 MPLEVEL=MPLEVEL-1 %FINISH %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'!LCACR<<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+36)=PROCESS; ! PROCESS NO TO BREG & ! HENCE VIA FRIG TO LOCAL CONTRLR 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)." ") ? %IF DRUMSIZE=0 %THEN DISPLAY TEXT(0,3,36,STRINT(PAGEFREES)." ") ?%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 ! STORE FLAGS : ! BIT 7 : DISC TRANSFER IN PROGRESS(1)/NOT IN PROGRESS(0) ! BIT 6 : DISC INPUT(0)/OUTPUT(1) ! BIT 5 : DRUM TRANSFER IN PROGRESS(1)/NOT IN PROGRESS(0) ! BIT 4 : DRUM INPUT(0)/OUTPUT(1) ! BIT 3 : WRITTEN TO MARKER ! BIT 2 : TYPE (0:DISC ONLY, 1:DISC & DRUM) ! BIT 1 : MAKE NEW ! BIT 0 : RECAPTURABLE %INTEGER AEX,AMTX,EPX,DDX,DTX,FLAGS,STOREX,SRCE,CALL,ID,I %RECORDNAME AMT(AMTF) %RECORDNAME ST(STOREF) %RECORDNAME PP(PARMXF) %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 I=AMTDD(DDX) %IF I&DTXBIT=0 %THEN %START ;! NO DRUM PAGE ALLOCATED DTX=-1 STOREX=I&STXMASK %FINISH %ELSE %START DTX=I&STXMASK STOREX=DRUMT(DTX) %FINISH ->ACTIVITY(P_DEST&X'FFFF') !----------------------------------------------------------------------- ACTIVITY(1):! PAGE-IN (ALLOWS FOR PAGETURN TO BE CALLED) ? PTURNN=PTURNN+1 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=1 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 ->REPLY %FINISH ? PSHAREN=PSHAREN+1 %IF ST_USERS=0 %THEN %START ;! PAGE-OUT IN PROGRESS ST_USERS=1 PAGEFREES=PAGEFREES-1 %FINISH %ELSE %START ST_USERS=ST_USERS+1 UNALLOCEPS=UNALLOCEPS+1 ! COULD POSSIBLY CALL SCHEDULE HERE TO LOAD NEXT PROCESS %FINISH ! IF ->STORE TRANSIT, SAVE IN PAGE-IN-TRANSIT TABLE %IF ST_FLAGS&X'C0'=X'80' %OR ST_FLAGS&X'30'=X'20' %THEN %START *JLK_ P_DEST=0 %RETURN %FINISH ! INTACT COPY IN STORE (EVEN IF STORE-> TRANSIT), SO REPLY NOW REPLY:P_P1=ID ;! IDENTIFIER P_P2=ST_REALAD P_P3=0 ;! SUCCESS %IF CALL>0 %THEN P_DEST=SRCE %AND P_SRCE=X'40001' %AND PON(P) %RETURN %FINISH ! ALLOCATE EPAGE P_DEST=X'50000' ;! GET EPAGE P_SRCE=X'80040003' P_P1=AEX %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 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 %START ;! IF NOT DEADLOCK PAGE ZERO ? *LSS_(6) ;? *ST_IC ;? *LSS_(5) ;? *ST_IT RETURN EPAGE(P) ? *LSS_(5) ;? *ST_ITT ;? *LSS_(6) ;? *ST_ICC ? RETIT=RETIT+IT-ITT ;? PTIT=PTIT-IT+ITT ? RETIC=RETIC+IC-ICC ;? PTIC=PTIC-IC+ICC ? RETCALLN=RETCALLN+1 %FINISH ->HERE %FINISH %IF P_P2=0 %THEN %START ;! DEADLOCK PAGE ZERO P_DEST=SRCE!1 P_P3=-1 PON(P) AMT_USERS=AMT_USERS-1 %RETURN %FINISH 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" ->REPLY %FINISH %IF DTX<0 %THEN %START ;! NOT ON DRUM *JLK_ 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 P_DEST=0 %RETURN %FINISH %ELSE %START ;! ON DRUM DRUMT(DTX)=STOREX *JLK_ ST_FLAGS=X'20' ;! DRUM->STORE TRANSIT P_DEST=X'280001' P_SRCE=X'80040006' P_P1=AEX 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 P_DEST=0 ;! IN CASE CALLED %RETURN %FINISH !----------------------------------------------------------------------- ACTIVITY(6):! REPLY FROM DRUM/READ ON FAILURE ONLY ST==STORE(STOREX) BAD DRUM PAGE(DTX) ->DRUMRF !----------------------------------------------------------------------- ACTIVITY(2):! PAGE-OUT ST==STORE(STOREX) AMT_USERS=AMT_USERS-1 ST_FLAGS=ST_FLAGS!(P_P2&X'E') ;! 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 ? *LSS_(6) ;? *ST_IC ;? *LSS_(5) ;? *ST_IT RETURN EPAGE(P) ? *LSS_(5) ;? *ST_ITT ;? *LSS_(6) ;? *ST_ICC ? RETIT=RETIT+IT-ITT ;? PTIT=PTIT-IT+ITT ? RETIC=RETIC+IC-ICC ;? PTIC=PTIC-IC+ICC ? RETCALLN=RETCALLN+1 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 !----------------------------------------------------------------------- ACTIVITY(5):! REPLY FROM DISC/WRITE 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 ? *LSS_(6) ;? *ST_IC ;? *LSS_(5) ;? *ST_IT RETURN EPAGE(P) ? *LSS_(5) ;? *ST_ITT ;? *LSS_(6) ;? *ST_ICC ? RETIT=RETIT+IT-ITT ;? PTIT=PTIT-IT+ITT ? RETIC=RETIC+IC-ICC ;? PTIC=PTIC-IC+ICC ? RETCALLN=RETCALLN+1 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 ST==STORE(STOREX) %IF P_P2<0 %THEN %START ;! WRITE FAILURE AMTDD(DDX)=STOREX ;! RETURN DRUM PAGE BAD DRUM PAGE(DTX) DTX=-1 %FINISH ! NEXT 2 LINES NOW DONE IN DRUM ROUTINE IF DRUM DOES NOT REPLY ONLY 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 !----------------------------------------------------------------------- PUSHPIT:I=NEWPPCELL PP==PARM(I) PP_DEST=SRCE PP_SRCE=X'40001' PP_P1=ID PP_P2=ST_REALAD PP_P3=0 ;! SUCCESS FLAG PP_LINK=ST_LINK ST_LINK=I *J_%TOS %END !---------------------------------------------------------------------- %ROUTINE BAD DRUM PAGE(%INTEGER DTX) !*********************************************************************** !* PUTS A DRUM PAGE ONTO BACK OF FREELIST. FREELIST IS NOT CIRCULAR * !* TO MINIMISE OVERHEADS SO SOME SEARCHING MAY BE NEEDED HERE. * !* DRUM ASL BTM POINTS TO LAST CELL UNLESS LIST HAS BEEN COMPLETELY * !* EMPTY SINCE IPL. * !*********************************************************************** %INTEGER I,J %IF DRUMTASL=DTEND %THEN DRUMTASL=DTX %AND ->ENTER %IF DRUMT(DRUMT ASL BTM)#DTEND %START I=DRUMTASL %CYCLE J=DRUMT(I) %IF J=DTEND %THEN %EXIT I=J %REPEAT DRUMT ASL BTM=I %FINISH DRUMT(DRUMT ASL BTM)=DTX ENTER: DRUMT(DTX)=DTEND DRUMT ASL BTM=DTX DRUM ALLOC=DRUM ALLOC-1 %END %ROUTINE GET EPAGE(%RECORDNAME P) !*********************************************************************** !* CAN BE CALLED OR PONNED TO PROVIDE AN EPAGE. IF CALLED AND THERE * !* ARE NO EPAGES IT WILL QUEUE CALL AND PON REPLY UNLESS P_SRCE * !* =X'80000000' WHEN A FAILURE REPLY OF STOREX=-1 IS GIVEN * !* REPLIES HAVE STORE INDEX IN P_P2 AND VIRTADDR IN P_P4 * !*********************************************************************** %RECORDSPEC P(PARMF) %RECORDNAME ST(STOREF) %INTEGER STOREX,PS,I,STAD !*SEM *INCT_(STORESEMA) !*SEM *JCC_8, !*SEM SEMALOOP(STORESEMA) !*SEMSEMACL: %IF FREEEPAGES=0 %THEN %START P_SRCE=P_SRCE&X'7FFFFFFF' %IF P_SRCE=0 %THEN P_P2=-1 %AND ->RETURN 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 ST==STORE(STOREX) FSTASL=STORE(FSTASL)_FLINK %IF FSTASL=0 %THEN BSTASL=0 %ELSE STORE(FSTASL)_BLINK=0 %IF ST_FLAGS=1 %THEN %START; ! RECAPTURABLE FLAG I=ST_LINK %IF I&DDBIT=0 %THEN AMTDD(I)=AMTDD(I)!STXMASK %ELSE %C I=I&(\DDBIT) %AND DRUMT(I)=STXMASK ST_FLAGS=0 %FINISH STAD=VIRTAD+ST_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: !*SEM STORESEMA=-1 %END !----------------------------------------------------------------------- %INTEGERFN NEW EPAGE !*********************************************************************** !* HANDS OUT A NEW EPAGE TO EXTEND A VITAL RESIDENT TABLE * !*********************************************************************** %RECORD P(PARMF) %INTEGER I P_DEST=X'50000' P_SRCE=X'80000000' P_P2=0; ! CLEAR TO ZERO GET EPAGE(P) %IF P_P2>0 %THEN %RESULT=STORE(P_P2)_REALAD %IF SPSTOREX>0 %START I=STORE(SPSTOREX)_REALAD SPSTOREX=0 %RESULT=I %FINISH %RESULT=-1 %END !----------------------------------------------------------------------- %ROUTINE RETURN EPAGE(%RECORDNAME P) !*********************************************************************** !* PUT AN EPAGE BACK ON THE FREE LIST. FLAWED PAGES ARE ABANDONED * !* IF THE PAGE IS MARKED AS 'RECAPTURABLE' IT GOES TO THE BACK OF * !* OF THE FREELIST OTHERWISE IT GOES ON THE FRONT. THIS GIVES THE * !* MAXIMUM CHANCES OF RECAPTURING ANYTHING USEFUL * !*********************************************************************** %RECORDSPEC P(PARMF) %RECORDNAME ST(STOREF) %INTEGER I,STOREX,STAD !*SEM *INCT_(STORESEMA) !*SEM *JCC_8, !*SEM SEMALOOP(STORESEMA) !*SEMSEMACL: ? %IF KMON&1<<6#0 %THEN PRINT STRING("RETURNEPAGE:") %AND PTREC(P) STOREX=P_P2 ST==STORE(STOREX) %IF ST_REALAD<0 %THEN %START OPMESS("PAGE ".STRINT(STOREX)." ABANDONED") *JLK_ %RETURN %FINISH %IF SPSTOREX=0 %START *JLK_ SPSTOREX=STOREX I=X'58000000'!EPAGESIZE<<10 STAD=VIRTAD+ST_REALAD *LDTB_I *LDA_STAD *MVL_%L=%DR,0,0 %FINISH %ELSE %START %IF ST_FLAGS&1#0 %START; ! RECAPTURABLE TO BACK ST_FLINK=0 ST_BLINK=BSTASL %IF BSTASL=0 %THEN FSTASL=STOREX %ELSE %C STORE(BSTASL)_FLINK=STOREX BSTASL=STOREX %FINISH %ELSE %START; ! NOT RECAPTURABLE ON FRONT ST_BLINK=0 ST_FLINK=FSTASL %IF FSTASL=0 %THEN BSTASL=STOREX %ELSE %C STORE(FSTASL)_BLINK=STOREX FSTASL=STOREX %FINISH %IF FREEEPAGES=0 %THEN UNINHIBIT(5) FREEEPAGES=FREEEPAGES+1 %FINISH !*SEM STORESEMA=-1 %RETURN STOP RECAPTURE: ! JLK SUBROUTINE TO BREAK LINK %IF ST_FLAGS=1 %THEN %START ;! RECAPTURABLE I=ST_LINK %IF I&DDBIT=0 %THEN AMTDD(I)=AMTDD(I)!STXMASK %ELSE %C I=I&(\DDBIT) %AND DRUMT(I)=STXMASK ST_FLAGS=0 %FINISH *J_%TOS %END !----------------------------------------------------------------------- %ROUTINE DEADLOCK !*********************************************************************** !* CALLED WHEN THE NUMBER OF PROCESSES NOT WAITING ON A PAGE FAULT * !* IS LESS THAN THE NUMBER OF OCPS TO EXECUTE THEM.THIS ROUTINE GOES* !* DOWN THE LIST OF GET EPAGES UNTIL IT FIND A PROCESS AND GIVES IT * !* PAGE ZERO AS A SIGNAL TO DEPART. NEEDS STORE SEMA TO CHECK FOR * !* A DEADLOCK AND THE MAINQSEMA FOR SUPPOFFING * !*********************************************************************** %RECORD P(PARMF) %INTEGER I,N N=GETEPN %RETURN %IF GETEPN<=0 GETEPN=GETEPN-1; ! ASSUMES WE WILL CURE DEADLOCK DEADLOCKS=DEADLOCKS+1 %CYCLE I=1,1,4*N; ! ALLOW FOR PLENTY OF OTHER RQS SUPPOFF(SERVA(5),P); ! TAKE A GET PAGE REQUEST %IF (P_SRCE=X'40003' %AND LOCSN0>16<=LOCSN1) %OR %C (P_SRCE&X'FFFF'=9 %AND LOCSN0>16<=LOCSN1) %START ! 4-3=PAGEIN. P_P5 IS PT SRCE ! L-C ACT 9 =GET PAGE FOR PTS P_DEST=P_SRCE P_SRCE=X'50000'; ! AS FROM GET EPAGE P_P2=0; ! PAGE 0 P_P4=-1; ! WHICH HAS REALAD OF -1 PON(P) PRINTSTRING("DEADLOCK RECOVERED ") %RETURN %FINISH PON(P); ! NOT SUITABLE: RETURN TO QUEUE %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 %LONGINTEGER LIM %RECORDNAME PROC(PROCF) %OWNHALFINTEGERARRAY AMTHASH(0:511)=0(512) %RECORDNAME AMT(AMTF) %OWNINTEGERARRAYNAME AMTAPT %OWNINTEGER AMTASIZE,AMTASL,AMTCLOCKS,AMTANEXT=0 %OWNINTEGERARRAYNAME AMTDDPT %OWNINTEGERARRAY DDASL(1:MAXBLOCK)=0(MAXBLOCK) %OWNINTEGER AMTDDSIZE,AMTDDNEXT=0 %SWITCH ACT(0:5) ? %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 ASL BTM=DRUMSIZE-1 DRUMT(DRUMT ASL BTM)=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 %C 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 ! TRY TO APPEND EPAGE TO AMTA AMTX=-1 %IF AMTANEXT>=MAXAMTAK %THEN ->RETURN;! ALREADY MAX SIZE REALAD=NEW EPAGE %IF REALAD<=0 %THEN ->RETURN;! NO FREE EPAGE APPENDAMTA(EPAGESIZE<<10,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 %C J=DDASL(I) %AND DDASL(I)=AMTDD(J) %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 ! TRY TO APPEND EPAGE TO AMTDD %IF FREEMAX<32 %AND AMTDDNEXT0 %THEN APPENDAMTDD(EPAGESIZE<<10,REALAD) %FINISH ->RETRY %FINISH SETAMT: ! PUSHDOWN NEW AMT CELL AMTX=AMTASL 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 I=100*DRUMALLOC//DRUMSIZE %ELSE I=0 ? %IF DRUMSIZE#0 %THEN DISPLAY TEXT(0,3,37,STRINT(I)."% ") %IF I>80 %THEN %START; ! ADJUST LC DRUM TIMEOUT RESIDENCES=MINRESIDENCES+(100-I)//2 RESIDENCES=MAXRESIDENCES %IF RESIDENCES>MAXRESIDENCES %FINISH %ELSE RESIDENCES=MAXRESIDENCES ! 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 P_SRCE=X'80000' %IF PROC_ACTIVE=4 %THEN %START ;! 2 MINS INACTIVITY P_DEST=(I+LOCSN3)<<16 ;! ASYNCH ACT 0 P_P1=2 ;! RELEASE ACTIVE MEMORY PON(P) %FINISH %IF I>3 %AND PROC_ACTIVE=2*MINSINACTIVE %AND PROC_STATUS&4=0%START P_DEST=(I+LOCSN3)<<16+1 P_P1=-1; P_P2=-1 P_P3=X'01570000'; ! SEND INT W PON(P) %FINISH PROC_ACTIVE=PROC_ACTIVE+1 %UNLESS PROC_ACTIVE>200 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 !----------------------------------------------------------------------- %ROUTINE APPENDAMTA(%INTEGER NEWSPACE,REALAD) %INTEGER FIRSTNEW,I,J 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 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:LOCSN0+3)="IDLE TIME", "NOWORK TIME","","SCHEDULE", "PAGETURN","GET EPAGE","RETURNEPAGE","SEMAPHORE","ACTIVEMEM","", "ELAPSEDINT","UPDATE TIME","DPONPUTONQ","TURNONEP","",""(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","FOREGRND USERS","BACKGRND USERS" ?%STRING(31)%FN STRPRINT(%REAL X,%INTEGER B,A) ?! STRING OF "PRINT(X,B,A)" ?%STRING(31) S,T,U ?%INTEGER I,J ?%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,J %IF PROCESS<=57 %THEN %START I=(PROCESS-1)//19 J=I*19-4 %FINISH %ELSE %START PROCESS=PROCESS-57 I=(PROCESS-1)//24 J=J*24-23 %FINISH DISPLAY TEXT(0,PROCESS-J,I*13+OFFSET,S) %END !----------------------------------------------------------------------- ! THE LOCAL CONTROLLER STACK HAS SEVERAL OTHER SEGMENTS MAPPED ONTO ITS ! FIRST PART. IT IS IMPORTANT THAT THESE SEGMENTS ARE ACCESSED VIA ! THEIR PROPER ADDRESSES AND NOT VIA ADDRESSES IN THE LOCAL CONTROLLER ! STACK AS THE SLAVES ARE NOT PROOF AGAINST 2 VIRTUAL ADDRESSES ! HAVING THE SAME REAL ADDRESS ! THIS AREA IS CURRENTLY LAID OUT AS FOLLOWS:- ! 0 TO X600 THE LOCAL SEGMENT TABLE 128 8BYTE ENTRIES ! X600 TO X680 THE LOCAL CONTROLLER SSN+1 ! X680 TO X700 SEGMENT 5 IE USER STACK SSN+1 ! X700 TO X780 SEGMENT 7 IE SIGNAL STACK SSN+1 ! X780 TO X800 RESERVED FOR SSN+1 OF CURRENTLY NOMINATED USER STACK ! X800 X1180 THE DIRERTOR-LOCALCONTROLLER COMMUNICATION SEGMENT(10) !----------------------------------------------------------------------- %ROUTINE LOCAL CONTROL !----------------------------------------------------------------------- ! DIRECTOR COMMUNICATIONS RECORDS %RECORDNAME DIROUTP(PARMF) %RECORDFORMAT SIGOUTPF(%INTEGER DEST,SRCE,P1,P2,P3,P4,P5,P6, %C TYPE,SSN,SSNAD,SUSP) %RECORDNAME SIGOUTP(SIGOUTPF) !----------------------------------------------------------------------- ! CLAIMED BLOCK TABLES %OWNBYTEINTEGERARRAYFORMAT SSTF(0:LSTLEN-1) %BYTEINTEGERARRAYNAME SST %RECORDFORMAT CBTF(%INTEGER DA,%HALFINTEGER AMTX,%BYTEINTEGER TAGS,LINK) %OWNRECORDARRAYFORMAT CBTAF(0:254)(CBTF) %RECORDARRAYNAME CBTA(CBTF) %INTEGERNAME CBTASL %RECORDNAME CBT(CBTF) %INTEGER CBTP !----------------------------------------------------------------------- ! CONSOLE IO RECORDS %RECORDNAME IOSTAT(IOSTATF) !----------------------------------------------------------------------- ! ACCOUNTING INFORMATION %RECORDFORMAT ACNTF(%LONGINTEGER LTIME,%INTEGER PTURNS) %RECORDNAME ACNT(ACNTF) ! INSTRUCTION COUNTER REVS WORD %INTEGERNAME ICREVS,SEMAHELD !----------------------------------------------------------------------- ! ACTIVE SEGMENT TABLES %CONSTINTEGER MAXAS=31 %LONGINTEGERARRAY AS(0:MAXAS) %BYTEINTEGERARRAY ASEG(0:MAXAS) %INTEGER ASFREE,ASWAP,ASWIP ;! %BITARRAY (0:MAXAS) %INTEGERARRAY OLDASWIPS(0:MAXRESIDENCES) %CONSTLONGINTEGER LTOPBIT=X'8000000000000000' %CONSTINTEGER TOPBIT=X'80000000' !----------------------------------------------------------------------- ! LOCAL STACKS INFORMATION %BYTEINTEGERARRAY LSTKSSN(1:LSTKN) !----------------------------------------------------------------------- ! CATEGORY INFORMATION %INTEGER EPLIM,EPN,RTLIM,RTN !----------------------------------------------------------------------- %INTEGERFNSPEC CHECK RES(%INTEGER WRITE,LEN,AD) %ROUTINESPEC CONNECT(%INTEGER SEG,DA,LEN,ACC) %ROUTINESPEC ASOUT(%INTEGER ASP) %ROUTINESPEC STROBE %ROUTINESPEC WORKSET %ROUTINESPEC CLEAR ACCESSED BITS %ROUTINESPEC DEACTIVATE(%INTEGER MASK) %ROUTINESPEC RETURN PTS %INTEGERFNSPEC FIND PROCESS %INTEGERFNSPEC CURSSN %ROUTINESPEC WAIT(%INTEGER DACT,N) !----------------------------------------------------------------------- %RECORD P(PARMF); ! FOR POFFING PARAMETERS %RECORDNAME PROC(PROCF) %RECORDNAME SERV0,SERV,SERV3(SERVF) %RECORD POUT(PARMF) %RECORDNAME SSNP1(SSNP1F) %RECORDNAME ST(STOREF) %LONGINTEGERARRAYNAME LST %INTEGERARRAYNAME PT %INTEGER PROCESS,ME,LSN3,PTAD,VSPARM,PEPARM,VSSEG,VSEPAGE,EPX,I,J,K %INTEGER NEWSTK,STOREX,DEST,SRCE,SUSP %INTEGER XSTROBE,SEGLEN,PTEPS,ASDESTROY,PARTALLOC,PTP,ASP,ASB,OUTN,PTE %INTEGER PROCACTAD1,PROCACTAD2,HIGHSEG,LOCKST,LOCKSTX,LTAD,TSTPTR %LONGINTEGERNAME LPIT %STRING(15) INTMESS %SWITCH ACTIVITY(1:16),VSCAUSE(0:4),ASYN0(1:3),AMTXSW(-3:0) %CONSTINTEGER MAXDIROUT=28 %SWITCH DIROUT(0:MAXDIROUT) %CONSTINTEGER MAXOUTACR=DIRACR ;! UP TO DIRECTOR LEVEL %CONSTBYTEINTEGERARRAY PAGEOUT DELAY(0:10)=1,2,4,8,15(7) ! TOTAL DELAY>120 SECS TO ALLOW TIME TO AUTOLOAD DFC ! !----------------------------------------------------------------------- ! INITIAL PROCESS CREATE ENTRY ONLY *LSS_(%LNB+0) *ST_PROCESS; ! FIND PROCESS NO PASSED BY FRIG PROCESS=INTEGER(PROCESS&X'FFFFFFFC') *LSS_OLDLNB *ST_(%LNB+0) ;! TO FRIG %MONITOR PROC==PROCA(PROCESS) ME=(PROCESS+LOCSN0)<<16 LSN3=PROCESS+LOCSN3 SERV0==SERVA(PROCESS+LOCSN0) SERV3==SERVA(LSN3) SUPPOFF(SERV0,P); ! OBTAIN STARTUP RECORD ! ! INITIALIZE LOCAL STACKS INFO ! LST==ARRAY(LSTVAD,LSTF) ;! LOCAL SEG TABLE IN SEG 0 LSTKSSN(1)=4 ;! DIRECTOR/USER STACK SEGMENT LST(5)=LST(1)+X'80'+(DIRACR-LCACR)<<56 LSTKSSN(2)=6 ;! SIGNAL STACK LST(7)=LST(5)+X'80' %CYCLE I=3,1,LSTKN LSTKSSN(I)=0 %REPEAT LST(DIRCSEG)=LST(0)&X'FFFC0000FFFFFFFF'+8+(DIRACR-LCACR)<<56+%C LENGTHENI(DIRCSEGL)<<32 DIROUTP==RECORD(DIROUTPAD) SIGOUTP==RECORD(SIGOUTPAD) CBTA==ARRAY(CBTAD,CBTAF) SST==ARRAY(SSTAD,SSTF) CBTASL==INTEGER(SSTAD+LSTLEN) %IF PROC_STATUS&4=0 %THEN LPIT==FLPIT %ELSE LPIT==BLPIT !----------------------------------------------------------------------- ! INITIALISE CLAIMED BLOCK TABLES %CYCLE I=0,1,LSTLEN-1 SST(I)=255 ;! ALL SEGMENTS UNCONNECTED LST(I)=LST(I)!X'7F00000000'; ! ALL SEGMENTS INACTIVE %REPEAT %CYCLE I=0,1,254 CBTA(I)_LINK=I+1 %REPEAT CBTASL=0 ASFREE=X'FFFFFFFF' ;! ALL FREE ASWAP=0 ASWIP=0 PROCACTAD1=X'28000004' PROCACTAD2=ADDR(PROC_ACTW0) ;! %INTEGERNAME DESCRIPTOR SUSP=0 ASDESTROY=0 ! 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) !----------------------------------------------------------------------- ! 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 ! BUT WRITE TO BOTH IST SEGMENTS ! MAPPED TOGETHER FOR SINGLE ! SINGLE PROCESSOR INSTALLATIONS ! SET UP DUMMY IST VECTOR *STLN_I ISTDUM_LNB=I ISTDUM_PSR=X'00140001' ISTDUM_PC=0 ISTDUM_SSR=X'01800BFE'; ! ONLY EVENT PENDING & SYSERR *STSF_I ISTDUM_SF=I ISTDUM_IT=MAXIT ISTDUM_IC=MAXIT ISTDUM_CTB=0 ! SET VS ERROR IST ENTRY *JLK_ ; *LSS_%TOS ; *ST_I ISTDUM_PC=I RECORD(X'80080000'+X'80')<-ISTDUM RECORD(X'800C0000'+X'80')<-ISTDUM ! SET INTERVAL TIMER IST ENTRY *JLK_ ; *LSS_%TOS ; *ST_I ISTDUM_PC=I RECORD(X'80080000'+X'A0')<-ISTDUM RECORD(X'800C0000'+X'A0')<-ISTDUM ! SET PROG ERROR IST ENTRY *JLK_ ; *LSS_%TOS ; *ST_I ISTDUM_PC=I RECORD(X'80080000'+X'C0')<-ISTDUM RECORD(X'800C0000'+X'C0')<-ISTDUM ! SET UP OUT IST ENTRY *JLK_ ; *LSS_%TOS ; *ST_I ISTDUM_PC=I RECORD(X'80080000'+X'100')<-ISTDUM RECORD(X'800C0000'+X'100')<-ISTDUM ! SET INSTRUCTION COUNTER IST ENTRY *JLK_ ; *LSS_%TOS ; *ST_I ISTDUM_PC=I RECORD(X'80080000'+X'160')<-ISTDUM RECORD(X'800C0000'+X'160')<-ISTDUM ! SET SYSTEM CALL IST ENTRY ISTDUM_LNB=0 ISTDUM_PSR=X'00140001' ISTDUM_PC=SYSTEMCALL ISTDUM_SF=ADDR(PROCACTAD1) ISTDUM_IC=X'30000000'+SCTIENTRIES;! 64 BIT VECTOR DESCRIPTOR TO SCTI ISTDUM_CTB=SCTI0 RECORD(X'80080000'+X'E0')<-ISTDUM RECORD(X'800C0000'+X'E0')<-ISTDUM ! SET LOCAL CNTRLR REACTIVATE CONTEXT *STLN_I LSSNP1_LNB=I LSSNP1_PSR=X'00140001' *JLK_ ; *LSS_%TOS ; *ST_I LSSNP1_PC=I LSSNP1_SSR=X'01800BFE' *STSF_I LSSNP1_SF=I LSSNP1_IT=MAXIT LSSNP1_IC=MAXIT LSSNP1_CTB=0 %FINISH !----------------------------------------------------------------------- ! SET UP DIRECTOR CONTEXT NEWSTK=LSTKSSN(1)<<18 SSNP1==RECORD(NEWSTK!X'40000') SSNP1=0 SSNP1_LNB=NEWSTK SSNP1_PSR=X'00040001'!DIRACR<<20 ;! 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 ! WORD 31 : INITIALLY SET TO DIROUTPAD FOR DIRECTOR. THEN USED BY ! BY DIRECTOR FOR COUNT OF KINSTRNS ! 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'0004FF01'!DIRACR<<20 ;! 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=SIGOUTPAD DIROUTP_P5=SCTI0 DIROUTP_P6=0 SIGOUTP_DEST=LSTLEN SIGOUTP_SRCE=SSTAD SIGOUTP_P1=ADDR(CBTASL) SIGOUTP_P2=CBTAD 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 *LSS_X'01800FFF' ;! NO SYSTEM ERROR INTS *ST_(3) LSSNP1P=LSSNP1 ;! LOCAL CONTROLLER REACTIVATE CONTEXT ! ! TO RETURN TO KERNEL REACTIVATE LOCAL CONTROLLER WITH EP SET ! THIS HORRENDOUS PROCEDURE WORKS SINCE WE ARE CERTAIN THAT:- ! 1) II (INSTRUCTION INCOMPLETE) IS NOT SET IN LC CONTEXTJUST SET ! 2) ALL OTHER INTERUPTS ARE MASKED ! HENCE EFFECT IS OF AN "OUT" TO KERNEL !!! ! WILL WORK OK FOR MULTIPROCESSORS (UNLIKE ACTIVATING BACK) ! *LXN_PROCACTAD2 *LSD_(%XNB+0) *OR_X'0000000100000000' *SLSD_0; ! LC STACK ADDRESSS (0) NOT PARAMETERISED *ST_%TOS ? *LSS_(6) ;? *ST_IC ;? *LSS_(5) ;? *ST_IT ? LCIC=LCIC+MAXIT-IC ? LCIT=LCIT+MAXIT-IT *ACT_%TOS *IDLE_X'B00B' !----------------------------------------------------------------------- ENTERI:*JLK_%TOS ! NORMAL LOCAL CALLS ENTER HERE SUPPOFF(SERV0,P); ! OBTAIN PARAMETER RECORD ->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 ! SET UP SSN+1 CONTEXT ADDRESSES K=INTEGER(LSTVAD+12); ! SEG 1 REAL ADDRESS %CYCLE I=1,1,LSTKN J=LSTKSSN(I) %IF J#0 %THEN INTEGER(LSTVAD+12+8*J)=K+I*X'80' %REPEAT INTEGER(LSTVAD+4+8*DIRCSEG)=INTEGER(LSTVAD+4)+8 SEMAHELD=0 PROC_STATUS=PROC_STATUS&X'FFFFFFFE' SSNP1==RECORD(PROC_STACK!X'40000') ;! PROCESS CONTEXT %IF SSNP1_IT&X'FF800000'=0 %THEN %START LPIT=LPIT-SSNP1_IT ACNT_LTIME=ACNT_LTIME-COM_ITINT*SSNP1_IT ;! UNUSED TIME %FINISH SSNP1_IT=TIMESLICE ;! START NEW TIMESLICE LPIT=LPIT+TIMESLICE ACNT_LTIME=ACNT_LTIME+COM_ITINT*TIMESLICE XSTROBE=0 PTEPS=0 PTP=0 EPN=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 ! ! COUNT ACTIVATIONS TO PROCESS ! ? %IF PROC_STATUS&4=0 %THEN FLPN=FLPN+1 %ELSE BLPN=BLPN+1 ? *LSS_(6) ;? *ST_IC ;? *LSS_(5) ;? *ST_IT ? LCIC=LCIC+MAXIT-IC ? LCIT=LCIT+MAXIT-IT *LXN_PROCACTAD2; ! ADRRESS OF ACTIVATE WORDS *ACT_(%XNB+0) !----------------------------------------------------------------------- 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 %IF I=X'FFFE' %THEN %START *OUT_99; ! CRASH WITH MASKED OUT INT %FINISH %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(1): ! DISC READ FAILS PEPARM=P_P2!18; ! TOP 22 BITS ARE VIRTADDR OF PAGE ->PE ASYN0(2):! RELEASE ACTIVE BLOCKS DEACTIVATE(\ASFREE) PROC_STATUS=PROC_STATUS!8 ->RESUSP !----------------------------------------------------------------------- ASYN0(3):! PROCMON PAGE-IN FAILURE ->RESUSP !----------------------------------------------------------------------- VSERRI:*JLK_%TOS ! VIRTUAL STORE INTERRUPTS ENTER HERE *LSS_%TOS *LSS_%TOS ;! PARAMETER *ST_VSPARM %IF VSPARM<0 %THEN PEPARM=9 %AND ->PE VSSEG=VSPARM>>18 %IF 0>32&127 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("VS ERROR ON SIGNAL STACK PARM=".STRHEX(VSPARM)." ") ->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 ->OLDPTP %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:! REMEMBER PAGE TABLE EPAGE STOREX ST==STORE(STOREX) ST_LINK=PTP ;! LIST OF PAGE TABLE PAGES PTP=STOREX PTAD=ST_REALAD EPN=EPN+1 PTEPS=256 OLDPTP:LST(VSSEG)=LST(VSSEG)!X'0000000080000001'!PTAD %IF VSSEG>HIGHSEG %THEN HIGHSEG=VSSEG PTEPS=PTEPS-SEGLEN PTAD=PTAD+((SEGLEN*EPAGESIZE+1)//2)<<3 ;! 8 BYTE BOUNDARY ! ! 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 ;! BLOCK NOT ACTIVE %IF TSTPTR&127=127 %THEN %START ;! SEGMENT NOT ACTIVE %IF ASFREE=0 %THEN %START ;! NO FREE SLOTS %IF ASWIP=0 %THEN DEACTIVATE(ASWAP) %ELSE DEACTIVATE(ASWIP) %FINISH *LSS_ASFREE *SHZ_ASP TSTPTR=ASP INTEGER(LSTVAD+8*VSSEG)=INTEGER(LSTVAD+8*VSSEG)&X'FFFFFF80'!ASP ASEG(ASP)=VSSEG AS(ASP)=0 ASB=TOPBIT>>ASP ASWIP=ASWIP!ASB ;! INSERT BIT ASFREE=ASFREE&(\ASB) ;! REMOVE BIT %FINISH POUT_DEST=X'80001' ;! GET AMTX POUT_SRCE=0 POUT_P1=PROCESS POUT_P2=CBT_DA POUT_P3=CBT_AMTX<<16!CBT_TAGS ;! NEW BITS<<16 ETC. ? *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 %IF POUT_P2<=0 %THEN ->AMTXSW(POUT_P2) CBT_AMTX=POUT_P2 CBT_TAGS=CBT_TAGS!X'20' %FINISH POUT_DEST=X'40001' ;! PAGETURN/PAGE-IN POUT_SRCE=ME!X'8000000A' ;! REPLY TO ACTIVITY 10 POUT_P1=CBT_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 PTE=X'80000001'!POUT_P2 %AND ->ACT10 PROC_STATUS=PROC_STATUS!2 ;! DEMAND PAGE PRIORITY ->RETURN !----------------------------------------------------------------------- ACTIVITY(10):! EPAGE HERE ! P_P1=RUBBISH IDENT ! P_P2=STORE(EPAGE)_REALAD ! VSSEG & VSEPAGE & TSTPTRSTILL INTACT !! EPH:PROC_STATUS=PROC_STATUS&X'FFFFFFFFD' PTE=X'80000001'!P_P2 ACT10:ASP=TSTPTR AS(ASP)=AS(ASP)!LTOPBIT>>VSEPAGE ASB=TOPBIT>>ASP ASWAP=ASWAP!ASB ASWIP=ASWIP&(\ASB) EPN=EPN+1 ACNT_PTURNS=ACNT_PTURNS+1 !PT==ARRAY(VIRTAD+LST(VSSEG)&X'0FFFFFF8'+VSEPAGE*EPAGESIZE<<2,PTF) !%CYCLE I=0,1,EPAGESIZE-1 ! PT(I)=PTE+I<<10 !%REPEAT ! ASSUMES EPAGESIZE=4 I=VIRTAD+LST(VSSEG)&X'0FFFFFF8'+VSEPAGE*16 *LXN_I *LSS_PTE ; *ST_(%XNB+0) *IAD_1024 ; *ST_(%XNB+1) *IAD_1024 ; *ST_(%XNB+2) *IAD_1024 ; *ST_(%XNB+3) ->ACTIVATE !-------------------------------------------- ACTIVITY(11): ! PAGE READ FAILURE PROC_STATUS=PROC_STATUS&X'FFFFFFFD' %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 !----------------------------------------------------------------------- AMTXSW(0):! CHANGE BLOCK SIZE IN SITU ? WAIT(2,1) ;! TRY AGAIN IN 1 SEC ->RETURN AMTXSW(-1):! NO AMT CELLS AVAILABLE AMTXSW(-2):! NOT ENOUGH GARBAGE DEACTIVATE(\ASFREE) ->ACTIVATE AMTXSW(-3):! CHANGE BLOCK SIZE WHEN STILL IN USE PEPARM=19 ->PE !----------------------------------------------------------------------- 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 ;! EIGHTH OF TIME SLICE LPIT=LPIT+TIMESLICE>>3 ACNT_LTIME=ACNT_LTIME+COM_ITINT*(TIMESLICE>>3) ->ACT %FINISH 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 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=EPN ;! EPAGES USED SO FAR PON(POUT) ->RETURN %FINISH EPLIM=POUT_P1 RTLIM=POUT_P2 PARTALLOC=POUT_P3 RTN=0 STROBE %FINISH %ELSE %START I=CATTAB(PROC_CATEGORY)_STROBEI %IF I#0 %AND RTN-(RTN//I)*I=0 %THEN STROBE %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: PROC_STATUS=PROC_STATUS!2; ! SET PRIORITY BIT PON(POUT) PROC_STATUS=PROC_STATUS!!2; ! UNSET PRIORITY BIT ->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 ->ACTIVATE %FINISH POUT_DEST=X'3000D' ;! WAIT FOR MORE POUT_P1=PROCESS SCHEDULE(POUT) %IF POUT_P1=0 %THEN ->RETURN %ELSE ->DEAD %FINISH %IF XSTROBE=1 %THEN %START STROBE %IF EPNACTIVATE ;! GOT SOME BACK ! %FINISH %IF EPLIMACTIVATE %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 ->ACTIVATE !----------------------------------------------------------------------- PROGERRI:*JLK_%TOS ! PROGRAM ERROR INTERRUPTS ENTER HERE *LSS_%TOS *LSS_%TOS *ST_PEPARM PE: 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("PROGRAM ERROR ON SIGNAL STACK CLASS="%C .STRINT(PEPARM&255)." SUBCLASS=".STRINT(PEPARM>>8&255)." ") ->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_OUTN %IF 0<=OUTN<=MAXDIROUT %THEN %START %IF INTEGER(J!X'40004')>>20&X'F'<=MAXOUTACR %THEN ->DIROUT(OUTN) %FINISH FREACT:! OUT INVALID, OUTN=19: SWOPFROM SIGNAL STACK %IF OUTN=19 %THEN SIGOUTP_DEST=-1 %ELSE DIROUTP_DEST=-1 ->ACTIVATE REACT:! OUT VALID DIROUTP_DEST=0 ->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): DEACTIVATE(\ASFREE) 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<=VSSEG>32&127 %IF TSTPTR#127 %THEN ASOUT(TSTPTR) ASDESTROY=0 LST(VSSEG)=LST(VSSEG)&X'FFFFFFFF00000000' ->REACT !----------------------------------------------------------------------- DIROUT(4):! DISCONNECT BLOCK, DIROUTP_P1=CBTX ->FREACT !----------------------------------------------------------------------- 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=EPN ;! 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 ->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(5)+(I-1)*X'80'; ! USE USERSTACK SSN+1 TO GET ACRS ->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 %CYCLE I=0,1,7 RECHECK:K=INTEGER(DIROUTPAD+4*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=PROC_ACTW0!DIROUTP_P5<<4>>28 ;! LSTBR!ACR DIROUTP_P6=PROC_LSTAD ->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 ->FREACT DIROUT(21):! DISABLE PROCMON ->FREACT ACTIVITY(16):! DISABLE COMPLETED ->REACT DIROUT(22):! PROCMON ON ->FREACT DIROUT(23):! PROCMON OFF ->FREACT DIROUT(24):! PROCMON INSERT TEXT ->FREACT 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 DIROUTP_P1>0 %AND CHECK RES(0,DIROUTP_P5,DIROUTP_P6)#0 %C %THEN ->FREACT %IF LOCKST=0 %THEN %START; ! NO SEG TABLE AROUND ->FREACT %UNLESS DIROUTP_P1>0 POUT_DEST=X'50000' 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 ? *LSS_(6) ;? *ST_IC ;? *LSS_(5) ;? *ST_IT RETURN EPAGE(POUT) ? *LSS_(5) ;? *ST_ITT ;? *LSS_(6) ;? *ST_ICC ? RETIT=RETIT+IT-ITT ;? LCIT=LCIT-IT+ITT ? RETIC=RETIC+IC-ICC ;? LCIC=LCIC-IC+ICC ? RETCALLN=RETCALLN+1 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 %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=CBT_AMTX<<16!EPX PAGETURN(POUT) %IF POUT_DEST=0 %AND DIROUTP_P1>0 %THEN MONITOR("LOCK GOES WRONG?") %REPEAT DIROUTP_P5=PROC_ACTW0 DIROUTP_P6=LOCKST&X'0FFFFFF0' ->REACT !----------------------------------------------------------------------- DIROUT(26):! CHANGE CONTEXT CLEAR ACCESSED BITS XSTROBE=1 ->ACTIVATE DIROUT(27): ! EXIT TO NOMINATED ENV(SAME STK) ! DIROUTP_P1-5==LNB->SF K=PROC_STACK ->FREACT %UNLESS K=DIROUTP_P1>>18<<18=DIROUTP_P5>>18<<18 K=K+X'40000' %CYCLE I=0,4,16 INTEGER(K+I)=INTEGER(ADDR(DIROUTP)+8+I) %REPEAT ->ACTIVATE !----------------------------------------------------------------------- DIROUT(28): ! HARD STORE ERROR IN PROCESS ! FROM ROUTINE SYSERR PEPARM=20 ->PE !----------------------------------------------------------------------- ICOUNTERI:*JLK_%TOS ! INSTRUCTION COUNTER INTERRUPTS ENTER HERE - STACK NOT SWITCHED YET !!! *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 SST(SEG)=CBTASL LL=X'40000380'!ACC<<20!(LEN*EPAGESIZE-1)<<10 LST(SEG)=LST(SEG)&X'800C007F00000000'!LL<<32 %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 ACC&X'100'=0 %THEN CBT_AMTX=X'FFFF' %ELSE CBT_AMTX=0 CBT_TAGS=L-1 CBT_LINK=CBTASL %REPEAT CBT_LINK=255 %END !----------------------------------------------------------------------- %ROUTINE ASOUT(%INTEGER ASP) %RECORDNAME CBT(CBTF) %INTEGERARRAYNAME PT %INTEGER MARK,VSSEG,VSEPAGE,SH,BLEN,PBLENS,ASB,POFL,I %LONGINTEGER MASK VSSEG=ASEG(ASP) %IF AS(ASP)=0 %THEN ->NOP PT==ARRAY(VIRTAD+LST(VSSEG)&X'0FFFFFF8',PTF) CBT==CBTA(SST(VSSEG)) BLEN=CBT_TAGS&X'F'+1 PBLENS=0 MASK=AS(ASP) VSEPAGE=-1 %WHILE MASK#0 %CYCLE *LSD_MASK ; *SHZ_SH ; *USH_1 ; *ST_MASK VSEPAGE=VSEPAGE+SH+1 %WHILE VSEPAGE>=BLEN+PBLENS %CYCLE PBLENS=PBLENS+BLEN CBT==CBTA(CBT_LINK) BLEN=CBT_TAGS&X'F'+1 %REPEAT !PAGE=VSEPAGE*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(VSEPAGE*EPAGESIZE)) *LXN_I *LSS_(%XNB+0) ; *OR_(%XNB+1) ; *OR_(%XNB+2) ; *OR_(%XNB+3) *ST_MARK *LSQ_0 *ST_(%XNB+0) %IF ASDESTROY=0 %THEN POFL=MARK<<3>>31<<3 %ELSE POFL=0 POUT_DEST=X'40002' ;! PAGETURN/PAGE-OUT POUT_P1=CBT_AMTX<<16!(VSEPAGE-PBLENS) 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 EPN=EPN-1 %REPEAT NOP:CBT==CBTA(SST(VSSEG)) %CYCLE %IF CBT_TAGS&X'20'#0 %THEN %START POUT_DEST=X'80002' ;! RETURN AMTX POUT_SRCE=0 POUT_P1=PROCESS POUT_P2=CBT_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 CBT_AMTX=POUT_P1>>16 ;! NEW BITS CBT_TAGS=CBT_TAGS&X'DF' %FINISH %IF CBT_LINK=255 %THEN %EXIT CBT==CBTA(CBT_LINK) %REPEAT LST(VSSEG)=LST(VSSEG)!X'7F00000000'; ! NOW MARKED AS INACTIVE ASB=TOPBIT>>ASP ASWAP=ASWAP&(\ASB) ASWIP=ASWIP&(\ASB) ! ! IT IS JUST POSSIBLE FOR A SEGMENT TO BE REACTIVATED AND BECOME ! INACTIVE AGAIN IN THE SAME RESIDENCE(EXTENDED ON THE FLY) TO ! PREVENT PREMATURE DISCARDING OF DRUM IN THIS RARE CASE REMOVE BIT ! FROM OLD ASIPS ! OLDASWIPS(0)=OLDASWIPS(0)&(\ASB) ASFREE=ASFREE!ASB %END !----------------------------------------------------------------------- %ROUTINE STROBE !*********************************************************************** !* WHIP THROUGH ALL THE ACTIVE PAGES IN EACH ACTIVE SEGMENT * !* ANY PAGES NOT REFERNECED ARE PAGED OUT. THE REFERENCE BITS ARE * !* CLEARED IN CASE THIS PAGES IS NOT USED FURTHER. * !* A CRITICAL ROUTINE FOR PERFORMANCE HENCE HAND CODING * !*********************************************************************** %RECORDNAME CBT(CBTF) !%INTEGERARRAYNAME PT; ! NOT USED IN HANDCODING ! %CONSTINTEGER USEMASK=X'DFFFFFFF' %CONSTLONGINTEGER DUSEMASK=X'DFFFFFFFDFFFFFFF' %INTEGER MARK,POFL,ASMASK,ASP,VSSEG,VSEPAGE,PTB,BLEN,PBLENS,ASB, %C PTEAD,I ?%INTEGER CAT %LONGINTEGER EPMASK ASMASK=ASWAP; ! ALL SLOTS WITH ACTIVE PAGES ASP=-1 ? CAT=PROC_CATEGORY ? STROBEN(CAT)=STROBEN(CAT)+1 ? STREPN(CAT)=STREPN(CAT)+EPN %WHILE ASMASK#0 %CYCLE; ! FOR EACH ACTIVE SEGMENT *LSS_ASMASK ; *SHZ_%B ; *USH_1 ; *ST_ASMASK *ADB_ASP; *ADB_1; *STB_ASP VSSEG=ASEG(ASP) CBT==CBTA(SST(VSSEG)) BLEN=CBT_TAGS&X'F'+1 PBLENS=0 EPMASK=AS(ASP) VSEPAGE=-1 PTB=VIRTAD+LST(VSSEG)&X'0FFFFFF8' ! PT==ARRAY(PTB,PTF) %WHILE EPMASK#0 %CYCLE; ! FOR EACH ACTIVE PAGE *LSD_EPMASK ; *SHZ_%B ; *USH_1 ; *ST_EPMASK *ADB_VSEPAGE; *ADB_1; *STB_VSEPAGE %WHILE VSEPAGE>=BLEN+PBLENS %CYCLE PBLENS=PBLENS+BLEN CBT==CBTA(CBT_LINK) BLEN=CBT_TAGS&X'F'+1 %REPEAT ! PAGE=EPAGE*EPAGESIZE ! MARK=0 ! %CYCLE I=PAGE,1,PAGE+EPAGESIZE-1 ! MARK=MARK!PT(I); ! GANG MARKERS TOGETHER ! PT(I)=PT(I)&USEMASK ! %REPEAT ! ! THIS HAND CODE ASSUMES THAT EPAGESIZE IS 4 ! PTEAD=PTB+16*VSEPAGE *LXN_PTEAD *LSD_(%XNB+0); *OR_(%XNB+2) *STUH_%B; *OR_%B *ST_MARK *LSD_(%XNB+0) ; *AND_DUSEMASK ; *ST_(%XNB+0) *LSD_(%XNB+2) ; *AND_DUSEMASK ; *ST_(%XNB+2) POFL=MARK<<3>>31<<3!1<<2 %IF MARK>>29&1=0 %THEN %START;! STROBE OUT ? STROUT(CAT)=STROUT(CAT)+1 POUT_DEST=X'40002'; ! PAGETURN/PAGE-OUT POUT_P1=CBT_AMTX<<16!(VSEPAGE-PBLENS) 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 ! ! THIS BIT OF HAND CODE ASSUMES EPAGESIZE=4 ! *LXN_PTEAD *LSQ_0 *ST_(%XNB+0) EPN=EPN-1 AS(ASP)=AS(ASP)&(\(LTOPBIT>>VSEPAGE)) %FINISH %REPEAT %IF AS(ASP)=0 %THEN %START ASB=TOPBIT>>ASP ASWAP=ASWAP&(\ASB) ASWIP=ASWIP!ASB %FINISH %REPEAT XSTROBE=XSTROBE+1 %END !----------------------------------------------------------------------- %ROUTINE WORKSET !*********************************************************************** !* PAGE OUT THE WORKING SET BY GOING THROUGH THE ACTIVE SEGMENT * !* LIST AND WRITING OUT ACTIVE EPAGES IN THAT SEGMENT * !*********************************************************************** %RECORDNAME CBT(CBTF) !%INTEGERARRAYNAME PT; ! NEEDED IN ALL IMP VERSION ONLY %INTEGER MARK,POFL,ASMASK,VSSEG,VSEPAGE,ASP,BLEN,PBLENS,I,J,PTB %LONGINTEGER EPMASK ASMASK=ASWAP ASP=-1 %WHILE ASMASK#0 %CYCLE; ! THROUGH ACTIVE SEGMENNTS *LSS_ASMASK; *SHZ_%B; *USH_1 *ST_ASMASK; *ADB_1; *ADB_ASP; *STB_ASP VSSEG=ASEG(ASP) CBT==CBTA(SST(VSSEG)) BLEN=CBT_TAGS&X'F'+1 PBLENS=0 EPMASK=AS(ASP) VSEPAGE=-1 PTB=VIRTAD+LST(VSSEG)&X'0FFFFFF8' ! PT==ARRAY(PTB,PTF) %WHILE EPMASK#0 %CYCLE *LSD_EPMASK; *SHZ_%B; *USH_1; *ST_EPMASK *ADB_1; *ADB_VSEPAGE; *STB_VSEPAGE %WHILE VSEPAGE>=BLEN+PBLENS %CYCLE PBLENS=PBLENS+BLEN CBT==CBTA(CBT_LINK) BLEN=CBT_TAGS&X'F'+1 %REPEAT ! PAGE=VSEPAGE*EPAGESIZE ! MARK=0 ! %CYCLE I=PAGE,1,PAGE+EPAGESIZE-1 ! MARK=MARK!PT(I); ! GANG MARKERS TOGETHER ! %REPEAT ! ! THIS HAND CODING ASSUMES EPAGESIZE=4 ! I=PTB+16*VSEPAGE *LXN_I *LSD_(%XNB+0); *OR_(%XNB+2) *STUH_%B; *OR_%B *ST_MARK POFL=MARK<<3>>31<<3!1<<2; ! WRIT & UPDATE DRUM POUT_DEST=X'40002'; ! PAGETURN/PAGE-OUT POUT_P1=CBT_AMTX<<16!(VSEPAGE-PBLENS) 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 EPN=EPN-1 %REPEAT AS(ASP)=0 %REPEAT ASWAP=0 ! ! SHUFFLE DOWN LIST OF OLD ASWIPS AND REMOVE ANY SEGMENTS NOT USED OVER ! "RESIDENCES" RESIDENCES PERIODS FROM ACTIVE LIST ! J=ASWIP&OLD ASWIPS(0) %CYCLE I=0,1,MAXRESIDENCES-1 J=J&OLD ASWIPS(I) %IF I RETURN PTS %END !----------------------------------------------------------------------- %ROUTINE CLEAR ACCESSED BITS !*********************************************************************** !* CALLED AFTER A "CHANGE CONTEXT" TO CLEAR THE USED BITS ON EACH * !* PAGE ACTUALLY IN CORE. THEREAFTER A STROBE OR EXTRA STROBE WILL * !* DISCARD ANY PAGES FROM THE OLD CONTEXT WITHOUT BOUNCING PROCESS * !*********************************************************************** !%INTEGERARRAYNAME PT; ! NOT USED IN HAND CODED VERSION %CONSTINTEGER USEMASK=X'DFFFFFFF' %CONSTLONGINTEGER DUSEMASK=X'100000000'*USEMASK!USEMASK %INTEGER ASMASK, PTB, VSEPAGE, ASP, I %LONGINTEGER EPMASK ASMASK=ASWAP; ! ACTIVE SLOTS WITH ACTIVE PAGES ASP=-1 %WHILE ASMASK#0 %CYCLE; ! FOR EACH ACTIVE SEGMENT *LSS_ASMASK; *SHZ_%B; *USH_1; *ST_ASMASK *ADB_ASP; *ADB_1; *STB_ASP VSSEG=ASEG(ASP) VSEPAGE=-1 EPMASK=AS(ASP) PTB=VIRTAD+LST(VSSEG)&X'0FFFFFF8' ! PT==ARRAY(PTB,PTF) %WHILE EPMASK#0 %CYCLE; ! FOR EACH ACTIVE PAGE *LSD_EPMASK; *SHZ_%B; *USH_1; *ST_EPMASK *ADB_VSEPAGE; *ADB_1; *STB_VSEPAGE ! PAGE=VSEPAGE*EPAGESIZE ! %CYCLE I=PAGE,1,PAGE+EPAGESIZE-1 ! PT(I)=PT(I)&USEMASK ! %REPEAT ! ! THIS HAND CODE ASSUMES EPAGESIZE=4 ! I=PTB+16*VSEPAGE *LXN_I *LSD_(%XNB+0); *AND_DUSEMASK; *ST_(%XNB+0) *LSD_(%XNB+2); *AND_DUSEMASK; *ST_(%XNB+2) %REPEAT %REPEAT %END !----------------------------------------------------------------------- %ROUTINE DEACTIVATE(%INTEGER MASK) !*********************************************************************** !* DEACTIVATE ALL ACTIVE SEGMENTS DEFINED BY BITMASK "MASK" * !*********************************************************************** %INTEGER ASP ASP=-1 %WHILE MASK#0 %CYCLE *LSS_MASK; *SHZ_%B; *USH_1; *ST_MASK *ADB_ASP; *ADB_1; *STB_ASP ASOUT(ASP) %REPEAT %END !----------------------------------------------------------------------- %ROUTINE RETURN PTS !*********************************************************************** !* RETURN ALL THE EPAGES USED FOR PAGE TABLES. THE LIST HEADED BY * !* "PTP" AND LINKED VIA THE STORE TABLE * !*********************************************************************** %WHILE PTP#0 %CYCLE POUT_P2=PTP PTP=STORE(PTP)_LINK ? *LSS_(6); ? *ST_IC; ? *LSS_(5); ? *ST_IT RETURN EPAGE(POUT) ? *LSS_(5); ? *ST_ITT; ? *LSS_(6); ? *ST_ICC ? RETIT=RETIT+IT-ITT; ? LCIT=LCIT-IT+ITT ? RETIC=RETIC+IC-ICC; ? LCIC=LCIC-IC+ICC ? RETCALLN=RETCALLN+1 %REPEAT %END !----------------------------------------------------------------------- %INTEGERFN FIND PROCESS %STRING(6) USER %INTEGER I,J,K,DACT,INCAR USER=STRING(PROC_STACK!X'40030') ;! IN OLD ACC J=INTEGER(PROC_STACK!X'4003C') INCAR=BYTEINTEGER(PROC_STACK!X'40037');! LAST BYTE = INCARNATION %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 %AND PROCA(I)_INCAR=INCAR %THEN %C DIROUTP_DEST=(I+K)<<16!DACT %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 !----------------------------------------------------------------------- %ROUTINE WAIT(%INTEGER DACT,N) POUT_DEST=X'A0002' POUT_SRCE=0 POUT_P1=ME!DACT POUT_P2=N PON(POUT) %END !----------------------------------------------------------------------- %END !----------------------------------------------------------------------- %END !*********************************************************************** !* THESE THREE ROUTINES ARE SYTEMCALLED DIRECTLY FROM USER * !*********************************************************************** %INTEGERFN REQUEST INPUT(%INTEGER OUTPUT POSN,TRIGGER POSN) %RECORDNAME IOSTAT(IOSTATF) %RECORDNAME DIROUTP(PARMF) IOSTAT==RECORD(X'140048') DIROUTP==RECORD(DIROUTPAD) %UNLESS IOSTAT_OUTBUFLEN>0 %AND 0<=OUTPUT POSN0 %AND 0<=TRIGGER POSN0 %AND 0<=OUTPUT POSN