! ! To make S series supervisor requires:- ! 1) Change SSERIES=NO to SSERIES=YES in ctoptions file ! ! ! 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 %CONSTINTEGER CBTLEN=299; ! LENGTH OF CBT TABLE %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=8*CBTLEN+255+2*LSTLEN; ! SIZE OF SAME ! MADE UP OF 2049 FOR CBT ! 2*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 %CONSTLONGINTEGER NONSLAVED=X'2000000000000000' %CONSTINTEGER MAXIT=X'FFFFFF' ! 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 SSTAD=CBTAD+8*CBTLEN; ! 2DRY SEG TABLE OF LSTLEN BYTES %CONSTINTEGER LSTVAD=0; ! VIRTUAL ADDRESS OF LOCAL SEG TABLE !----------------------------------------------------------------------- %RECORDFORMAT IOSTATF(%INTEGER IAD, %STRING (15) INTMESS, %INTEGER INBUFLEN,OUTBUFLEN,INSTREAM,OUTSTREAM) %RECORDFORMAT PARMF(%INTEGER DEST,SRCE,(%INTEGER P1,P2,P3,P4,P5,P6 %ORSTRING (6) USER, %BYTEINTEGER INCAR, %STRING (15) INTMESS)) %CONSTRECORD (PARMF) %NAME DIROUTP=DIROUTPAD %CONSTRECORD (IOSTATF) %NAME IOSTAT=X'140048' ! ! THESE ROUTINES MUST BE DEFINED VIA EXTERNALSPEC FOLLOWED BY EXTERNAL ! ROUTINE SO AS TO FORCE EXTERNAL ACCESS AT ALL CALLS. IF NOT CALLS ! MADE VIA THE SYSTEM CALL TABLE WILL BE FOR INTERNAL ACCESS AND ! THIS MAY BE DISASTEROUS ! %EXTERNALINTEGERFNSPEC REQUEST INPUT(%INTEGER OUTPUT POSN,TRIGGER POSN) %EXTERNALINTEGERFNSPEC REQUEST OUTPUT(%INTEGER OUTPUT POSN,TRIGGER POSN) %EXTERNALINTEGERFNSPEC CHANGE CONTEXT %LONGINTEGERFNSPEC RTDR(%INTEGERFN A) %EXTERNALROUTINE SUP29 !----------------------------------------------------------------------- %OWNSTRING (3) SUPID="29I" ! MAIN CHANGES FOR 26I !--------------------- ! 1) CHANGES FOR BETTER ACCESSING OF SEQUENTIAL FILES ! TOGETHER WITH REDUCTION IN STROBING ! 2) CHANGES TO PREPAGING LC STACK TO AVOID USING PPCELLS ! 3) PENALISING PROCESS WITH LOTS OF P4 TO P4 TRANSITIONS ! MAIN CHANGES FOR 26J ! -------------------- ! 1) CHANGE TO IMP80 ! MAIN CHANGES FOR 27A ! 1) STORE LIST NOW CONSTRUCTED BY CHOPSUPE ! ! MAIN CHANGES FOR 27B ! 1) INDIVIDUAL TIMEOUTS ON SNOOZING ! ! ! MAIN CHANGES FOR 27C ! 1) CORRECTIONS AND EXTENSIONS TO CODE FOR SPLITTING A DUAL ! SERVICE TO A SINGLE SERVICE AND A DEVLOPMENT M-C ! ! MAIN CHANGES FOR 27D ! 1) CHANGE TO SCHEDULE FOR SMOOTHER TRANSITION FROM SNNOZING ! TO NON-SNOOZING AS LOAD INCREASE PAST OPTIMUM ! ! MAIN CHANGES FOR 27E ! 1) CHANGE TO COLLECTION OF TIMING INFORMATION TO ALLOW ACCESS ! FROM A PRIVILEGED PROCESS ! 2) ON A PAGE FAULT IF A SEGMENT APPEARS TO BE BEING ACCESSED ! SEQUENTIALLY A LOWER NUMBERED PAGE IS REMOVED FROM THE ! WORKING SET. ! ! MAIN CHANGES FOR 27F ! 1) SETTING NONSLAVED BITS ON CONFIGURING IN AN OPC SINCE THE ! IPL MIGHT HAVE BEEN DONE ON A SINGLE! ! MAIN CHANGES FOR 27G ! 1) CHANGES TO SNOOZING TO OMIT READ ONLY PAGES FROM SNOOZ SET ! WHEN STORE IS BUSY PRIOR TO ABANDONING SNOOZING ALLTOGETHER ! MAIN CHANGES FOR 27H ! 1) REMOVING CHANGE 1 OF 27G AFTER DEVASTATING ERTE FIGURES ! 2) IN PROCESS VS MONITORING VIA OUT20 ! MAIN CHANGES FOR 27I ! 1) DIRECT CALLS OF COMMS CONTROLLER FROM REQUEST OUTPUT ! MAIN CHANGES FOR 27J ! 1) DEDICATED FLAG (RECONFIGURE=YES/NO) FOR CONDITIONAL COMPILATION ! OF RECONFIGURE CODE. ! Main changes for 28A ! 1) Fully "S" series compatible. ! 2) Report to OPER on illegal system call ! MAIN CHANGES FOR 28B ! 1) USES THE MULTIPLE CONNECTS BIT IN DRUM WSET COMPUTATION ! 2) REVISION TO SCHEDULING OF P4 JOBS ! Main changes for 28C ! 1) Uses the new GPC/DCU driver 'GDC' ! ! MAIN CHANGES FOR 28D ! 1) CORRECTION TO CLEAR CODE TO STOP FILES BEING RECONNECTED ! BEFORE ALL THE CLEARS HAVE BEEN COMPLETED AND TO PREVENT ! CLEARS OVERWRITING VALID DATA. ! 2) INCORPORATION OF CONDITIONAL "DAP" CODE ! Main changes for 28E ! 1) Changes to multi OCP code to handle dual "S" series processors ! 2) Change to insist on day of week in "DT" command ! 3) Addition of FEDOWN command ! ! Main changes for 29a ! 1) Chanegs to Dap Driver for better interactive access ! MAIN CHANGES FOR 29B ! 1) "DIRECT" STACK MOVED UP 100 EPAGES TO ALLOW MORE FIXED SITES ! MAIN CHANGES FOR 29C ! 1) DAP DRIVER ADAPTED FOR MULTIPLE DAPS ! ! MAIN CHANGES FOR 29D ! 1) DPA DRIVER TIMES OUT DUD DAPS AND GEN RESSES THEM ! ! Main changes for 29F ! 1) Clears store to remove parities when configuring on a SMAC ! 2) Periodically checks that 'other' OCP is still awake ! ! Main changes for 29G ! 1) Dap now restarts at once after check for file syncronising ! 2) L-C Stacks page 0 into proper smac not dap after uncured problems ! with OCP claiming SSN+1 not resident when its in Dap store. ! ! Main changes for 29H ! 1) Schedule now more inclined to give more store on the fly. ! A result of running out of transfer capacity on 2976s at busy times ! means paging out further people is akin to hari-kiri. ! ! Main changes for 29i ! 1) Change to configuring off DAP. People on the Priority queus ! dont get the Async pon to free lc stack until dont sched reset ! which causes a big delay at peak times ! %CONSTSTRING (3) CHOPID="22B"; ! EARLIEST COMPATABLE CHOPSUPE !----------------------------------------------------------------------- !* !* Communications record format - extant from CHOPSUPE 22B onwards * !* %RECORDFORMAT CDRF(%BYTEINTEGER IPDAPNO,DAPBLKS,DAPUSER,DAPSTATE, %INTEGER DAP1,DAPINT) %RECORDFORMAT COMF(%INTEGER OCPTYPE,SLIPL,SBLKS,SEPGS,NDISCS,DLVNADDR,(%INTEGER GPCTABSIZE, GPCA %ORINTEGER DCUTABSIZE,DCUA), %INTEGER SFCTABSIZE,SFCA,SFCK,DIRSITE,DCODEDA,SUPLVN,TOJDAY,DATE0,DATE1,DATE2, TIME0,TIME1,TIME2,EPAGESIZE,USERS,CATTAD,SERVAAD, %BYTEINTEGER NSACS,RESV1,(%BYTEINTEGER SACPORT1, SACPORT0 %ORBYTEINTEGER OCP1 SCU PORT,OCP0 SCU PORT), %BYTEINTEGER NOCPS,SYSTYPE,OCPPORT1,OCPPORT0, %INTEGER ITINT,(%INTEGER CONTYPEA,GPCCONFA,FPCCONFA,SFCCONFA %ORINTEGER DCU2HWNA,DCUCONFA,MIBA,SP0), %INTEGER BLKADDR,RATION,(%INTEGER SMACS %ORINTEGER SCUS), %INTEGER TRANS, %LONGINTEGER KMON, %INTEGER DITADDR, SMACPOS,SUPVSN,PSTVA,SECSFRMN,SECSTOCD,SYNC1DEST,SYNC2DEST,ASYNCDEST,MAXPROCS,INSPERSEC,ELAPHEAD,COMMSRECA, STOREAAD,PROCAAD,SFCCTAD,DRUMTAD,TSLICE,FEPS,MAXCBT,PERFORMAD, %RECORD (CDRF) %ARRAY CDR(1:2), %INTEGER LSTL,LSTB, PSTL,PSTB,HKEYS,HOOT,SIM,CLKX,CLKY,CLKZ,HBIT,SLAVEOFF,INHSSR,SDR1,SDR2,SDR3,SDR4,SESR,HOFFBIT,BLOCKZBIT,BLKSHIFT, BLKSIZE,END) ! ! This format describes "The Communication Record" which is kept ! locked in store at Public address X'80C00000'. It is readable at ! all ACR levels but writeable at ACR 1 only. Its purpose is to describe ! the hardware on which the EMAS System is running. Each entry is now ! described in more detail:- ! ! OCPTYPE The 2900 Processor on this configuration as follows ! 1 = 2950 (S1) ! 2 = 2960 (P2) or 2956 (S2) ! 3 = 2970 (P3) or 2966 (S3) ! 4 = 2980 (P4) ! 5 = 2972 or non-interleaved 2976 (P4/1) ! 6 = Interleaved 2976 (P4/1) ! ! SLIPL bit 0 is set to 1 to force an AUTO IPL from RESTART. ! bits 1-15 are the SLOAD lvn & site >>4. ! (equivalent to the handkey settings for AUTO IPL). ! bits 16-31 are thehe port/trunk/stream(or DCU/stream) of the ! device used at IPL time. ! SBLKS The no of 128k blocks of main store present ! SEPGS The no of extended pages for paging(ie not including ! any pages occupied by resident code & data). ! NDISCS Then number of EDS drives avaliable ! DLVNADDR The address of an array which maps disc lvns to ! their ddt slots. ! GPCTABSIZE The size in bytes of the GPC (or DCU) table ! GPCA The address of the GPC (or DCU) table ! SFCTABSIZE The size of the SFC(ie DRUM) table ! SFCA The address of the SFC table ! SFCK The number of (useable) 1K page frames of Drum store ! available for paging.(0 = No drum configuration) ! DIRSITE The Director site address(eg X200) no longer reqd? ! DCODEDA The Disc Address of the Director (expressed as ! SUPLVN<<24!DIRSITE) ! SUPLVN The logical volume no of the disc from which the ! Sytem was "SLOADED". Various System components (eg ! DIRECT, VOLUMS will page from here ! ! TOJDAY Todays (Julien) day number. ! DATE0} These three integers define the current date(updated at ! DATE1} at 2400) as a character string such that ! DATE2} the length byte is in the bottom of DATE0 ! ! TIME0} These three integers define the clock time as a string ! TIME1} in the same format as for DATE. The time is updated ! TIME2} about every 2 seconds ! ! EPAGESIZE The number of 1K pages combined together to make up ! the logical "Extended Page" used in Emas.Currently=4 ! USERS The number of user processes (foreground+background) ! currently in existence.Includes DIRECT,VOLUMS&SPOOLR ! CATTAD Address of maxcat followed by category table. ! SERVAAD The address of the service array SERVA. ! NSACS The number of sacs found at grope time ! SACPORT1} Holds the Port no of the Store Access Controller(s) ! SACPORT0} found at grope time. SACPORT0 was used to IPL system. ! NOCPS The number of OCPS found at grope time. ! SYSTYPE System infrastructure: ! 0 = SMAC based ! 1 = SCU based (SCU1) ! 2 = SCU based (SCU2) ! OCPPORT1} Hold the Port no of the OCPs found at grope time. ! OCPPORT0} OCPPORT0 was used to IPL the system. ! ITINT The Interval Timer interval in microsecs. Varies ! between different members of the range ! CONTYPEA The address of a 31 byte area containing the codes ! of the controllers in port-trunk order. Codes are:- ! 0 = Not relevant to EMAS ! 1 = SFC1 ! 2 = FPC2 ! 3 = GPC1 ! ! GPCCONFA} These three variables each point to a word array ! FPCCONFA} containing controller data. The first word in each ! SFCCONFA} case says how many controllers on the system. The ! remainder have Port&Trunk in top byte and Public ! segment no of comms segment in bottom byte. For GPCS ! the Public Seg no is apparently omitted! ! BLKADDR The address of first element of a word array bounds ! (1:SBLKS) containing the real address of each 128K ! block of main store. Real addresses are in the form ! RSN/SMAC NO/Address in SMAC ! RATION Information maintained by DIRECT concerning access ! rationing. Bytes from left indicate scarcity, ! pre-empt point, zero and interactive users ! respectively ! SMACS Bits 0-15 are a map of SMACS in use by the system. ! 2**16 bit set if SMAC0 in use etc. ! Bits 16-31 are a map of SMACS found at grope time. ! 2**0 bit set if SMAC0 found etc. ! TRANS The address of a 768 byte area containing 3 translate ! tables. The first is ISO to EBCDIC, the second the ! exact converse & the third is ISO to ISO with ! lower to upper case conversion. ! KMON A 64 bit bitmask controlling monitoring of Kernel ! services. Bit 2**n means monitor service n. Bits can ! be set by Operator command KMON. ! DITADDR Disc index table address. The address of first ! element of an array(0:NDISCS-1) containing the address ! of the disc device entries. ! SMACPOS The no of places that the Smac no must be left ! shifted to be in the right position to access ! a Smac image store location. Incredibly this varies ! between the 2980 and others!! ! SUPVSN The Supervisor id no as a three char string eg 22A ! PSTVA The virtual address of the Public Segment table which ! is itself a Public segment. All other information ! about PST can be found by looking at its own PST entry ! SECSFRMN The no of Seconds since midnight. Updated as for TIME ! SECSTOCD The number of seconds to System closedown if positive ! If zero or negative no close down time has yet been ! notified. Updated as for TIME ! SYNC1DEST} These are the service nos N2,N3 & N4 for process ! SYNC2DEST} parameter passing described in Supervisor Note 1 ! ASYNCDEST} ! MAXPROCS The maximum number of paged processes that the ! Supervisor is configured to run. Also the size ! of the Process array. ! INSPERSECS The number of instructions the OCP executes in 1 ! second divided by 1000(Approx average for EMAS) ! ELAPHEAD The head of a linked list of param cells holding ! service with an elapsed interval interrupt request ! outstanding ! COMMSRECA The address of an area containing details of the ! Communication streams.(private to COMMS Control) ! STOREAAD The address of first element of the store record array ! bounds (0:SEPGS-1) ! PROCAAD The address of first element of the process record ! array bounds(0:MAXPROCS) ! SFCCTAB} The addresses of two private tables provided by grope ! DRUMTAD} for use by the routine DRUM. They give details of ! the SFCS and DRUMS found on the system ! TSLICE Time slice in microsecs. Supervisor has to allow for ! differences in interval timer speeds accross the range ! FEPS Bits 0-15 are a map of FEPs found at grope time. ! 2**16 bit set if FE0 found etc. ! Bits 16-31 are a map of currently available FEPs. ! 2**0 bit set if FE0 available etc. ! MAXCBT Maximum cbt entry ! PERFORMAD Address of record holding timing information and counts ! for performance analysis. ! IPDAPNO PORT & SMAC number for the DAP ! DAPBLKS The number of 128K blocks in DAP ! DAPUSER The PROCESS currently holding the DAP ! DAPSTATE The state of the DAP ! DAP1 DAP control fields ! DAPBMASK Bit map of currently allocated DAP blocks ! SP1->SP3 Spare locations ! LSTL} ! LSTB} ! PSTL} ! PSTB} These are the image store addresses for the following ! HKEYS} control registers:- ! HOOT} Local Segment Table Limit & Base ! SIM } Public Segment Table Limit & Base ! CLKX} Handkeys,Hooter System Interrupt Mask Register ! CLKY} and the clock X,Y & Z Registers ! CLKZ} ! HBIT A bit pattern that when ORed into Control Register ! "HOOT" operates the Hooter.(0=Hooterless machine) ! SLAVEOFF A bit pattern (top 16 bits) and Image store address ! in bottom 16 bits. ORing the top 16 bits(after ! shifting) into the image store will stop all slaving of ! operands but not instructions ! INHSSR A bit pattern and image location as for SLAVEOFF. ! ORing the bits into the location will switch off ! reporting of successful system retry ! SDR1} ! SDR2} The image store addresses of SMAC internal registers ! SDR3} needed by the Engineers after Smac errors have ! SDR4} occurred ! SESR} ! HOFFBIT A bit pattern that when ORed into a Smac Engineers ! status register will stop reporting of error ! from that Smac ! ! BLOCKZBIT A bit pattern indicating the position of ! the block zero bit in the SMAC config register. ! ! BLKSHIFT Indicates which way to shift the BLOCKZBIT mask ! to correspond with subsequent store blocks. ! ! BLKSIZE Store block size. ! %CONSTRECORD (COMF) %NAME COM=X'80000000'+48<<18 %CONSTINTEGER VIRTAD=X'81000000'; ! CAN NOT BE USED IF PAGE FLAWED %CONSTINTEGER PUBSEG=X'80000000',SEG64=X'01000000' COM_MAXPROCS=MAXPROCS %CONSTINTEGER EPAGESHIFT=12; ! 4*1024==1<<12 %CONSTINTEGER SEGEPSIZE=256//EPAGESIZE !----------------------------------------------------------------------- ! 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 PKMONREC(%STRING (20) TEXT, %RECORD (PARMF) %NAME P) %EXTERNALROUTINESPEC MONITOR(%STRING (63) S) %EXTERNALROUTINESPEC OPMESS(%STRING (63) S) %EXTERNALROUTINESPEC DISPLAY TEXT(%INTEGER SCREEN,LINE,CHAR, %STRING (41) S) %EXTERNALROUTINESPEC UPDATE TIME %EXTERNALROUTINESPEC DPONPUTONQ(%RECORD (PARMF) %NAME P) %EXTERNALROUTINESPEC TURNONER(%RECORD (PARMF) %NAME P) %EXTERNALROUTINESPEC DUMP TABLE(%INTEGER TABNO,ADR,LEN) %IF SFCFITTED=YES %THENSTART %ROUTINESPEC BAD DRUM PAGE(%INTEGER DTX) %EXTERNALROUTINESPEC DRUM(%RECORD (PARMF) %NAME P) %INTEGER DRUMSIZE,DRUMTASL,DRUMT ASL BTM,DRUMALLOC %FINISH %IF CSU FITTED=YES %START %EXTERNALROUTINESPEC CSU(%RECORD (PARMF) %NAME P) %FINISH %IF MULTIOCP=YES %THENSTART %INTEGERFNSPEC REMOTE ACTIVATE(%INTEGER PORT,AD) %EXTERNALROUTINESPEC CHECK OTHER OCP %EXTERNALROUTINESPEC HALT OTHER OCP %EXTERNALROUTINESPEC RESTART OTHER OCP(%INTEGER MODE) %EXTERNALROUTINESPEC CLOCK TO THIS OCP %IF SSERIES=YES %START %EXTERNALROUTINESPEC DCU1 RECOVERY(%INTEGER PARM) %FINISH %FINISH %IF MONLEVEL&4#0 %START %LONGINTEGERNAME IDLEIT,NOWORKIT,LCIT,FLPIT,BLPIT,PTIT,DRUMIT,PDISCIT,RETIT,AMIT %LONGINTEGERNAME LCIC,PTIC,DRUMIC,PDISCIC,RETIC,AMIC %INTEGERNAME IDLEN,NOWORKN,LCN,FLPN,BLPN,PTCALLN,DRUMCALLN,PDISCCALLN,RETCALLN,AMCALLN %FINISH %HALFINTEGERNAME FSTASL,BSTASL %INTEGER I,J,K,FREEEPAGES,SHAREDEPS,UNALLOCEPS,OVERALLOC,MAXP4PAGES,P4PAGES,SXPAGES,NPQ,OLDLNB,IDLE,DONT SCHED, SMAC RCONFIG,SMACRPAGES,MPLEVEL,PAGEFREES,DCLEARS,GETEPN,PREEMPTED,MAX OVERALLOC,SNOOZTIME,SAC MASK %LONGINTEGER L,STKPSTE %STRING (3) STRPROC !----------------------------------------------------------------------- ! CONFIGURATION DECLARATIONS %BYTEINTEGERARRAYNAME CONTYPE %BYTEINTEGERARRAYFORMAT CONTYPEF(0:31) CONTYPE==ARRAY(COM_CONTYPEA,CONTYPEF) %INTEGERARRAYNAME BLOCKAD %INTEGERARRAYFORMAT BLOCKADF(0:127); ! ALLOW UP TO 16 MEGABYTES BLOCKAD==ARRAY(COM_BLKADDR,BLOCKADF) !----------------------------------------------------------------------- %RECORDFORMAT SSNP1F(%INTEGER LNB,PSR,PC,SSR,SF,IT,IC,CTB,XNB,B,DR0,DR1,A0,A1,A2,A3,PEAD,II) %RECORDFORMAT ISTF(%INTEGER LNB,PSR,PC,SSR,SF,IT,IC,CTB) %RECORD (ISTF) LSSNP1I,LSSNP1,ISTDUM %RECORD (ISTF) %NAME LSSNP1P %RECORD (ISTF) GSSNP1 %CONSTLONGINTEGERARRAYNAME PST=PSTVA; ! PST SEG %INTEGERARRAYFORMAT PTF(0:255); ! PAGE TABLE FORMAT !----------------------------------------------------------------------- ! STORE TABLE ETC. DECLARATIONS %RECORDFORMAT STOREF(%BYTEINTEGER FLAGS,USERS, %HALFINTEGER LINK,BLINK,FLINK, %INTEGER REALAD) %CONSTRECORD (STOREF) %ARRAYNAME STORE=STORE0AD; ! ONE RECORD PER EPAGE %CONSTINTEGER OVERALLOC PERCENT=25 %CONSTINTEGER STOREFSIZE=12; ! SIZE OF ELEMENT OF STORE ARRAY %CONSTINTEGERNAME STORESEMA=STORE0AD+8; ! USE STORE(0)_REALAD AS SEMA %INTEGER SPSTOREX; ! FOR KEEPING EMERGENCY SPARE PAGE !----------------------------------------------------------------------- ! ACTIVE MEMORY TABLE DECLARATIONS %CONSTINTEGER MIN RESIDENCES=3,MAXRESIDENCES=15; ! 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,USERS,LINK, %BYTEINTEGER LEN,OUTS) ! DA : DISC ADDRESS ! DDP : AMTDD POINTER ! LINK : COLLISION LINK ! USERS : NO OF USERS OF THIS BLOCK ! LEN : BLOCK LENGTH IN EPAGES ! OUTS : NO OF PAGE-OUTS OF ! PAGES IN THIS BLOCK IN PROGRESS %CONSTINTEGER AMTFLEN=12 %CONSTRECORD (AMTF) %ARRAYNAME AMTA=X'80000000'! %C AMTASEG<<18+(MAXAMTAK<<2-AMTFLEN) %CONSTINTEGER AMTDDSEG=22 %CONSTINTEGER MAXAMTDDK=MAXPROCS//EPAGESIZE*EPAGESIZE %CONSTINTEGER DDFLEN=2 %CONSTHALFINTEGERARRAYNAME AMTDD=X'80000000'! %C AMTDDSEG<<18+(MAXAMTDDK<<2-DDFLEN) ! EACH %HALF : NEW EPAGE(1) / ! STOREX-DRUMTX(1) / INDEX(14) %CONSTINTEGER MAXBLOCK=32; ! MAX BLOCK SIZE %IF SFCFITTED=YES %THENSTART DRUMSIZE=COM_SFCK//EPAGESIZE %HALFINTEGERARRAY DRUMT(0:DRUMSIZE) ! SPARE(2) / STOREX(14) %FINISH %CONSTINTEGER DTEND=X'FFFF' %CONSTINTEGER NEWEPBIT=X'8000' %CONSTINTEGER DTXBIT=X'4000' %CONSTINTEGER STXMASK=X'3FFF' %CONSTINTEGER DDBIT=X'8000' !----------------------------------------------------------------------- ! SCHEDULING CATEGORY TABLES %RECORDFORMAT CATTABF(%BYTEINTEGER PRIORITY,EPLIM,RTLIM,MOREP,MORET,LESSP,SP0,SUSP,RQTS1,RQTS2,STROBEI,SP2) %OWNINTEGER MAXCAT MAXCAT=INTEGER(COM_CATTAD) %RECORD (CATTABF) %ARRAYFORMAT CATTABAF(0:MAXCAT) %RECORD (CATTABF) %ARRAYNAME CATTAB CATTAB==ARRAY(COM_CATTAD+4,CATTABAF) %OWNINTEGER MAXEPAGES MAXEPAGES=CATTAB(MAXCAT-1)_EPLIM %IF MONLEVEL&32#0 %THENSTART %HALFINTEGERARRAY FLYCAT,CATREC(0:MAXCAT,0:MAXCAT) %FINISH %IF MONLEVEL&16#0 %THENSTART %INTEGERARRAY STROBEN,STREPN,STROUT,SEQOUT(0:MAXCAT) %FINISH !----------------------------------------------------------------------- ! PON & POFF ETC. DECLARATIONS %RECORDFORMAT SERVF(%INTEGER P,L) %EXTERNALROUTINESPEC PON(%RECORD (PARMF) %NAME P) %EXTERNALROUTINESPEC DPON(%RECORD (PARMF) %NAME P, %INTEGER DELAY) %EXTERNALINTEGERFNSPEC NEWPPCELL %EXTERNALROUTINESPEC RETURN PP CELL(%INTEGER CELL) %EXTERNALROUTINESPEC FASTPON(%INTEGER PPCELL) %IF MULTIOCP=YES %THENSTART %EXTERNALROUTINESPEC SEMALOOP(%INTEGERNAME SEMA, %INTEGER PARM) %EXTERNALROUTINESPEC RESERVE LOG %EXTERNALROUTINESPEC RELEASE LOG %FINISH %EXTERNALROUTINESPEC SUPPOFF(%RECORD (SERVF) %NAME SERV, %RECORD (PARMF) %NAME P) %EXTERNALROUTINESPEC INHIBIT(%INTEGER SERVICE) %EXTERNALROUTINESPEC UNINHIBIT(%INTEGER SERVICE) %EXTERNALROUTINESPEC PINH(%INTEGER PROCESS,MASK) %EXTERNALROUTINESPEC PUNINH(%INTEGER PROCESS,MASK) %EXTERNALROUTINESPEC CLEAR PARMS(%INTEGER SERVICE) %EXTERNALINTEGERFNSPEC PPINIT(%INTEGERFN NEW EPAGE) %INTEGERFNSPEC NEW EPAGE %RECORDFORMAT PARMXF(%INTEGER DEST,SRCE,P1,P2,P3,P4,P5,P6,LINK) %CONSTRECORD (PARMXF) %ARRAYNAME PARM=PARM0AD %CONSTINTEGER LOCSN1= LOCSN0+MAXPROCS COM_SYNC1DEST=LOCSN1 %CONSTINTEGER LOCSN2= LOCSN0+2*MAXPROCS COM_SYNC2DEST=LOCSN2 %CONSTINTEGER LOCSN3= LOCSN0+3*MAXPROCS COM_ASYNCDEST=LOCSN3 %CONSTRECORD (SERVF) %ARRAYNAME SERVA=SERVAAD %EXTRINSICINTEGER KERNELQ,RUNQ1,RUNQ2,MAINQSEMA %OWNINTEGER SCHEDSEMA=-1 %EXTERNALLONGINTEGER KMON KMON=COM_KMON !----------------------------------------------------------------------- ! SERVICE ROUTINE SPECS %ROUTINESPEC SCHEDULE(%RECORD (PARMF) %NAME P) %ROUTINESPEC PAGETURN(%RECORD (PARMF) %NAME P) %ROUTINESPEC GET EPAGE(%RECORD (PARMF) %NAME P) %INTEGERFNSPEC QUICK EPAGE(%INTEGER ZEROED,SMACMASK) %ROUTINESPEC RETURN EPAGE(%RECORD (PARMF) %NAME P) %ROUTINESPEC DEADLOCK %ROUTINESPEC OVERALLOC CONTROL %ROUTINESPEC CONFIG CONTROL(%RECORD (PARMF) %NAME P) %ROUTINESPEC SHUTDOWN(%RECORD (PARMF) %NAME P) %ROUTINESPEC ACTIVE MEM(%RECORD (PARMF) %NAME P) %EXTERNALLONGINTEGERFNSPEC CLOCK %ROUTINESPEC UPDISP(%INTEGER PROCESS,OFFSET, %STRING (13) S) %EXTERNALROUTINESPEC ELAPSEDINT(%RECORD (PARMF) %NAME P) %EXTERNALROUTINESPEC SEMAPHORE(%RECORD (PARMF) %NAME P) %EXTERNALROUTINESPEC GDC(%RECORD (PARMF) %NAME P) %EXTERNALROUTINESPEC DISC(%RECORD (PARMF) %NAME P) %EXTERNALROUTINESPEC PDISC(%RECORD (PARMF) %NAME P) %EXTERNALROUTINESPEC BMOVE(%RECORD (PARMF) %NAME P) %EXTERNALROUTINESPEC TAPE(%RECORD (PARMF) %NAME P) %EXTERNALROUTINESPEC OPER(%RECORD (PARMF) %NAME P) %EXTERNALROUTINESPEC PRINTER(%RECORD (PARMF) %NAME P) %EXTERNALROUTINESPEC LP ADAPTOR(%RECORD (PARMF) %NAME P) %IF CRFITTED=YES %START %EXTERNALROUTINESPEC CR ADAPTOR(%RECORD (PARMF) %NAME P) %FINISH %EXTERNALINTEGERFNSPEC SAFE IS READ(%INTEGER ISAD, %INTEGERNAME VAL) %EXTERNALINTEGERFNSPEC SAFE IS WRITE(%INTEGER ISAD,VAL) %IF CPFITTED=YES %THENSTART %EXTERNALROUTINESPEC CP ADAPTOR(%RECORD (PARMF) %NAME P) %FINISH %IF DAP FITTED=YES %THENSTART %CONSTINTEGER MAXLDAP=2 %ROUTINESPEC DAP DRIVER(%RECORD (PARMF) %NAME P) %FINISH %IF MONLEVEL&256#0 %START %EXTERNALROUTINESPEC COMBINE(%RECORD (PARMF) %NAME P) %EXTERNALROUTINESPEC HARVEST(%INTEGER EVENT,PROCESS,LEN,A,B,C,D,E) %EXTRINSICINTEGER TRACE EVENTS %EXTRINSICINTEGER TRACE PROCESS %EXTRINSICINTEGER TRACE %FINISH %EXTERNALROUTINESPEC COMMS CONTROL(%RECORD (PARMF) %NAME P) %EXTERNALROUTINESPEC MK1FEADAPTOR(%RECORD (PARMF) %NAME P) %EXTERNALROUTINESPEC COMREP(%RECORD (PARMF) %NAME P) %EXTERNALROUTINESPEC BMREP(%RECORD (PARMF) %NAME P) %EXTERNALROUTINESPEC SYSERR(%INTEGER STK,IP) !----------------------------------------------------------------------- ! TIMING INFORMATION DECS. %IF MONLEVEL&X'3C'#0 %THENSTART %ROUTINESPEC TIMEOUT %ROUTINESPEC CLEAR TIME %FINISH %IF MONLEVEL&4#0 %THENSTART %RECORDFORMAT PERFORMF(%INTEGER RECAPN,PTURNN,PSHAREN,NEWPAGEN,PAGEOUTN,PAGEZN,SNOOZN,ABORTN,SNOOZOK,SNOOZTO, SNOOZAB, %LONGINTEGER CLOCK0, %LONGINTEGERARRAY SERVIT,SERVIC(0:LOCSN0+3), %INTEGERARRAY SERVN(0:LOCSN0+3)) %RECORD (PERFORMF) PERFORM COM_PERFORMAD=ADDR(PERFORM) IDLEIT==PERFORM_SERVIT(0) NOWORKIT==PERFORM_SERVIT(1) PTIT==PERFORM_SERVIT(4) RETIT==PERFORM_SERVIT(6) AMIT==PERFORM_SERVIT(8) PDISCIT==PERFORM_SERVIT(33) DRUMIT==PERFORM_SERVIT(40) LCIT==PERFORM_SERVIT(LOCSN0+1) FLPIT==PERFORM_SERVIT(LOCSN0+2) BLPIT==PERFORM_SERVIT(LOCSN0+3) ! PTIC==PERFORM_SERVIC(4) RETIC==PERFORM_SERVIC(6) AMIC==PERFORM_SERVIC(8) PDISCIC==PERFORM_SERVIC(33) DRUMIC==PERFORM_SERVIC(40) LCIC==PERFORM_SERVIC(LOCSN0+1) ! IDLEN==PERFORM_SERVN(0) NOWORKN==PERFORM_SERVN(1) PTCALLN==PERFORM_SERVN(4) RETCALLN==PERFORM_SERVN(6) AMCALLN==PERFORM_SERVN(8) PDISCCALLN==PERFORM_SERVN(33) DRUMCALLN==PERFORM_SERVN(40) LCN==PERFORM_SERVN(LOCSN0+1) FLPN==PERFORM_SERVN(LOCSN0+2) BLPN==PERFORM_SERVN(LOCSN0+3) %FINISH !----------------------------------------------------------------------- ! PROCESS INORMATION ETC. %RECORDFORMAT PROCF(%STRING (6) USER, %BYTEINTEGER INCAR,CATEGORY,P4TOP4,RUNQ,ACTIVE, %INTEGER ACTW0,LSTAD, %BYTEINTEGER EPA,EPN, %HALFINTEGER LAMTX, %INTEGER STACK,STATUS) %RECORD (PROCF) %ARRAY PROCA(0:MAXPROCS) ! 2**0 = HOLDS A SEMAPHORE ! 2**1 = ON A PAGE FAULT ! 2**2 = A BACKGROUND JOB ! 2**3 = DEALLOCATING AMT (&DRUM) ONLY ! 2**4 = AMT LOST ! 2**5 = HAD TIME ON FLY ! 2**6 = HAD EPAGES ON FLY ! 2**7 = SNOOZING ! 2**8 = LC STACK READ FAILURE ! 2**9 = STATE X(LC STK SNOOZED) ! 2**10 HAS PIECE OF DAP ! REMAINDER UNUSED ! DUMP PROGRAM NEED TO HAVE ! DETAILS OF ANY CHANGES ! %CONSTINTEGER HADTONFLY=32,HADPONFLY=64,SNOOZED=128 %CONSTINTEGER LCSTFAIL=256,AMTLOST=16,STATEX=512 %CONSTINTEGER FIRST UPROC=6 %CONSTINTEGER OPERSPACE=41*(6+MAXPROCS//3) %INTEGERARRAY PROC PICT(0:2+OPERSPACE>>2); ! SPACE FOR PROCESS PICTURE PROC PICT(0)=OPERSPACE; ! FIRST WORD=LENGTH OF REM !----------------------------------------------------------------------- ! LOCAL CONTROLLER DECS ETC. %ROUTINESPEC LOCAL CONTROL %ROUTINESPEC GLOBAL CONTROL %OWNLONGINTEGERARRAYFORMAT LSTF(0:LSTLEN-1) %OWNINTEGER TIMESLICE=X'4000'; ! 131072 MICROSECS %OWNINTEGER OUT18CHARGE=X'800'; ! CHARGE FOR OUT116 =8 MILLESECS %OWNINTEGER OUT18INS; ! CHARGE *INS RATE %OWNINTEGER ALLOW PERI INTS=X'01803FFE'; ! CHANGED IN SCHEDULE ACT0 %EXTERNALINTEGERFNSPEC SYSTEMCALL !----------------------------------------------------------------------- I=SYSTEM CALL; ! TO INITIALISE "COM" FILE *STLN_OLDLNB ! ! 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; ! TO CALL OF L-C AFTER ACTIVATE LSSNP1I_SSR=X'01803BFE' LSSNP1I_SF=LSTLEN*8+LSTKN*X'80'+(DIRCSEGL+1)+X'80' ! SF AT 12 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; ! INTERRUPT EVERY 2 SECS(APPROX) *ST_(0+ %B ); ! Z-REG %IF COM_TSLICE>0 %THEN TIMESLICE=COM_TSLICE//COM_ITINT OUT18CHARGE=TIMESLICE>>3; ! ONE EIGHTH OF TSLICE OUT18INS=OUT18CHARGE*COM_INSPERSEC*COM_ITINT//1000 ! ! FIND END OF KERNEL STACK ETC. ! PST(44)=0; PST(45)=0; ! CLEAR CHOPSUPE CODE GLA PST(46)=0; PST(47)=0; ! & STACK SEGMENTS FROM PST PST(13)=PST(5)-128; ! SSN FOR OCP PORT 2 PST(15)=PST(5)+128; ! SSN FOR OCP PORT 3 FSTASL==STORE(0)_FLINK BSTASL==STORE(0)_BLINK ! SET KERNEL STACK SEGMENT LIMIT ! INCLUDING PROTEM 8 K FOR EACH OCP ! STACK. THESE WILL BE REMOVED ! ONCE THE OCPS ARE ACTIVATED I=PST(4)&X'0FFFFFF8'; ! REALAD OF STACK K=PST(4)>>32&X'3FF80'+128+I; ! REALAD OF MAX TOS *STSF_J L=(J&X'3FFFF'+X'7F'+X'2000')>>7 %IF MULTIOCP=YES %THEN L=L+X'2000'>>7 PST(4)=PST(4)&X'FFFC007FFFFFFFFF'!(L-1)<<39 STKPSTE=PST(4)-X'200000000000' %IF MULTIOCP=YES %THEN STKPSTE=STKPSTE-X'200000000000' J=EPAGESIZE<<10; ! ADD UNUSED KERNEL STACK TO FREE LIST K=K//J-1 J=(I+L<<7+J-1)//J STORESEMA=-1 SPSTOREX=0 GETEPN=0 PREEMPTED=0; ! NO PROCESS PRE-EMPTED DONT SCHED=0 SMAC RCONFIG=0 SMAC RPAGES=0 %IF SSERIES=NO %START; ! mask for configured in SACs SAC MASK=1<1 %THEN SAC MASK=SAC MASK!(1<0 %THENSTART P_DEST=X'280000' P_P1=EPAGESIZE P_P2=COM_SFCA P_P3=ADDR(STORE(0)) P_P4=ADDR(PARM(0)) PON(P) %FINISH ! INITIALISE SCHEDULE & ACTIVEMEM INHIBIT(3); ! HOLD PON FOR DISC LABEL READS P_DEST=X'30000' PON(P); ! PONNED TO ALLOW DISC LABEL READING ! ! CLEAR TIMING ARRAY ETC. ! %IF MONLEVEL&4#0 %THEN CLEAR TIME P_DEST=X'A0001' P_SRCE=0 P_P1=X'B0000' P_P2=2 PON(P); ! KICK UPDATE TIME P_P1=X'360000' PON(P); ! KICK PRINTER P_P1=X'E0004' P_P2=10 PON(P); ! ACTIVE MEM P_P1=X'70004' PON(P); ! SEMAPHORE EVERY 10 SECS P_P1=X'D0001' PON(P); ! KICK ERROR REPORTING P_P1=X'00100000' P_P2=600 PON(P); ! KICK OVERALLOC CNTRL EVERY 10 MIN %IF STRING(ADDR(COM_SUPVSN))1 %START P_DEST=X'110001'; P_P1=1<<16!COM_OCPPORT1 COM_NOCPS=1 PON(P); ! CONFIGURE IN 2ND OCP LATER %FINISHELSE COM_NOCPS=1 %END ! ! NOW ACTIVATE THIS OCP INTO GLOBAL CONTROLLER. ALSO REMOTE ACTIVATE ! OTHER OCP IF PRESENT. STACKS ARE PUBLIC 12 FOR PORT 2 AND 14 FOR PORT 3 ! %IF SSERIES=YES %THEN I=2*COM_OCPPORT0+12 %ELSE I=2*COM_OCPPORT0+8; ! PST no. for local activate K=I!!2; ! AND FOR REMOTE ACTIVATE GSSNP1=LSSNP1I *JLK_ *LSS_ %TOS; *ST_J GSSNP1_PC=J GSSNP1_LNB=X'80000004'+I<<18 GSSNP1_SF=GSSNP1_LNB+X'20' GSSNP1_SSR=X'01803FFE' RECORD(X'80000000'+(I+1)<<18)<-GSSNP1; ! context from record to SSN+1 *STSF_J PST(I)=PST(4)&X'1FF000008FFFFF80'+X'1F8000000000'+(J+128)&X'3FF80' %IF MULTIOCP=YES %THEN PST(K)=PST(I)+X'2000' *LSD_0; *SLSS_I; *USH_18; *OR_X'80000000' *LUH_0; *ST_ %TOS; *ACT_ %TOS GCCALL: *JLK_ %TOS *STCT_(%LNB +5) *LSD_(%CTB +3); *ST_(%LNB +3); ! COPY ACROSS PLT DESCR 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 *LSD_(%CTB +3); *ST_(%LNB +3); ! COPY ACROSS PLT DESCR LOCAL CONTROL; ! INITIAL CALL(DOES NOT RETURN!) %ROUTINE GLOBAL CONTROL !%ROUTINESPEC UNQUEUE(%INTEGERNAME QUEUE,UNQUED SERVICE) %INTEGER I,J,K,PORT,SEIP,SELN,SESTK,KSERVICE,LSERVICE,TSERVICE,MY OCP PORT,HIS OCP PORT,IS DIAG,ISTAD %LONGINTEGER WORK %IF MONLEVEL&4#0 %THENSTART %INTEGER IT,IC,IT CORRN %INTEGERNAME KIT; ! IT IN KERNEL CONTEXT %CONSTINTEGER IC CORRN=20; ! INSTRNS NOT COUNTED IN IDLE %FINISH %IF MULTI OCP=YES %START %INTEGERNAME MY ALARM,HIS ALARM %CONSTINTEGER MAX ALARM=1024 ! control words to catch other OCP going to sleep %FINISH %INTEGERNAME CURPROC; ! CURRENT PROCESS KEPT IN IST ! (LAST WRD) FOR DUMPS ETC %SWITCH CONROUT(0:3) %SWITCH SERVROUT(0:LOCSN0); ! KERNEL SERVICES %RECORD (PROCF) %NAME PROC; ! STATUS BITS SIGNIFY AS FOLLOWS %RECORD (SERVF) %NAME KSERV,LSERV,LSERVQ %RECORD (ISTF) %NAME ISTP %RECORD (CDRF) %NAME LDAP %INTEGERNAME RUNQ %RECORD (PARMF) P ! ! FIND WHICH OCP THIS ACTIVATION IS USING AND SET RELEVANT IST ! *LSS_(3); *USH_-26 *AND_3; *ST_MY OCP PORT %IF MULTI OCP=YES %THEN HIS OCP PORT=MY OCP PORT!!1 PST(4)=STKPSTE; ! SHORTEN OLD STACK *LSS_OLDLNB; *ST_(%LNB +0); ! FOR %MONITOR ISTAD=X'80000000'+MY OCP PORT<<18 ISTP==RECORD(ISTAD); ! IST BASE *STLN_I; ! USED TO FRIG %MONITOR LATER ISTP_LNB=I ISTP_PSR=X'00140001'; ! ACR=1, PRIV=1, PM=0, ACS=1 ISTP_PC=0 ISTP_SSR=X'01803FFE'; ! ONLY SYSERR *STSF_I ISTP_SF=I ISTP_IT=MAXIT ISTP_IC=MAXIT ISTP_CTB=0 RECORD(ISTAD+X'20')<-ISTP; ! EXTERNAL INTS RECORD(ISTAD+X'40')<-ISTP; ! M-P INTS RECORD(ISTAD+X'60')<-ISTP; ! PERIPHERAL INTS RECORD(ISTAD+X'120')<-ISTP; ! EXTRACODE(!) INTS RECORD(ISTAD+X'140')<-ISTP; ! EVEBT PENDING INTS RECORD(ISTAD+X'180')<-ISTP; ! Primitive ints. RECORD(ISTAD+X'1A0')<-ISTP; ! Unit ints. LSSNP1P==RECORD(X'40000') ! ! MASK SYSERR& UNMASK OUT ON SYSERR. INTERRUPT ! ISTP_SSR=X'01803EFF' 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 +74) *JLK_; *LSS_ %TOS; *ST_(%XNB +82) *JLK_; *LSS_ %TOS; *ST_(%XNB +98) *JLK_; *LSS_ %TOS; *ST_(%XNB +106) %IF MULTI OCP=YES %START MY ALARM==INTEGER(ISTAD+4*94); ! uses IC field for IC int HIS ALARM==INTEGER(ISTAD!!1<<18+4*94) %FINISH CURPROC==INTEGER(ISTAD+4*95); ! onto CTB field for IC int CURPROC=0 KSERVICE=0 KSERV==SERVA(0) LSERV==KSERV; ! INITIALISE POINTERS. HERE AFTER ! ADDRESS FIELD ONLY UPDATE ! IN ASSEMBLER SEQUENCES %IF MONLEVEL&4#0 %START IT CORRN=1+1024*IC CORRN//(COM_INSPERSEC*COM_ITINT) KIT==INTEGER(ISTP_SF&X'FFFC0000'+X'40014') %FINISH %IF MULTIOCP=YES %AND COM_NOCPS>1 %THENSTART ! OPEN PATHS FOR MP INT ETC ! SET PORT DEPENDENT PHOTO(P4S) %IF SSERIES=NO %START %IF BASIC PTYPE<=3 %START *LSS_1; *ST_(X'6009'); ! BROADCAST SE *LSS_(X'600A') *AND_X'CC'; *ST_(X'600A'); ! PERMIT MP INTS & ACTIVATES *ST_IS DIAG %FINISHELSESTART *LSS_(X'4012'); *OR_X'300C'; *ST_(X'4012'); ! PERMIT MPINTS ! AND SE INTS FROM OCP PORTS *LSS_(X'4013'); *OR_X'8004'; *ST_(X'4013') *ST_IS DIAG %FINISH %FINISH %IF MY OCP PORT#COM_OCPPORT0 %START; ! IM NOT IPL PROCESSOR %IF SSERIES=YES %START J=COM_OCP0 SCU PORT *LSS_J; *ST_(X'600F') *LB_X'602B'; *LSS_0; *ST_(0+ %B ); ! unset selective masks *LB_X'6011'; *LSS_(0+ %B ); *AND_X'FFFD'; *OR_1; *ST_(0+ %B ); ! miniphotos only J=X'400C0000'!COM_OCP0 SCU PORT<<22 ! set up UTBR I=J!X'6004'; *LB_I; *LSS_(0+ %B ); *LB_X'6004'; *ST_(0+ %B ) I=J!X'6005'; *LB_I; *LSS_(0+ %B ); *LB_X'6005'; *ST_(0+ %B ) ! set up MIB %UNLESS COM_MIBA=0 %START I=COM_MIBA+MY OCP PORT<<12 *LB_X'601A'; *LSS_I; *ST_(0+ %B ) %FINISH ! set up cross reporting of errors I=COM_OCP0 SCU PORT<<22 *LB_X'601D'; *LSS_I; *ST_(0+ %B ) I=J!X'601D'; J=COM_OCP1 SCU PORT<<22 *LB_I; *LSS_J; *ST_(0+ %B ) %FINISHELSEIF BASIC PTYPE<=3 %START J=X'80'>>COM_SACPORT0 %IF COM_NSACS>1 %THEN J=J!X'80'>>COM_SACPORT1 J=J!!(-1) *LSS_(X'600A'); *AND_J; *ST_(X'600A') ! CLOSE OFF SAC INTS TO THIS OCP %IF BASIC PTYPE=2 %START *LSS_X'00011001'; *ST_(X'6011') ! INHIBIT PHOTO ON SOFT SYSTEM ERROR %FINISH J=COM_OCPPORT0 *LSS_J; *ST_(X'600F'); ! OPEN ROUTE FOR RRTC *ST_IS DIAG %FINISHELSESTART %IF COM_OCPTYPE=4 %THEN J=COM_SACPORT0 %ELSE J=COM_OCPPORT0 J=J<<20 *LSS_(X'4013'); *OR_J; *ST_(X'4013') *ST_IS DIAG *LSS_(X'4012'); *AND_X'FFFF3FCF' *ST_(X'4012'); ! INHIBIT SAC INTERRUPTS %FINISH %FINISH %FINISH !----------------------------------------------------------------------- ! TURN ON SLAVING WHICH HAS BEEN INHIBITED BY CHOPSUPE SLAVESONOFF(-1) !----------------------------------------------------------------------- ! SERVICE LOOPS KSERVE: ! KERNEL SERVICES %IF MONLEVEL&4#0 %THENSTART *LSS_X'FFFFFF'; ! SET IT & IC TO MAX. *ST_(5) *ST_(6) %FINISH *LSS_ALLOW PERI INTS; ! LET INTERRUPTS IN *ST_(3) *LSS_X'01803FFE' *ST_(3) %IF MULTIOCP=YES %THENSTART *INCT_(MAINQSEMA) *JCC_8, SEMALOOP(MAINQSEMA,0) MQGOT1: %FINISH KSKIP: ! TRY NEXT WITHOUT RECLAIMING SEMA %IF KSERVICE!KERNELQ=0 %THENSTART %IF CURPROC#0 %THENSTART ! PROC MAPPED AT LAST LSERVE %IF RUNQ1#0 %AND PREEMPTED=0 %AND PROC_RUNQ=2 %START PREEMPTED=CURPROC ! RUNQ==RUNQ1 *LD_RUNQ1 *J_; ! PREMPTED LOWPRIO FOR HIGHPRIO %FINISH KACT: ! ACTIVATE DIRECT KERNEL->USER %IF MULTIOCP=YES %START; *TDEC_(MAINQSEMA); %FINISH %IF MONLEVEL&4#0 %THENSTART %IF PROC_STATUS&4#0 %THEN BLPN=BLPN+1 %ELSE FLPN=FLPN+1 %FINISH *LXN_PROC+4 *ACT_(%XNB +3); ! REACTIVATE INTERRUPTED PROCESS %FINISH ! %IF RUNQ1#0 %THEN RUNQ==RUNQ1 %AND ->LSERVE *LSS_(RUNQ1); *JAF_4, %IF PREEMPTED#0 %START; ! RESUME PREMPTED PROCESS CURPROC=PREEMPTED LSERVICE=CURPROC+LOCSN0 LSERV==SERVA(LSERVICE) PREEMPTED=0 PROC==PROCA(CURPROC) ->KACT %FINISH ! %IF RUNQ2#0 %THEN RUNQ==RUNQ2 %AND ->LSERVE *LSS_(RUNQ2); *JAF_4, ! ! NO PROCESS NEEDS OCP. ENTER AND TIME THE IDLE LOOP ! WHICH IS DIFFERENT FOR MULTI OCPS WHERE OTHER OCP CAN GENERATE WORK ! %IF MULTIOCP=YES %START; *TDEC_(MAINQSEMA); %FINISH %IF MONLEVEL&4#0 %THENSTART %IF MPLEVEL+NPQIDLE0; ! IN CASE "EKS" SET %FINISHELSESTART; ! IDLE IN DUALS %IF SSERIES=NO %AND MY OCP PORT#COM_OCPPORT0 %START ! ! for S series DCU2 interrupts are reported to the ! activating OCP & DCU1 ints. to the IPL (or S/W nominated) OCP ! so trying to grab outstanding ints. will not work! ! PORT=COM_SACPORT0 *LSS_X'01803FFE'; *ST_(3) J=X'44000000'!PORT<<20 *LB_J; *LSS_(0+ %B ); *ST_I *JAF_4, %IF COM_NSACS>1 %START PORT=COM_SACPORT1 J=X'44000000'!PORT<<20 *LB_J; *LSS_(0+ %B ); *ST_I *JAF_4, %FINISH *LSS_X'01800820'; *ST_(3) %FINISH *RRTC_0; *AND_1023; *STUH_ %B; *ST_ %B; *ADB_2; ! RANDOM LOOP TIME IL0: *LSS_1 *IAD_1 *DEBJ_ %IF MONLEVEL&4#0 %START *LSS_(5) *IRSB_MAXIT *IAD_IT CORRN; ! CORRECT FOR THESE INSTRNS *ST_I %IF MPLEVEL+NPQKSERVE %FINISH %FINISH ! ! MAIN QUEUE SERVICING SECTION ! %IF KSERVICE=0 %THENSTART ! UNQUEUE(KERNELQ,KSERVICE) ! KSERV==SERVA(KSERVICE) *LD_KERNELQ; *JLK_ *STB_KSERVICE *STXN_KSERV+4; ! COPY MAPPING FROM JLK SUBROUTINE %FINISH I=KSERV_P&X'BFFFFFFF'; ! REMOVE EXECUTED BIT %IF I<=0 %THEN KSERV_P=I %AND KSERVICE=0 %AND ->KSKIP %IF KSERVICE>LOCSN1 %START; ! SUSPEND REPLY I=(KSERVICE-LOCSN0)&(MAXPROCS-1)+LOCSN1 SERVA(I)_P=SERVA(I)_P!X'80000000' I=I+(LOCSN2-LOCSN1) SERVA(I)_P=SERVA(I)_P!X'80000000' I=I+(LOCSN3-LOCSN2) SERVA(I)_P=SERVA(I)_P!X'80000000' %IF MULTIOCP=YES %START; *TDEC_(MAINQSEMA); %FINISH P_DEST=X'30007'; ! RESCHEDULE LOCAL CONTROLLER P_SRCE=0 P_P1=I-LOCSN3 SCHEDULE(P) TSERVICE=3 ->KTIMES %FINISH %IF MULTIOCP=YES %START; *TDEC_(MAINQSEMA); %FINISH SUPPOFF(KSERV,P) ->SERVROUT(KSERVICE) !----------------------------------------------------------------------- ! SERVICE ROUTINE CALLS SERVROUT(1): SNOOZTIME=P_P1; ->KEXIT SERVROUT(2): DEADLOCK; ->KEXIT SERVROUT(3): SERVROUT(15): 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): SERVROUT(14): ACTIVE MEM(P); ->KEXIT SERVROUT(9): ! ONLY FOR MONITORING %IF MONLEVEL&X'3C'#0 %THEN TIMEOUT; ->KEXIT SERVROUT(10): ELAPSEDINT(P); ->KEXIT SERVROUT(11): UPDATE TIME; ->KEXIT SERVROUT(12): DPONPUTONQ(P); ->KEXIT SERVROUT(13): TURNONER(P); ->KEXIT SERVROUT(16): OVERALLOC CONTROL; ->KEXIT SERVROUT(17): CONFIG CONTROL(P); ->KEXIT SERVROUT(18): SHUTDOWN(P); ->KEXIT SERVROUT(19): %IF MULTI OCP=YES %AND COM_NOCPS>1 %THEN CHECK OTHER OCP %AND ->KEXIT ->INVALID SERVROUT(20): SERVROUT(21): SERVROUT(22): SERVROUT(23): SERVROUT(24): SERVROUT(25): SERVROUT(26): SERVROUT(27): SERVROUT(28): SERVROUT(29): SERVROUT(30): ->INVALID SERVROUT(31): %IF DAP FITTED=YES %THEN DAP DRIVER(P) %AND ->KEXIT ->INVALID SERVROUT(32): DISC(P) ->KEXIT SERVROUT(33): PDISC(P); ->KEXIT SERVROUT(34): SERVROUT(35): ->INVALID SERVROUT(36): SERVROUT(37): BMOVE(P); ->KEXIT SERVROUT(38): SERVROUT(39): ->INVALID SERVROUT(40): %IF SFC FITTED=YES %THEN DRUM(P) %AND ->KEXIT %ELSE ->INVALID SERVROUT(41): %IF CSU FITTED=YES %THEN CSU(P) %AND ->KEXIT %ELSE ->INVALID SERVROUT(42): SERVROUT(43): SERVROUT(44): SERVROUT(45): SERVROUT(46): SERVROUT(47):->INVALID SERVROUT(48): GDC(P); ->KEXIT SERVROUT(49): TAPE(P); ->KEXIT SERVROUT(50): OPER(P); ->KEXIT SERVROUT(51): LP ADAPTOR(P); ->KEXIT SERVROUT(52): %IF CRFITTED=YES %THEN CR ADAPTOR(P) %AND ->KEXIT %ELSE ->INVALID SERVROUT(53): %IF CPFITTED=YES %THEN CP ADAPTOR(P) %AND ->KEXIT %ELSE ->INVALID SERVROUT(54): PRINTER(P); ->KEXIT SERVROUT(55): COMMS CONTROL(P); ->KEXIT SERVROUT(56): %IF MONLEVEL&256#0 %THEN COMBINE(P) %AND ->KEXIT %ELSE ->INVALID SERVROUT(57): MK1FEADAPTOR(P); ->KEXIT SERVROUT(58): SERVROUT(59): SERVROUT(60):->INVALID SERVROUT(61): BMREP(P); ->KEXIT SERVROUT(62): COMREP(P); ->KEXIT SERVROUT(63): ! DELAYED RELAY I=P_DEST&X'FFFF'; ! THE DELAY P_DEST=P_P6 DPON(P,I) ->KEXIT SERVROUT(64): SERVROUT(0): ->INVALID !----------------------------------------------------------------------- KEXIT: %IF MONLEVEL&4#0 %THEN TSERVICE=KSERVICE KTIMES: ! RECORD SERVICE ROUTINE TIMES %IF MONLEVEL&4#0 %THENSTART *LSS_(6); *IRSB_MAXIT; *IAD_IC CORRN; *ST_IC *LSS_(5); *IRSB_MAXIT; *IAD_IT CORRN; *ST_IT PERFORM_SERVIT(TSERVICE)=IT+PERFORM_SERVIT(TSERVICE) PERFORM_SERVIC(TSERVICE)=IC+PERFORM_SERVIC(TSERVICE) PERFORM_SERVN(TSERVICE)=PERFORM_SERVN(TSERVICE)+1 %FINISH ->KSERVE !----------------------------------------------------------------------- LINVALID: ! LOCAL CNTRL NOT RESIDENT CURPROC=0 SUPPOFF(LSERV,P) LSERV_P=LSERV_P&X'BFFFFFFF'; ! REMOVE EXECUTING BIT %IF MULTI OCP=YES %START; *TDEC_(MAINQSEMA); %FINISH ! AND DROP THRO FOR MSG INVALID: ! INVALID SERVICE CALLED PKMONREC("INVALID POFF:",P) ->KSERVE !----------------------------------------------------------------------- LSERVE: ! LOCAL CONTROLLER SERVICES *STD_RUNQ; ! COMPLETE MAPPING OF RUNQ ! UNQUEUE(RUNQ,LSERVICE) ! LSERV==SERVA(LSERVICE) *JLK_; *STB_LSERVICE *STXN_LSERV+4; ! COPY MAPPING FROM JLK SUBROUTINE ! THIS IS USED ON L-C EXIT ! ! L-C IS ONLY INHIBITIED BEFORE PROCESS START AND AFTER STOPPING ! SO THE LOGICALLY NECESSARY TEST FOR INHIBITION CAN BE OMITTED ! UNLESS CODEING ELSEWHERE IS CHANGED. CODE LEFT AS COMMENT AS ! A REMINDER ! ! I=LSERV_P&X'BFFFFFFF'; ! WITHOUT "EXECUTING" BIT ! %IF I<=0 %THEN LSERV_P=I %AND ->KSKIP;! INHIBITED ! CURPROC=LSERVICE-LOCSN0 *SBB_LOCSN0; *STB_(CURPROC) PROC==PROCA(CURPROC) %IF PROC_ACTIVE#255 %THEN ->LINVALID %IF MULTI OCP=YES %START *TDEC_(MAINQSEMA) %IF COM_NOCPS>1 %START; ! other OCP sleep check HIS ALARM=HIS ALARM+1 %IF HIS ALARM>MAX ALARM %THEN CHECK OTHER OCP %AND HIS ALARM=0 MY ALARM=0 %FINISH %FINISH ! ! TO ACTIVATE TO LOCAL CONTROLLER USE THE ACTIVATE WORDS IN THE PROCESS ! LIST BUT SUBSTITUTE LC STACK NO(0) FOR PROCESS STACK NO ! *LXN_PROC+4 *LSD_(%XNB +3) *SLSD_0; ! LC STACK NO NOT PARAMETERISED ! *ST_ %TOS %IF MONLEVEL&4#0 %THENSTART LCN=LCN+1 *LSS_(6); *IRSB_MAXIT; *LUH_0; *IAD_(LCIC); *ST_(LCIC) *LSS_(5); *IRSB_MAXIT; *LUH_0; *IAD_(LCIT); *ST_(LCIT) %FINISH *ACT_ %TOS !----------------------------------------------------------------------- ! EVENT PENDING (USED TO EXIT FROM LOCAL CONTROLLER) IST11I: *JLK_ %TOS ! LOCAL CONTROL RETURNS TO HERE CURPROC=0 %IF MULTIOCP=YES %THENSTART %IF COM_NOCPS>1 %THEN MY ALARM=0 *INCT_(MAINQSEMA) *JCC_8, SEMALOOP(MAINQSEMA,0) MQGOT2: %FINISH LSERV_P=LSERV_P&X'BFFFFFFF'; ! REMOVE "EXECUTING" BIT ! ! IF THE PROCESS IS NOT SUSPENDED THERE WILL BE MORE PARAMETERS FOR IT ! AND IT MUST BE REQUEUED. NOTE THAT THE PROCESS MAY HAVE CHANGED ! ITS RUNQ BY TRANSITIONS MADE ON THE FLY! ! %IF LSERV_P>0 %THENSTART %IF PROC_RUNQ=1 %THEN RUNQ==RUNQ1 %ELSE RUNQ==RUNQ2 %IF RUNQ=0 %THEN LSERV_L=LSERVICE %ELSESTART LSERVQ==SERVA(RUNQ) LSERV_L=LSERVQ_L LSERVQ_L=LSERVICE %FINISH RUNQ=LSERVICE %UNLESS PROC_STATUS&3#0 %AND RUNQ#0 %FINISH %IF MULTIOCP=YES %START; *TDEC_(MAINQSEMA); %FINISH ->KSERVE !----------------------------------------------------------------------- ! INTERRUPT ENTRY POINTS IST1I: *JLK_ %TOS; ! ENTRY IS LINK PC I.E. NEXT INSTR ! SYSTEM ERROR INTS ENTER HERE *LSS_ %TOS; *ST_SESTK *LSS_ %TOS; *ST_SEIP *LSS_(%LNB +8); *ST_SELN; ! OLD LINE NUMBER SYSERR(SESTK,SEIP); ! DOES NOT RETURN ->KSERVE !----------------------------------------------------------------------- IST2I:*JLK_ %TOS ! EXTERNAL INTS (CLOCK+DAP) ENTER HERE *LSS_ %TOS; *ST_I; ! OLD STACK *LSS_ %TOS; *ST_J; ! INTERRUPT PARAMETER %IF MONLEVEL&4#0 %AND IDLE#0 %THENSTART %IF MPLEVEL+NPQ>20&15 P_SRCE=0 %IF DAP FITTED=YES %AND 4<=PORT<=5 %START; ! FROM DAP %FOR I=1,1,MAXLDAP %CYCLE LDAP==COM_CDR(I) %IF LDAP_IPDAPNO>>4=PORT %START J=LDAP_DAP1+7 *LB_J; *LSS_(0+ %B ); *ST_J; ! READ AND CLEAR INT %IF J#0 %START; ! WAS AN INTERRUPT P_P3=J; ! DAP INT STATUS REG P_P4=MY OCP PORT P_DEST=X'1F0003'!I<<8 PON(P) %FINISH %FINISH %REPEAT ->KSERVE %FINISH %IF SSERIES=NO %AND BASIC PTYPE=4 %AND 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 %IF BASIC PTYPE=4 %AND COM_CLKX>>20&15#PORT %THEN OPMESS("?? CLOCK INT PORT ".STRINT(PORT)) P_DEST=X'A0000' %IF MULTIOCP=YES %THEN PON(P) %AND ->KSERVE %ELSESTART ELAPSEDINT(P) %IF MONLEVEL&4#0 %THEN TSERVICE=10 ->KTIMES %FINISH !----------------------------------------------------------------------- IST3I:*JLK_ %TOS; ! multi-processor MULT: ! or pseudo via PON 19 %IF MULTIOCP=YES %THENSTART *LSS_ %TOS; *LSS_ %TOS; *USH_-20 *AND_15; *ST_I; ! INTERRUPTING PORT ! ! A MULTIOCP INT MEANS THAT THE OTHER OCP IS DOWN (EVEN THO THE ! INT MAY HAVE COME FROM SELF). STEP1 IS TO READ AND CLEAR THE INT AND ! MASK OUT ANY FURTHER COMMUNICATION FRON THE DEAD OCP. ! %IF SSERIES=NO %START %IF BASIC PTYPE<=3 %START *LSS_(X'6303'); ! CLEAR & DISCARD *LSS_(X'600A'); *OR_X'33' *ST_(X'600A') *LSS_0; *ST_(X'6009'); ! DONT BROADCAST SE INTS %FINISHELSESTART %IF I=MY OCP PORT %START; ! MP INT FROM SELF *LSS_(X'4012'); *AND_X'FFFFFDFF' *ST_(X'4012') %FINISHELSESTART J=X'42000006'!I<<20 *LB_J; *LSS_6; *ST_(0+ %B ) %FINISH *LSS_(X'4013'); *AND_X'FFFF7FFB' *ST_(X'4013'); ! REMOVE MULT AND DD %FINISH %FINISH ! ! If the remaining OCP is not the IPL OCP then clock control must be ! established in this OCP. ALSO ALLOW SAC INTS ! %IF COM_OCP PORT0#MY OCP PORT %START %IF SSERIES=NO %START; ! OPEN SAC INTERRUPT PATHS I=X'8'>>COM_SACPORT0 %IF COM_NSACS>1 %THEN I=I!(X'8'>>COM_SACPORT1) %IF BASIC PTYPE<=3 %START J=(I!I<<4)!!(-1) *LSS_(X'600A'); *AND_J; *ST_(X'600A') %FINISHELSESTART J=I<<12!I<<2 *LSS_(X'4012'); *OR_J; *ST_(X'4012') %FINISH %FINISH CLOCK TO THIS OCP ! ! ALLOW DAP INTERUPTS IF RELEVANT ! %IF DAP FITTED=YES %THENSTART J=0 %FOR I=1,1,MAXLDAP %CYCLE K=COM_CDR(I)_IPDAPNO %IF K#0 %THEN J=J!(X'80000000'>>(K>>4)) %REPEAT %IF J>0 %START; ! A DAP CONFIGURED IN %IF BASIC PTYPE<=3 %START; ! DAP ON 2970 *LSS_(X'600A') *AND_X'F3FFFFFF' *ST_(X'600A') %FINISHELSESTART; ! DAP ON P4 *LSS_(X'4012') *OR_X'0C000000' *ST_(X'4012') %FINISH %FINISH %FINISH %FINISH ! ! FREE UP ANY BUSY KERNEL SERVICE. THESE MUST BE DUE TO HIM ! SINCE MPINT IS MASKED DURING KERNEL ! %CYCLE I=1,1,LOCSN0 %IF SERVA(I)_P&X'40000000'#0 %THEN SERVA(I)_P=SERVA(I)_P!!X'40000000' %AND UNINHIBIT(I) %REPEAT ! ! FREE UP EXECUTING PROCESS ON OTHER OCP IF RELEVANT ! J=X'8000017C'+HIS OCP PORT<<18 I=INTEGER(J); INTEGER(J)=0; ! NO CURRENT PROC ON DEAD OCP %IF I#0 %THENSTART OPMESS(PROCA(I)_USER." CRASHES OCP") I=I+LOCSN0 CLEAR PARMS(I); ! ANY L-C SERVICES CLEAR PARMS(I+(LOCSN2-LOCSN0)); ! ANY ASYNC SERVICES SERVA(I)_P=SERVA(I)_P&X'BFFFFFFF' UNINHIBIT(I) P_DEST=I<<16!4; ! CATASTROPHIC HW ERROR PON(P) %FINISH P_DEST=X'110002'; P_P1=1<<16!HIS OCP PORT CONFIG CONTROL(P); ! FINISH CONFIGURING OFF HIM ->KSERVE %FINISH *IDLE_X'F3' !----------------------------------------------------------------------- IST4I:*JLK_ %TOS ! PERIPHERAL INTS ENTER HERE *LSS_ %TOS; ! OLD STACK *LSS_ %TOS; ! PARAMETER = SAC NUMBER<<20 *ST_I %IF MONLEVEL&4#0 %AND IDLE#0 %THENSTART %IF MPLEVEL+NPQKTIMES %FINISHELSE ->KSERVE %FINISHELSESTART; ! FOR P SERIES PORT=I>>20&3 *LSS_1 *USH_PORT *AND_SACMASK *JAT_4,; ! IGNORE OTHERWISE ! *JAF_4,; ! SAC configured in ! OPMESS("Surprise int. - SAC ".STRINT(PORT).TOSTRING(17)) ! ->KSERVE SACOK: I=X'44000000'!PORT<<20; ! IMAGE STORE ADDR FOR TRUNK FLAGS *LB_I *LSS_(0+ %B ) *JAT_4,; ! NO TRUNK FLAGS *ST_I PROCESS INT: K=0 %CYCLE *LSS_I *SHZ_J *USH_1 *ST_I P_SRCE=0 J=J+K P_P1=PORT<<4!J ->CONROUT(CONTYPE(P_P1)) %IF P_P1<=31 CONROUT(1): %IF SFC FITTED=YES %THENSTART P_DEST=X'280003' DRUM(P) %IF MONLEVEL&4#0 %THEN TSERVICE=42 ->CONTINUE %FINISH CONROUT(0): ! IN CASE OF SPURIOUS BITS %IF MONLEVEL&4#0 %THEN TSERVICE=1 ->CONTINUE CONROUT(2): P_DEST=X'200003' %IF MULTI OCP=YES %AND I#0 %AND COM_NOCPS>1 %THEN PON(P) %ELSE DISC(P); ! PON if more ints. & multi ocp %IF MONLEVEL&4#0 %THEN TSERVICE=34 ->CONTINUE CONROUT(3): P_DEST=X'300003' P_SRCE=M'INT' %IF MULTI OCP=YES %AND I#0 %AND COM_NOCPS>1 %THEN PON(P) %ELSE GDC(P) %IF MONLEVEL&4#0 %THEN TSERVICE=58 CONTINUE: %IF I=0 %THEN ->KTIMES %IF MONLEVEL&4#0 %THENSTART *LSS_(6); *ST_IC; *LSS_(5); *ST_IT *LSS_X'FFFFFF'; *ST_(5); *ST_(6) PERFORM_SERVN(TSERVICE)=PERFORM_SERVN(TSERVICE)+1 PERFORM_SERVIT(TSERVICE)=PERFORM_SERVIT(TSERVICE)+(MAXIT-IT) PERFORM_SERVIC(TSERVICE)=PERFORM_SERVIC(TSERVICE)+(MAXIT-IC) %FINISH K=J+1 %REPEAT %FINISH !----------------------------------------------------------------------- ! EXTRACODE IST10I:*JLK_ %TOS; *IDLE_X'FA' !----------------------------------------------------------------------- ! Primitive IST13I:*JLK_ %TOS; *IDLE_X'FB' !----------------------------------------------------------------------- ! Unit IST14I: *JLK_ %TOS %IF SSERIES=YES %START; ! unit interrupts S series only *LSS_ %TOS; *LSS_ %TOS *ST_I %IF MONLEVEL&4#0 %AND IDLE#0 %THENSTART %IF MPLEVEL+NPQ>24) %IF J=0 %START OPMESS("Unit int.?? ".STRHEX(I)) ->KSERVE %FINISH J=J<<24!(INTEGER(K+8)>>8&255) ! h/w no./00/00/strm K=I>>16&15; ! int. sub-class %IF K=0 %THEN J=J!X'00208000' %ELSE { normal term } %IF K=1 %THEN J=J!X'00208400' %ELSE { abterm } %IF %C K=4 %THEN J=J!X'00204000' { attention } %ELSE J=J!X'00201000' { control term } P_DEST=X'300003' P_P1=J P_P2=I GDC(P) %IF MONLEVEL&4#0 %START TSERVICE=58 ->KTIMES %FINISHELSE ->KSERVE %FINISHELSESTART; ! P series *IDLE_X'FC'; ! should not occur %FINISH !----------------------------------------------------------------------- JLUNQ: ! JUMP&LINK VERSION OF ROUTINE UNQUEUE ! DR DESCRIBES QUEUE *LB_(%DR ); *MYB_8; *ADB_SERVA+4 *LCT_ %B; ! CTB TO SERVQ *LB_(%CTB +1); *STB_ %TOS *MYB_8; *ADB_SERVA+4 *LXN_ %B; ! XNB TO SERV *LSS_(%XNB +0); *OR_X'40000000'; *ST_(%XNB +0) *LB_ %TOS; *CPB_(%DR ); *JCC_7, *LSS_0; *ST_(%DR ); *J_ JLUNQA:*LSS_(%XNB +1); *ST_(%CTB +1) JLUNQB:*LSS_0; *ST_(%XNB +1) *J_ %TOS; ! SERVICE NO IN B !%ROUTINE UNQUEUE(%INTEGERNAME QUEUE,UNQUED SERVICE) !!*********************************************************************** !!* UNQUEUES A SERVICE FROM MAIN OR RUN QUEUES AND MARKS IT * !!* AS BEING EXECUTED * !!*********************************************************************** !%INTEGER SERVICE; ! LOCAL COPY OF UNQUED SERVICE !%RECORD(SERVF)%NAME SERVQ; ! MAPPED ON TO SERVICE AT BACK OF Q !%RECORD(SERVF)%NAME SERV; ! FOR UNQUED SERVICE ! SERVQ==SERVA(QUEUE); ! BACK OF Q. L POINTS TO FRNT ! SERVICE=SERVQ_L; ! SERVICE TO UNQUEUE ! SERV==SERVA(SERVICE) ! SERV_P=SERV_P!X'40000000'; ! MARK AS UNDER EXECUTION ! %IF SERVICE=QUEUE %THEN QUEUE=0 %ELSE SERVQ_L=SERV_L ! SERV_L=0 ! UNQUED SERVICE=SERVICE !%END %END; ! OF GLOBAL CONTROLLER %ROUTINE SCHEDULE(%RECORD (PARMF) %NAME P) !*********************************************************************** !* ACTIVITY 0 : INITIALISE * !* ACTIVITY 1 : CREATE FOREGROUND PROCESS * !* ACTIVITY 2 : REPLY FROM CREATE PROCESS * !* ACTIVITY 3 : OUT OF EPAGES FROM LOCAL CONTROLLER * !* ACTIVITY 4 : OUT OF TIME SLICES FROM LOCAL CONTROLLER * !* ACTIVITY 5 : SUSPEND PROCESS * !* ACTIVITY 6 : TRY AND LOAD FURTHER 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: SNOOZING HAS TIMED OUT * !* ACTIVITY 13: RESCHEDULE ALL RESIDENT TO FREE SMAC * !* ACTIVITY 14: DEADLOCK RECOVERY * !* ACTIVITY 15: UPDATE OPER DIPLAY * !* ACTIVITY 16: CREATE BACKGROUND JOB * !* ACTIVITY 17: START OR RESTART DIRECT * !* ACTIVITY 18: SUSPEND ON FLY? * !*********************************************************************** %ROUTINESPEC PARE EPAGES %ROUTINESPEC ONPQ %CONSTINTEGER PRATMAX=255,PRIQS=5 %CONSTBYTEINTEGERARRAY PRAT(0:PRATMAX)= %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, 1,1,2,1,3,1,1,2,1,1,2,1,1,5,1,2,1,1,2,1,1,1,2,1,1,3,1,1,2,1,1,2, 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, 1,1,2,1,3,1,1,2,1,1,2,1,1,5,1,2,1,1,2,1,1,1,2,1,1,3,1,1,2,1,1,2, 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, 1,1,2,1,3,1,1,2,1,1,2,1,1,5,1,2,1,1,2,1,1,1,2,1,1,3,1,1,2,1,1,2, 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, 1,1,2,1,3,1,1,2,1,1,2,1,1,5,1,2,1,1,2,1,1,1,2,1,1,3,1,1,2,1,1,2 %OWNINTEGER PRATP=0,SCHTICKS=0 !----------------------------------------------------------------------- ! PRIORITY QUEUE ARRAY ETC. %OWNBYTEINTEGERARRAY PQ(1:MAXPROCS)=0(MAXPROCS) %OWNBYTEINTEGERARRAY PQH(1:PRIQS)=0(PRIQS); ! NUMBER OF PRIORITIES=PRIQS %OWNBYTEINTEGERARRAY PQN(1:PRIQS)=0(PRIQS) %IF MONLEVEL&1#0 %THENSTART %OWNINTEGER SUSPN=0 %CONSTSTRING (2) %ARRAY STRPN(1:PRIQS)="P1","P2","P3","P4","P5" %FINISH %CONSTSTRING (16) %ARRAY STARTMESS(0:3)=" PROCESS CREATED", " : SYSTEM FULL"," : NO AMT"," : PROCESS RUNNG" %LONGINTEGERARRAYNAME LST %INTEGER SRCE,ACT,PROCESS,PTY,LSTAD,LSTVAD,LSTACKDA,DCODEDA,DSTACKDA,DGLADA,XEPS,OLDCATSLOT,NEWCATSLOT,INCAR,LCDDP,I, J,K,L,LCSTX %LONGINTEGER LIM %STRING (15) USER %STRING (2) PSTATE %RECORD (CATTABF) %NAME OLDCAT,NEWCAT %RECORD (PROCF) %NAME PROC %SWITCH ACTIVITY(0:20) %IF MONLEVEL&2#0 %AND KMON&1<<3#0 %THEN PKMONREC("SCHEDULE:",P) ACT=P_DEST&X'FFFF' PROCESS=P_P1 %IF 0 SEMALOOP(SCHEDSEMA,0) SSEMAGOT: %FINISH ->ACTIVITY(ACT&255) !----------------------------------------------------------------------- ACTIVITY(0): ! INITIALISE I=FREEEPAGES//2-LSTACKLEN %IF MAXEPAGES>I %THENSTART MAXEPAGES=I %CYCLE I=1,1,MAXCAT-2; ! DONT ADJUST TRASHING CAT %IF CATTAB(I)_EPLIM>MAXEPAGES %THEN CATTAB(I)_EPLIM=MAXEPAGES %REPEAT %FINISH COM_USERS=0 MPLEVEL=0 PAGEFREES=0 DCLEARS=0 %CYCLE I=1,1,MAXPROCS-1 PROCA(I)=0 PINH(I,X'F'); ! INHIBIT LOCSN0&1&2&3 %REPEAT ! ! 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-1 STRPROC=STRINT(I) UPDISP(I,3-LENGTH(STRPROC),STRPROC) %REPEAT %IF MONLEVEL&1#0 %THENSTART DISPLAY TEXT(0,2,0,"RQ1 RQ2 P1 P2 P3 P4 P5 TOTAL STF") DISPLAY TEXT(0,3,0," 0 0 0 0 0 0 0 0 100") %IF SFCFITTED=NO %OR DRUMSIZE=0 %THEN DISPLAY TEXT(0,2,36,"OUTS") %FINISH USER="OCP ".STRINT(COM_OCPPORT0) %IF MULTI OCP=YES %AND COM_NOCPS>1 %THEN CHARNO(USER,4)='s' DISPLAY TEXT(0,4,13,USER) P_DEST=X'80000' ACTIVE MEM(P) %IF SNOOZING=YES %OR MONLEVEL&1#0 %START P_DEST=X'A0001'; ! REGULAR CLOCK TICK P_SRCE=0 P_P1=X'F000F'; ! ON SCHED ALT SERVICE NO P_P2=5; ! AT 5 SEC INTERVALS PON(P); ! FOR VIDEO & BOOTING %FINISH ALLOW PERI INTS=X'01800824'; ! PERMITS INTS BETWEEN KERNEL ! SERVICES NOW INITIALISATION ! IS COMPLETED(XCEPT IT,IC&MP INTS) ! ! START "DIRECT" PROCESS TAKING CARE ITS INCARNATION IS 0 ! AND THAT ALL ITS TEMP SPACE IS IN X40 EPAGES(1 SEGMENT) ! ACTIVITY(17): ! FOR DIRECTOR RESTARTS 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'500'; ! 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) %IF MULTIOCP=YES %START; *TDEC_SCHEDSEMA; %FINISH %RETURN !----------------------------------------------------------------------- ACTIVITY(16): ! CREATE BATCH JOB ACTIVITY(1): ! CREATE FORGROUND PROCESS ! P_P1/P2 : STRING(USER NAME) ! P_P3 : L-C STACK DISC ADDRESS ! P_P4 : DIRCODE DISC ADDRESS ! (<=0 FOR DEFAULT) ! P_P5 : DIR STACK DISC ADDRESS ! P_P6 : DIR GLA DISC ADDRESS SRCE=P_SRCE USER=P_USER INCAR=P_INCAR %IF COM_USERS>=MAXPROCS-1 %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 USER="MAILER" %THEN PROCESS=4 %IF USER="FTRANS" %THEN PROCESS=5 %IF PROCESS>0 %START PROC==PROCA(PROCESS) %IF PROC_USER#"" %THEN P_P1=3 %AND ->STARTREP %FINISHELSESTART %CYCLE PROCESS=FIRST UPROC,1,MAXPROCS-1 PROC==PROCA(PROCESS) %IF PROC_USER="" %THENEXIT %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 CNTRLRL 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 PROC_INCAR=INCAR PROC_ACTIVE=0; ! SUSPENDED PROC_CATEGORY=0 %IF MONLEVEL&1#0 %THEN SUSPN=SUSPN+1 %IF MULTIOCP=YES %START; *TDEC_SCHEDSEMA; %FINISH %IF ACT=16 %START %FOR I=1,1,6 %CYCLE J=BYTEINTEGER(ADDR(USER)+I) %IF 'A'<=J<='Z' %THEN J=J!32 BYTEINTEGER(ADDR(USER)+I)=J %REPEAT %FINISH UPDISP(PROCESS,4,USER) CLEAR PARMS(PROCESS+LOCSN0) CLEAR PARMS(PROCESS+LOCSN1) %UNLESS PROCESS>2&1; ! INITIAL CATEGORY =1 FORE =2BACKGROUND NEWCAT==CATTAB(NEWCATSLOT) PROC_CATEGORY=NEWCATSLOT ->STOUT !----------------------------------------------------------------------- ACTIVITY(3): ! OUT OF EPAGES NEWCATSLOT=OLDCAT_MOREP NEWCAT==CATTAB(NEWCATSLOT) PROC_CATEGORY=NEWCATSLOT ->STOUT !----------------------------------------------------------------------- ACTIVITY(10): ! MORE EPAGES ON THE FLY ? P_P1=0 NEWCATSLOT=OLDCAT_MOREP NEWCAT==CATTAB(NEWCATSLOT) XEPS=NEWCAT_EPLIM-OLDCAT_EPLIM %IF XEPS<=0 %THEN ->WAYOUT %IF RECONFIGURE=YES %AND SMAC RCONFIG#0 %THEN ->WAYOUT %IF OLDCAT_PRIORITY<=3 {%AND PROC_STATUS&HADPONFLY=0} %AND XEPSGIVE PAGES ->WAYOUT %IF XEPS>SHAREDEPS+UNALLOCEPS I=1; J=0; K=OLDCAT_PRIORITY; ! CHECK FOR HIGHER PRIORITY WK %IF K=5 %THEN K=4; ! QUEUES 4 & 5 EQIVALENT %WHILE IWAYOUT; ! NO: MORE URGENT WORK GIVE PAGES: ! WITHOUT BOUNCING PROC_STATUS=PROC_STATUS!HADPONFLY; ! SO HE WONT DO IT AGAIN UNALLOCEPS=UNALLOCEPS-XEPS PROC_CATEGORY=NEWCATSLOT P_P1=NEWCAT_EPLIM PROC_EPA=NEWCAT_EPLIM CONT: P_P2=NEWCAT_RTLIM P_P3=NEWCAT_STROBEI; ! SO L-C CAN DECIDE TO STROBE %IF OLDCAT_PRIORITY>=4 %THEN P4PAGES=P4PAGES-OLDCAT_EPLIM %IF NEWCAT_PRIORITY>=4 %THEN P4PAGES=P4PAGES+NEWCAT_EPLIM %IF NEWCAT_PRIORITY=4=OLDCAT_PRIORITY %AND PROC_P4TOP4<255 %AND PROCESS>=FIRST UPROC %THEN %C PROC_P4TOP4=PROC_P4TOP4+1 %IF MONLEVEL&32#0 %THEN FLYCAT(NEWCATSLOT,OLDCATSLOT)<-FLYCAT(NEWCATSLOT,OLDCATSLOT)+1 WAYOUT: %IF MULTIOCP=YES %START; *TDEC_SCHEDSEMA; %FINISH %RETURN !----------------------------------------------------------------------- ACTIVITY(4): ! OUT OF TIME NEWCATSLOT=OLDCAT_MORET PARE EPAGES ->STOUT !----------------------------------------------------------------------- ACTIVITY(11): ! MORE TIME ON THE FLY? ! BE KIND TO VOLUMS&SPOOLR P_P1=0 %IF OLDCAT_PRIORITY>=4 %AND P4PAGES>=MAXP4PAGES %AND SXPAGES>(SHAREDEPS+UNALLOCEPS) %AND %C PROCESS>=FIRST UPROC %THEN ->WAYOUT %IF RECONFIGURE=YES %AND SMAC RCONFIG#0 %THEN ->WAYOUT NEWCATSLOT=OLDCAT_MORET NEWCAT==CATTAB(NEWCATSLOT) %IF PROC_STATUS&HADTONFLY=0 %AND (SFC FITTED=NO %OR PQN(1)+PQN(2)=0) %THEN ->GIVE TIME I=1; J=0; K=NEWCAT_PRIORITY %IF K=4 %THEN K=5; ! QUEUES 4 & 5 EQUIVALENT HERE %WHILE I<=K %CYCLE J=J+PQN(I) I=I+1 %REPEAT %IF J#0 %AND PROCESS>=FIRST UPROC %THEN ->WAYOUT ! CANNOT ALLOW VOLS&SPOOLR MORE ! TIME IF SYSTEM IS CONFGRD ! SO ONLY 1 P4 CAN BE IN STORE %IF PROCESS0 %AND P4PAGES<=OLDCAT_EPLIM %THEN ->WAYOUT GIVE TIME: ! WITHOUT REQUEING PROC_STATUS=PROC_STATUS!HADTONFLY PARE EPAGES; ! AND MAP NEWCAT UNALLOCEPS=UNALLOCEPS+OLDCAT_EPLIM-NEWCAT_EPLIM P_P1=NEWCAT_EPLIM PROC_EPA=NEWCAT_EPLIM ->CONT !----------------------------------------------------------------------- ACTIVITY(18): ! SUSPEND ON FLY(IE WITHOUT ! PAGING WOKSET OUT)? %IF SNOOZING=YES %THENSTART ! %IF SHAREDEPS+UNALLOCEPS1 %C ! %THEN ->WAYOUT; ! NO ! %IF RECONFIGURE=YES %AND SMAC RCONFIG#0 %THEN ->WAYOUT I=(PQN(1)+PQN(2))*MAXEPAGES>>1; ! PAGES NEEDED TO CLERAR QS ! ! THE NEXT CONDITION IS CRUCIAL FOR SATISFACTORY SNOOZING ! CAN NOT AFFORD IN GENERAL TO ALLOW ANYONE TO SNOOZE WHEN THERE ARE ! NOT ENOUGH FREE PAGES TO CLEAR QUEUEING INTEGERACTIVE PROCESSES ! HOWEVER IN LARGE STORE NO DRUM CONFIGURATIONS QUEUEING MAY BE ! DUE TO LARGE NUMBER OF PAGE FREES BUILDING UP. IN THESE CIRCUMSTANCES ! IT IS BETTER TO LET THIS CHAP SNOOZE TILL THING QUIETEN DOWN. ! THE BIGGER THE STORE THE TRUEUER THIS IS SO DO NOT SCALE PAGE FREES ! FOR BIGGER CORE SIZES ! %IF I>FREE EPAGES+PAGE FREES %AND (PAGE FREES>2 %OR (SFC FITTED=YES %AND DRUMSIZE>0)) %THEN %C ->WAYOUT NEWCATSLOT=OLDCAT_SUSP %IF MONLEVEL&1#0 %THENSTART SUSPN=SUSPN+1 UPDISP(PROCESS,11,"Z ") %FINISH I=8!(1<<((P_SRCE-LOCSN0)//MAXPROCS)) PUNINH(PROCESS,I) PROC_ACTIVE=0 PROC_STATUS=PROC_STATUS!SNOOZED PARE EPAGES PROC_EPA=NEWCAT_EPLIM UNALLOCEPS=UNALLOCEPS+OLDCAT_EPLIM-PROC_EPN %IF MONLEVEL&32#0 %THEN FLYCAT(NEWCATSLOT,OLDCATSLOT)<-FLYCAT(NEWCATSLOT,OLDCATSLOT)+1 MPLEVEL=MPLEVEL-1 %IF OLDCAT_PRIORITY>=4 %THEN P4PAGES=P4PAGES-OLDCAT_EPLIM; ! PEDANTIC ! P_DEST=X'A0002'; P_SRCE=X'30012'; ! KICK ELAPSED INT P_P1=X'3000C'!PROCESS<<8 P_P2=SNOOZTIME; P_P3=PROCESS PON(P) P_P1=0; ! YES MAY SUSPEND ON FLY %FINISH %IF NPQ#0 %THEN P_DEST=X'30006' %AND PON(P) ->WAYOUT !---------------------------------------------------------------------- ACTIVITY(5): ! SUSPEND %IF MONLEVEL&1#0 %THEN SUSPN=SUSPN+1 I=8!(1<<((P_SRCE-LOCSN0)//MAXPROCS)) PUNINH(PROCESS,I) PSTATE="S " %IF PROC_STATUS&AMT LOST=0 %AND SMAC RCONFIG=0 %AND (PROCESSSTOUT !----------------------------------------------------------------------- ACTIVITY(7): ! UNSUSPEND %IF PROC_ACTIVE=255 %THEN ->WAYOUT; ! RACE CONDITION WITH BOOTONFLY %IF MONLEVEL&1#0 %THEN SUSPN=SUSPN-1 %IF SNOOZING=YES %AND PROC_STATUS&SNOOZED#0 %START; ! PROCESS IN STORE PROC_STATUS=PROC_STATUS!!SNOOZED MPLEVEL=MPLEVEL+1 PROC_RUNQ=OLDCAT_RQTS1 %IF MONLEVEL&4#0 %THEN PERFORM_SNOOZOK=PERFORM_SNOOZOK+1 %IF MONLEVEL&1#0 %THEN UPDISP(PROCESS,11,"R".TOSTRING(PROC_RUNQ+'0')) P_DEST=(PROCESS+LOCSN0)<<16!3 P_SRCE=X'30000' P_P1=OLDCAT_EPLIM P_P2=OLDCAT_RTLIM UNALLOCEPS=UNALLOCEPS+PROC_EPN-PROC_EPA %IF OLDCAT_PRIORITY>=4 %THEN P4PAGES=P4PAGES+OLDCAT_EPLIM PROC_ACTIVE=255 PON(P) %IF MONLEVEL&4#0 %THEN PERFORM_SNOOZN=PERFORM_SNOOZN+LSTACKLENP ->WAYOUT %FINISH PROC_ACTIVE=255 %IF OLDCAT_PRIORITY<4 %AND PROC_STATUS&(STATEX+4)=STATEX %THEN SXPAGES=SXPAGES-PROC_EPN ONPQ ->LOAD !----------------------------------------------------------------------- ACTIVITY(8): ! DESTROY PROCESS MPLEVEL=MPLEVEL-1 DESTROY: UPDISP(PROCESS,4," ") COM_USERS=COM_USERS-1 PINH(PROCESS,X'F'); ! ALL PROCESS SERVICES %IF OLDCAT_PRIORITY>=4 %THEN P4PAGES=P4PAGES-OLDCAT_EPLIM P_DEST=X'40002'; ! PAGE-TURN OUT P_SRCE=X'30008' P_P2=0; ! REGARD AS NOT WRITTEN TO %CYCLE I=0,1,LSTACKLEN-1 P_P1=PROC_LAMTX<<16!I PON(P) %REPEAT P_DEST=X'80002'; ! RETURN AMTX FOR L-CNTRLR STACK P_P1=0; ! ID NOT USED P_P2=PROC_LAMTX P_P3=1; ! DESTROY FLAG PON(P) PROC=0 ->DEALL !----------------------------------------------------------------------- STOUT: ! PAGE-OUT LOCAL CONTROLLER STACK %IF NEWCAT_PRIORITY=4=OLDCAT_PRIORITY %AND PROC_P4TOP4<255 %AND PROCESS>=FIRST UPROC %THEN %C PROC_P4TOP4=PROC_P4TOP4+1 %IF MONLEVEL&32#0 %THEN CATREC(NEWCATSLOT,OLDCATSLOT)<-CATREC(NEWCATSLOT,OLDCATSLOT)+1 ACTIVITY(14): ! DEADLOCK RECOVERY MPLEVEL=MPLEVEL-1 P_DEST=X'40002'; ! PAGETURN/PAGE-OUT P_SRCE=X'3008A' %IF PROC_STATUS&STATEX#0 %THEN I=LSTACKLENP %ELSE I=0 %CYCLE I=I,1,LSTACKLEN-1 P_P1=PROC_LAMTX<<16!I %IF I>=LSTACKLENP %THEN P_P2=2 %ELSE P_P2=X'D'; ! MAKE END "NEW" PON(P); ! NO REPLIES %REPEAT %IF OLDCAT_PRIORITY>=4 %THEN P4PAGES=P4PAGES-OLDCAT_EPLIM PROC_RUNQ=0 %UNLESS ACT=5 %THEN ONPQ; ! UNLESS SUSPENEDED DEALL: ! DEALLOCATE PROCESSES EPAGES UNALLOCEPS=UNALLOCEPS+OLDCAT_EPLIM+LSTACKLEN PROC_EPA=0 !----------------------------------------------------------------------- ACTIVITY(6): ! MORE LOADS LOAD: ! LOAD FURTHER PROCESS(ES) ! ! TRY TO LOAD AS MANY WAITING ! PROCESSES AS POSSIBLE EXCEPT THAT ONLY "MAXP4PAGES" OF BIG JOBS ARE ! LOADED EXCEPT WHEN THERE ARE NO INTERACTIVE JOBS ASLEEP IN QUEUES 1-3 ! THIS COUNT IS MAINTAINED IN 'NP4L' ! %IF NPQ=0 %OR DONT SCHED#0 %THEN ->WAYOUT AGN: %CYCLE PTY=PRAT(PRATP) %EXITIF PQH(PTY)#0 PRATP=(PRATP+1)&PRATMAX %REPEAT %IF SFC FITTED=NO %AND PTY>=3 %AND PAGEFREES>=40 %START; ! TOO MANY WRITEOUT PRATP=(PRATP+1)&PRATMAX; ! PASS OVER BIG JOB %IF MULTIOCP=YES %START; *TDEC_SCHEDSEMA; %FINISH P_DEST=X'A0002' P_P1=X'30006'; P_P2=1 PON(P); ! WAIT 1 SEC %RETURN %FINISH PROCESS=PQ(PQH(PTY)) PROC==PROCA(PROCESS) OLDCATSLOT=PROC_CATEGORY OLDCAT==CATTAB(OLDCATSLOT) ! ! THE IDEA OF THE NEXT FEW LINES IS TO RESTRICT P4 JOBS TO 1 OR TO ! P4PAGES OF STORE EXCEPT WHEN THERE ARE SO FEW FOREGROUND USERS ! ASLLEEP THAT THEY WILL NOT BE INCONVENINECED. ! %IF PTY>=4 %THENSTART %IF P4PAGES>0 %AND P4PAGES+OLDCAT_EPLIM>MAXP4PAGES %AND SXPAGES>(SHAREDEPS+UNALLOCEPS) %START %IF NPQ>PQN(4)+PQN(5) %THEN PRATP=(PRATP-31)&PRATMAX %AND ->AGN ->WAYOUT %FINISH %FINISH I=OLDCAT_EPLIM+LSTACKLEN %IF I>SHAREDEPS+UNALLOCEPS %AND MPLEVEL>0 %THENSTART; ! NOT ENOUGH ROOM ->WAYOUT %FINISH PROC_EPA=OLDCAT_EPLIM UNALLOCEPS=UNALLOCEPS-I PRATP=(PRATP+1)&PRATMAX; ! TO NEXT PRIORITY Q %IF PTY>=4 %THEN P4PAGES=P4PAGES+OLDCAT_EPLIM %IF PROCESS=PQH(PTY) %THEN PQH(PTY)=0 %ELSE PQ(PQH(PTY))=PQ(PROCESS) NPQ=NPQ-1 PQN(PTY)=PQN(PTY)-1 %IF MULTIOCP=YES %START; *TDEC_SCHEDSEMA; %FINISH ! PAGE IN LOCAL CONTROLLER STACK P_SRCE=X'30009' %IF PROC_STATUS&STATEX#0 %THEN I=LSTACKLENP %ELSE I=0 PQ(PROCESS)=LSTACKLEN-I; ! TO COUNT PAGE-TURN REPLIES %CYCLE I=I,1,LSTACKLEN-1 %IF I=LSTACKLEN %START; ! ROOM FOR ANOTHER? P_DEST=X'30006'; ! YES KICK OURSELVES AGAIN P_SRCE=P_DEST; ! SINCE THIS IS NOT COMMON AND PON(P); ! AND THIS SIMPLIFIES DUALS %FINISH %RETURN !----------------------------------------------------------------------- ACTIVITY(12): ! SNOOZING TIMED OUT FROM ELAPSED INT %IF SNOOZING=YES %AND PROC_STATUS&SNOOZED#0 %START PROC_STATUS=PROC_STATUS&(\SNOOZED) PROC_ACTIVE=255 UNALLOCEPS=UNALLOCEPS+PROC_EPN-PROC_EPA MPLEVEL=MPLEVEL+1 %IF MONLEVEL&4#0 %THEN PERFORM_SNOOZTO=PERFORM_SNOOZTO+1 %IF MONLEVEL&1#0 %THEN SUSPN=SUSPN-1 P_DEST=(PROCESS+LOCSN0)<<16!8 P_SRCE=X'3000C' PON(P) %FINISH %IF MULTIOCP=YES %START; *TDEC_SCHEDSEMA; %FINISH %RETURN !----------------------------------------------------------------------- ACTIVITY(13): ! RESCHEDULE ALL RESIDENT TO FREE SMAC %CYCLE I=1,1,MAXPROCS PROC==PROCA(I) %IF PROC_USER#"" %START P_DEST=(COM_ASYNCDEST+I)<<16 P_SRCE=X'3000D' P_P1=3; ! DUMMY ACT %IF PROC_ACTIVE=255 %OR PROC_STATUS&SNOOZED#0 %THEN PON(P) %ANDCONTINUE %IF PROC_STATUS&STATEX#0 %START K=AMTA(PROC_LAMTX)_DDP %CYCLE J=0,1,LSTACKLENP-1 %IF STORE(AMTDD(J+K))_REALAD>>20&15=SMAC RCONFIG %THEN PON(P) %ANDEXIT %REPEAT %FINISH %FINISH %REPEAT ->WAYOUT !----------------------------------------------------------------------- ACTIVITY(9): ! L-C STACK PAGE ARRIVED I=P_P1&X'FF'; ! EPAGE NO PROCESS=P_P1>>8&X'FF' PROC==PROCA(PROCESS) PQ(PROCESS)=PQ(PROCESS)-1 %IF I=0 %THEN PROC_LSTAD=P_P2; ! REAL ADDR OF NEW LST %IF P_P3#0 %THEN PROC_STATUS=PROC_STATUS!LCSTFAIL; ! FAIL FLAG ->WAYOUT %UNLESS PQ(PROCESS)=0; ! WAIT UNTIL ALL PAGES HERE OLDCATSLOT=PROC_CATEGORY OLDCAT==CATTAB(OLDCATSLOT) %IF PROC_STATUS&LCSTFAIL#0 %START; ! FAILED TO READ L-C STACK ! THIS IS NOT RECOVERABLE AS ! PAGETURN WILL HAVE TRIED DRUM ! AND DISC. MUST DESTROY PROCESS PRINT STRING("LOCAL CONTROLLER STACK READ FAIL, PROCESS ".STRINT(PROCESS)) ->DESTROY %FINISH LSTAD=PROC_LSTAD LSTVAD=(SEG64+LSTAD)!PUBSEG LST==ARRAY(LSTVAD,LSTF); ! LOCAL SEG TABLE IN SEG 0 LIM=LSTACKLEN*EPAGESIZE-1 K=LSTAD+(LSTLEN*8+X'50') LST(0)=X'4150038080000001'!LIM<<42!K ! FILL IN PAGE TABLE ENTRIES ! BY DIGGING IN AMT AND STORE TABLES K=LSTVAD+(LSTLEN*8+X'50') LCDDP=AMTA(PROC_LAMTX)_DDP; ! DD POINTER FOR PAGE O OF LC %IF PROC_STATUS&STATEX#0 %THENSTART PROC_STATUS=PROC_STATUS!!STATEX %IF MONLEVEL&4#0 %THEN PERFORM_SNOOZN=PERFORM_SNOOZN+LSTACKLENP I=LSTACKLENP %FINISHELSE I=0 %CYCLE I=I,1,LSTACKLEN-1 LCSTX=AMTDD(LCDDP+I); ! DRUM OR STORE POINTER ! NB PAGE MUST BE INCORE ! NOT ALL CASES NEED TO BE TESTED %IF SFCFITTED=YES %AND LCSTX&DTXBIT#0 %THEN LCSTX=DRUMT(LCSTX&STXMASK) L=X'80000001'!STORE(LCSTX)_REALAD %CYCLE J=0,1,EPAGESIZE-1 INTEGER(K+4*EPAGESIZE*I+J<<2)=L+J<<10 %REPEAT %REPEAT LST(1)=X'00F0000080000001'!LCACR<<56!(LSTAD+LSTLEN*8) PROC_RUNQ=OLDCAT_RQTS1 %IF MONLEVEL&1#0 %THEN UPDISP(PROCESS,11,"R".TOSTRING(PROC_RUNQ+'0')) MPLEVEL=MPLEVEL+1 %IF OLDCATSLOT=0 %THENSTART; ! PROCESS BEING CREATED ! LST ENTRIES >=2 ZERO ALREADY I=LSTVAD+8*LSTLEN; ! PUBLIC ADR OF LOCAL SEG 1 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 %FINISHELSESTART P_DEST=(PROCESS+LOCSN0)<<16!1; ! TO L-C : START NEW RESIDENCE P_SRCE=X'30000' P_P1=OLDCAT_EPLIM P_P2=OLDCAT_RTLIM ! ! IF THE PERSON HAS USED A LOT OF P4 TIME FROM THE TERMINAL PENALISE ! HIM BY GRADUALLY REDUCING HIS RESIDENCE TIMES. IF HE GETS TIME ON ! THE FLY THEN HE AND THE SYSTEM WILL NOT BE AFFECTED ! %IF PROCESS>=FIRST UPROC %AND OLDCAT_PRIORITY=4 %AND PROC_P4TOP4>16 %THEN P_P2=P_P2*(300-PROC_P4TOP4)//300 PON(P) %FINISH %IF MULTIOCP=YES %START; *TDEC_SCHEDSEMA; %FINISH %RETURN !----------------------------------------------------------------------- ACTIVITY(15): ! UPDATE OPER INFO(EVERY 5 SECS) SCHTICKS=SCHTICKS+1 %IF SCHTICKS&3=0 %START; ! @EVERY 20 SECS I=1; J=0 %UNTIL J=COM_USERS %OR I>MAXPROCS %CYCLE PROC==PROCA(I) %IF PROC_USER#"" %THENSTART %IF I>=FIRST UPROC %AND PROC_ACTIVE=3*MINSINACTIVE %AND PROC_STATUS&X'404'=0 %START; ! NOT BATCH OR DAP 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 %FINISH %IF MULTIOCP=YES %START; *TDEC_SCHEDSEMA; %FINISH %IF MONLEVEL&1#0 %THENSTART %BEGIN %INTEGERARRAY RUNQ(0:2) %IF MONLEVEL&256#0 %START %INTEGER SNOOS,PGFLT SNOOS=0; PGFLT=0 %FINISH %CYCLE I=0,1,2 RUNQ(I)=0 %REPEAT J=0; I=1 %UNTIL J=COM_USERS %OR I>MAXPROCS %CYCLE PROC==PROCA(I) %IF PROC_USER#"" %THENSTART J=J+1 %IF PROC_ACTIVE=255 %THEN RUNQ(PROC_RUNQ)=RUNQ(PROC_RUNQ)+1 %IF MONLEVEL&256#0 %START %IF PROC_STATUS&SNOOZED#0 %THEN SNOOS=SNOOS+1 %IF PROC_STATUS&2#0 %THEN PGFLT=PGFLT+1 %FINISH %FINISH I=I+1 %REPEAT %CYCLE I=1,1,2 DISPLAY TEXT(0,3,I*4-3,STRINT(RUNQ(I))." ") %REPEAT %CYCLE I=1,1,5 DISPLAY TEXT(0,3,I*3+7,STRINT(PQN(I))." ") %REPEAT DISPLAY TEXT(0,3,27,STRINT(COM_USERS)." ") I=100*FREE EPAGES//COM_SEPGS DISPLAY TEXT(0,3,31,STRINT(I)."% ") %IF SFCFITTED=NO %OR DRUMSIZE=0 %THEN DISPLAY TEXT(0,3,36,STRINT(PAGEFREES)." ") %IF MON LEVEL&256#0 %START; ! include harvesting? HARVEST(1,0,20,COM_USERS<<24!RUNQ(1)<<16!RUNQ(2)<<8!PGFLT,PQN(1)<<24!PQN(2)<<16!PQN(3)<<8!PQN(4), PQN(5)<<24!SUSPN<<16!SNOOS<<8,PAGEFREES<<16!UNALLOCEPS,FREEEPAGES<<16) %IF %C TRACE=YES %AND TRACE EVENTS&(1<<1)#0 %FINISH %END %FINISH %RETURN !----------------------------------------------------------------------- ACTIVITY(19): ! SET BITS IN P_P2 INTO STATUS ! OF PROCESS IN P_P1 PROC_STATUS=PROC_STATUS!P_P2 ->WAYOUT ACTIVITY(20): ! CONVERSE OF 19 PROC_STATUS=PROC_STATUS&(\P_P2) ->WAYOUT %ROUTINE PARE EPAGES !*********************************************************************** !* CHAIN BACK DOWN CATEGORY TABLE TO FIND THE BEST FIT * !* AFTER ALLOWING SOME LEEWAY * !*********************************************************************** %CONSTINTEGER LEEWAY=2 %CYCLE NEWCAT==CATTAB(NEWCATSLOT) %IF NEWCAT_LESSP=0 %OR P_P2+LEEWAY>CATTAB(NEWCAT_LESSP)_EPLIM %THEN PROC_CATEGORY=NEWCATSLOT %ANDRETURN NEWCATSLOT=NEWCAT_LESSP %REPEAT %END !----------------------------------------------------------------------- %ROUTINE ONPQ !*********************************************************************** !* PUT PROCESS ONTO APPROPIATE PRIORITY QUEUE AS GIVEN IN THE * !* CATEGORY TABLE. NORMALLY PROCESSES GO TO THE BACK OF QUEUE BUT * !* THEY ARE HOLDING A SEMA THEY GO TO THE FRONT * !*********************************************************************** PTY=CATTAB(PROC_CATEGORY)_PRIORITY %IF PQH(PTY)=0 %THEN PQ(PROCESS)=PROCESS %ELSE PQ(PROCESS)=PQ(PQH(PTY)) %AND PQ(PQH(PTY))=PROCESS PQH(PTY)=PROCESS %UNLESS (PROCESS=1 %OR PROC_STATUS&1#0) %AND PQH(PTY)#0 NPQ=NPQ+1; ! COUNT PROCESSES QUEUED PQN(PTY)=PQN(PTY)+1 %IF MONLEVEL&1#0 %THEN UPDISP(PROCESS,11,STRPN(PTY)) %END %END !----------------------------------------------------------------------- %ROUTINE PAGETURN(%RECORD (PARMF) %NAME P) !*********************************************************************** !* FOR ALL ACTS : P_P1=AMTX<<16!EPX * !* ACTIVITY 1 : "PAGE IN" REQUEST FROM LOCAL CONTROLLER * !* : P_P2=RETURNABLE IDENTIFIER * !* ACTIVITY 2 : "PAGE OUT" REQUEST FROM LOCAL CONTROLLER * !* : P_P2=FLAGS (BEING THE BOTTOM 4 BITS OF STOREFLAGS) * !* ACTIVITY 3 : REPLY FROM "EPAGE" WITH EPAGE P_P2=STOREX * !* ACTIVITY 4 : ZERO "NEW" DISC EPAGE * !* ACTIVITY 5 : REPLY FROM DISC/WRITE * !* ACTIVITY 6 : REPLY FROM DRUM/READ ON FAILURE ONLY * !* ACTIVITY 7 : REPLY FROM DRUM/WRITE * !* ACTIVITY 8 : REPLY FROM ZERO DISC EPAGE * !* ACTIVITY 9 : AS ACT 1 BUT PLACE IN SYSTEM SMAC IF POSSIBLE * !* STORE FLAGS SIGNIFY AS FOLLOWS : * !* 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 IE DONT PAGE OUT & SUPPLY ZEROPAGE ON REREAD * !* BIT 0 : RECAPTURABLE(IF ON FREE LIST ON PAGING OUT) * !*********************************************************************** %CONSTINTEGER ZEROPAGEAD=X'804C0000' %INTEGER AEX,AMTX,EPX,DDX,DTX,FLAGS,STOREX,SRCE,CALL,ID,I,B,F,PAGEMASK %IF MONLEVEL&12=12 %THENSTART %INTEGER IT,IC %FINISH %HALFINTEGERNAME AMTDDDDX %RECORD (AMTF) %NAME AMT %RECORD (STOREF) %NAME ST %RECORD (PARMXF) %NAME PP %IF SFC FITTED=YES %THENSTART %RECORD (PARMF) TDRUM,TDISC %FINISHELSESTART %RECORD (PARMF) TDISC %FINISH %SWITCH ACTIVITY(0:9) %IF MONLEVEL&2#0 %AND KMON&1<<4#0 %THEN PKMONREC("PAGETURN:",P) ! AEX=P_P1 ! AMTX=AEX>>16 ! EPX=AEX&X'FFFF' *LCT_P+4; *LSS_(%CTB +2); *ST_AEX *LUH_0; *USH_16; *SHS_-16; *ST_AMTX ! AMT==AMTA(AMTX) *LB_AMTX; *MYB_AMTFLEN *LD_AMTA; *MODD_ %B; *STD_AMT ! DDX=AMT_DDP+EPX *LDTB_X'58000002'; *LB_(%DR +4) *ADB_EPX; *STB_DDX; ! AMTDDDDX==AMTDD(DDX) *ADB_ %B; *LD_AMTDD *INCA_ %B; *STD_AMTDDDDX %IF MULTIOCP=YES %THENSTART *INCT_(STORESEMA) *JCC_8, SEMALOOP(STORESEMA,0) SSEMAGOT: %FINISH I=AMTDDDDX ! %IF SFCFITTED=NO %OR I&DTXBIT=0 %START;! NO DRUM PAGE ALLOCATED ! STOREX=I&STXMASK ! DTX=-1 ! %FINISH %ELSE %START ! DTX=I&STXMASK ! STOREX=DRUMT(DTX) ! %FINISH %IF SFC FITTED=YES %THENSTART *LSS_I; *AND_DTXBIT; *JAT_4, *LB_I; *SBB_DTXBIT; *STB_DTX *ADB_ %B; *LSS_(DRUMT+ %B ) *ST_STOREX; *J_ MCL1: %FINISH *LSS_I *AND_STXMASK; *ST_STOREX *LSS_-1; *ST_DTX MCL2: ->ACTIVITY(P_DEST-X'40000') !----------------------------------------------------------------------- ACTIVITY(9): ! PAGE INTO SYTEM SMACS PAGEMASK=COM_SMACS>>16 ->ACT1 ACTIVITY(1): ! PAGE-IN (ALLOWS PAGETURN TO BE CALLED) PAGEMASK=-1 ACT1: %IF MONLEVEL&4#0 %THEN PERFORM_PTURNN=PERFORM_PTURNN+1 AMT_USERS=AMT_USERS+1 CALL=P_SRCE SRCE=CALL&X'7FFFFFFF' ID=P_P2 %IF STOREX=STXMASK %THEN ->FETCH PAGE HERE: ! EPAGE ALLOCATED ST==STORE(STOREX) ! ->NOTRECAP %UNLESS ST_FLAGS=1 %AND ST_USERS=0;! RECAPTURE ! ST_FLAGS=0 ! ST_USERS=1 ! ST_LINK=0 ! F=ST_FLINK ! B=ST_BLINK ! ST_BLINK=AMTX ! ST_FLINK=EPX *LCT_ST+4; *LSS_(%CTB +0) *USH_-16; *ICP_X'0100'; ! FLAGS=1 & USERS=0 *JCC_7, *LSS_(%CTB +1); *LUH_0 *USH_16; *SHS_-16; *ST_B; ! UNPACK&STORE BOTH LINKS *LSS_AEX; *LUH_X'00010000'; ! SET FLAGS,USERS&LINK IN ONE *ST_(%CTB +0) STORE(B)_FLINK=F STORE(F)_BLINK=B FREEEPAGES=FREEEPAGES-1 %IF FREEEPAGES=0 %THEN INHIBIT(5) %IF MONLEVEL&4#0 %THEN PERFORM_RECAPN=PERFORM_RECAPN+1 ->PAGEIN REPLY NOTRECAP: ! PAGE MUST BE SHARED %IF ST_USERS=0 %THENSTART; ! PAGE-OUT IN PROGRESS PAGEFREES=PAGEFREES-1 %FINISHELSESTART SHAREDEPS=SHAREDEPS+1 %FINISH ST_USERS=ST_USERS+1 %IF MONLEVEL&4#0 %THEN PERFORM_PSHAREN=PERFORM_PSHAREN+1; ! PAGE SAVED BY SHARING ! IF PAGE IS COMING IN MUST AWAIT ! ITS ARRIVAL. USE PIT LIST %IF ST_FLAGS&X'C0'=X'80' %OR (SFCFITTED=YES %AND ST_FLAGS&X'30'=X'20') %START *JLK_ MUST WAIT: ! FOR FREE PAGE OR TRANSFER %IF MULTIOCP=YES %START; *TDEC_(STORESEMA); %FINISH P_DEST=0; ! IF CALLED MEANS PAGE COMING %RETURN %FINISH PAGEIN REPLY: ! INTACT COPY IN STORE IF ! RECAPTURED OR PAGING OUT:REPLY ! PAGE IMMEDIATELY AVAILABLE P_P1=ID; ! IDENTIFIER P_P2=ST_REALAD&X'0FFFFFFF'; ! MAY BE FLAWED(BIT SET IN TOP) P_P3=0; ! SUCCESS %IF MONLEVEL&256#0 %START P_P5=ST_USERS P_P6=ST_FLAGS %FINISH %IF MULTIOCP=YES %START; *TDEC_(STORESEMA); %FINISH %IF CALL>0 %THEN P_DEST=SRCE %AND P_SRCE=X'40001' %AND PON(P) %RETURN FETCH PAGE: ! ALLOCATE EPAGE %IF AMTDDDDX&NEWEPBIT#0 %THEN I=0 %ELSE I=1; ! CLEAR IF NEW %IF FREE EPAGES>0 %THEN STOREX=QUICK EPAGE(I,PAGEMASK) %AND ->ACT3 P_SRCE=X'40003' P_P1=AEX P_P2=I; ! =0 FOR ZEROED P_P5=SRCE P_P6=ID %IF LOCSN0>16<=LOCSN1 %THEN GET EPN=GET EPN+1 %IF MULTIOCP=YES %START; *TDEC_(STORESEMA); %FINISH %IF PAGEFREES<=1 %AND GETEPN>=MPLEVEL+1-COM_NOCPS %THEN P_DEST=X'20000' %AND PON(P) P_DEST=X'50000' PON(P) P_DEST=0; ! IN CASE PAGETURNED CALLED %RETURN !----------------------------------------------------------------------- ACTIVITY(3): ! REPLY FROM GET EPAGE CALL=1; ! I.E. >0 SRCE=P_P5 ID=P_P6 ! ! THERE ARE TWO COMPLICATIONS WHICH MUST BE DEALT WITH BEFORE GOING ! ON TO SET UP THE TRANSFER. FIRSTLY WE MAY GET PAGE 0 MEANING THE SYSTEM ! HAS DEADLOCKED. PASS THIS BACK TO LOCAL CONTROLLER WITH SPECIAL FLAG ! MEANING "PLEASE DEPART AS FAST AS POSSIBLE". ! THE OTHER POSSIBILTY IS THAT MORE THAN ONE PROCESS HAS ASKED ! FOR THIS PAGE WHILE THE FIRST IS AWAITING STORE. CARE IS REQUIRED TO ! AVOID LOSING A PAGE IN THESE CIRCOMSTANCES ! %IF P_P2=0 %THENSTART; ! DEADLOCK PAGE ZERO P_DEST=SRCE!1; ! FAILED TO PRODUCE PAGE P_P3=-1; ! PLEASE DEPART ! AMT_USERS=AMT_USERS-1 %IF MULTIOCP=YES %START; *TDEC_(STORESEMA); %FINISH PON(P) %RETURN %FINISH %IF STOREX#STXMASK %THENSTART; ! PAGE HAS ARRIVED BEFORE P_DEST=X'60000'; ! RETURN EPAGE P_SRCE=X'80040003' PON(P) ->HERE %FINISH STOREX=P_P2 ACT3: ! ENTERS HERE IF PAGE AVAILABLE ST==STORE(STOREX) ! ST_USERS=1 ! ST_LINK=0 ! ST_BLINK=AMTX ! ST_FLINK=EPX *LCT_ST+4; *LSS_AEX *LUH_X'00010000'; *ST_(%CTB +0) %IF AMTDDDDX&NEWEPBIT#0 %THENSTART; ! NEW EPAGE AMTDDDDX=STOREX; ! NOT "NEW" & NOT DRUM ST_FLAGS=8; ! "WRITTEN" %IF MONLEVEL&4#0 %THEN PERFORM_NEWPAGEN=PERFORM_NEWPAGEN+1 ->PAGEIN REPLY %FINISH ! ! IT IS NECESSARY TO TRANSFER THE PAGE IN FROM DRUM OR DISC ! %IF SFCFITTED=YES %AND DTX>=0 %START; ! PAGE ON DRUM DRUMT(DTX)=STOREX *JLK_ ST_FLAGS=X'20'; ! DRUM->STORE TRANSIT FLAGS=X'20'; ! DRUM TRANSFER TO BE STARTED %IF MULTIOCP=YES %START; *TDEC_(STORESEMA); %FINISH TDRUM_DEST=X'280001' TDRUM_SRCE=X'80040006' TDRUM_P1=AEX TDRUM_P2=DTX TDRUM_P3=STOREX P_DEST=0; ! IN CASE CALLED ->TRANSFER NEEDED %FINISH ! NO DRUMS OR PAGE IS ON DISC *JLK_ DRUMRF: ! DRUM READ FAILURES REJOIN HERE AMTDDDDX=STOREX ST_FLAGS=X'80'; ! DISC->STORE TRANSIT FLAGS=X'80'; ! DISC TRANSFER NEEDED %IF MULTIOCP=YES %START; *TDEC_(STORESEMA); %FINISH TDISC_DEST=X'210005'; ! DIRECT REPLIES TO LC TDISC_SRCE=X'80040099' TDISC_P1=AEX TDISC_P2=AMT_DA+EPX; ! DISC ADDRESS TDISC_P3=STOREX P_DEST=0 ->TRANSFER NEEDED !----------------------------------------------------------------------- ACTIVITY(6): ! FAILURE REPLY FROM DRUM/READ %IF SFCFITTED=YES %THENSTART ST==STORE(STOREX) BAD DRUM PAGE(DTX); ! DISCARD DRUM PAGE ->DRUMRF; ! AND FETCH FROM DISC %FINISH !----------------------------------------------------------------------- ACTIVITY(2): ! PAGE-OUT ST==STORE(STOREX) %IF ST_USERS=0 %OR AMT_USERS=0 %START OPMESS("? PAGEOUT ".STRHEX(AEX)) OPMESS("SRCE ".STRHEX(P_SRCE)) OPMESS("INFORM PDS") %IF MULTIOCP=YES %START; *TDEC_(STORESEMA); %FINISH %RETURN %FINISH AMT_USERS=AMT_USERS-1 ST_FLAGS=ST_FLAGS!P_P2; ! INSERT WRITTEN ETC. MARKERS ST_USERS=ST_USERS-1 %IF ST_USERS>0 %THENSTART SHAREDEPS=SHAREDEPS-1 %IF MULTIOCP=YES %START; *TDEC_(STORESEMA); %FINISH %RETURN %FINISH PAGEFREES=PAGEFREES+1; ! PAGE ABOUT TO BECOME FREE %IF ST_FLAGS&X'A0'#0 %THEN ->MUST WAIT ! PREVIOUS WRITEOUTS STILL GOING PAGEOUT: ! ACTUALLY PAGE IT OUT FLAGS=0; ! NO TRANSFER SET UP YET ! ! FIRST UPDATE DISC COPY IF PAGE HAS BEEN UPDATED. THEN CONSIDER ! WHETHER TO UPDATE OR GENERATE A DRUM COPY ! %IF ST_FLAGS&X'0A'=8 %THENSTART; ! \NEW&WRITTEN THEN WRITE TO DISC %IF MONLEVEL&4#0 %THEN PERFORM_PAGEOUTN=PERFORM_PAGEOUTN+1 ST_FLAGS=ST_FLAGS!X'C0'; ! DISC TRANSFER OUT BITS FLAGS=X'C0'; ! TRANSFER INITIATED AMT_OUTS=AMT_OUTS+1; ! AVOIDS AMT BEING DEALLOCATED TDISC_DEST=X'210006'; ! STORE->DISC TDISC_SRCE=X'80040005' TDISC_P1=AEX TDISC_P2=AMT_DA+EPX; ! DISC ADDR TDISC_P3=STOREX %FINISH %IF SFCFITTED=YES %THENSTART %IF ST_FLAGS&4=0 %START; ! NO DRUM UPDATE %IF DTX>=0 %THENSTART; ! RETURN DRUM PAGE(IF ANY) AMTDDDDX=STOREX DRUMT(DTX)=DRUMTASL DRUMTASL=DTX DRUMALLOC=DRUMALLOC-1 DTX=-1 %FINISH %FINISHELSESTART; ! DRUM UPDATE REQUIRED %IF DTX<0 %AND DRUMTASL#DTEND %START; ! NOT ON DRUM YET DTX=DRUMTASL; ! GET DRUM PAGE DRUMTASL=DRUMT(DRUMTASL) DRUMALLOC=DRUMALLOC+1 AMTDDDDX=DTXBIT!DTX DRUMT(DTX)=STOREX ST_FLAGS=ST_FLAGS!8; ! FORCE DRUM UPDATE %FINISH %FINISH %FINISH %IF SFCFITTED=YES %AND DTX>=0 %AND ST_FLAGS&8#0 %START ! UPDATE DRUM COPY ST_FLAGS=ST_FLAGS!X'30'; ! DRUM TRANSFER OUT BITS FLAGS=FLAGS!X'30'; ! TRANSFER INITIATED AMT_OUTS=AMT_OUTS+1; ! AVOIDS AMT SPACE GOING TDRUM_DEST=X'280002'; ! DRUM WRITE TDRUM_SRCE=X'80040007' TDRUM_P1=AEX TDRUM_P2=DTX TDRUM_P3=STOREX TDRUM_P4=ADDR(AMT_OUTS) %FINISH %IF FLAGS=0 %THENSTART; ! NO TRANSFERS INITIATED %IF ST_FLAGS&2#0 %THEN AMTDDDDX=NEWEPBIT!STXMASK %AND ST_FLAGS=0 ->REP; ! TO RETURN EPAGE %FINISH ST_FLAGS=ST_FLAGS&X'F1' %IF MULTIOCP=YES %START; *TDEC_(STORESEMA); %FINISH TRANSFER NEEDED: ! TO COMPLETE PAGETURN %IF FLAGS&X'80'#0 %THENSTART; ! DISC TRANSFER TO START %IF MONLEVEL&12=12 %THENSTART *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH PDISC(TDISC) %IF MONLEVEL&12=12 %THENSTART *LSS_(5); *IRSB_IT; *IMYD_1; *ST_ %TOS *IAD_(PDISCIT); *ST_(PDISCIT) *LSD_(PTIT); *ISB_ %TOS; *ST_(PTIT) *LSS_(6); *IRSB_IC; *IMYD_1; *ST_ %TOS *IAD_(PDISCIC); *ST_(PDISCIC) *LSD_(PTIC); *ISB_ %TOS; *ST_(PTIC) PDISCCALLN=PDISCCALLN+1 %FINISH %FINISH %IF SFCFITTED=YES %AND FLAGS&X'20'#0 %START; ! DRUM DIITO %IF MONLEVEL&12=12 %START *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH DRUM(TDRUM) %IF MONLEVEL&12=12 %THENSTART *LSS_(5); *IRSB_IT; *IMYD_1; *ST_ %TOS *IAD_(DRUMIT); *ST_(DRUMIT) *LSD_(PTIT); *ISB_ %TOS; *ST_(PTIT) *LSS_(6); *IRSB_IC; *IMYD_1; *ST_ %TOS *IAD_(DRUMIC); *ST_(DRUMIC) *LSD_(PTIC); *ISB_ %TOS; *ST_(PTIC) DRUMCALLN=DRUMCALLN+1 %FINISH %FINISH %RETURN !----------------------------------------------------------------------- ACTIVITY(4): ! ZERO "NEW" EPAGE ON DEACTIVATION %IF MONLEVEL&4#0 %THEN PERFORM_PAGEZN=PERFORM_PAGEZN+1 %IF MULTIOCP=YES %START; *TDEC_(STORESEMA); %FINISH FLAGS=X'80'; ! DISC WRITE INITIATED TDISC_DEST=X'210002'; ! WRITEOUT TDISC_SRCE=X'80040008'; ! REPLY TO ACT 8 TDISC_P1=AEX TDISC_P2=AMT_DA+EPX TDISC_P3=ZEROPAGEAD ->TRANSFER NEEDED !---------------------------------------------------------------------- ACTIVITY(5): ! REPLY FROM DISC/WRITE ST==STORE(STOREX) ! ! THERE ARE THREE POSSIBLE COURSES OF ACTION ON DISC FAILURE ! 1) FRIG THE USER COUNT SO IT STAYS IN CORE ! 2) TRY AGAIN (UNHELPFUL SINCE 42*8 TRIES ALREADY MADE) ! 3) DO NOTHING AND RELY ON NEXT READ FAILING ! FOR THE MOMENT FOLLOW COURSE 3 ! ST_FLAGS=ST_FLAGS&X'3F'; ! NO DISC TRANSFER %IF P_P2=4 %THENSTART; ! WAS ABORTED %IF MONLEVEL&4#0 %THEN PERFORM_ABORTN=PERFORM_ABORTN+1 ST_FLAGS=ST_FLAGS!8; ! PUT BACK WRITTEN MARKER %FINISH AMT_OUTS=AMT_OUTS-1 %IF ST_FLAGS&X'A0'#0 %OR ST_USERS#0 %THEN ->MUST WAIT %IF ST_FLAGS&X'E'#0 %THEN ->PAGEOUT REP: ! RETURN THE EPAGE ST_FLAGS=ST_FLAGS&1 %IF ST_FLAGS=0 %START; ! NOT RECAPTURABLE %IF SFCFITTED=NO %OR DTX<0 %THEN AMTDDDDX=AMTDDDDX!STXMASK %ELSE DRUMT(DTX)=STXMASK %FINISHELSESTART %IF SFCFITTED=NO %OR DTX<0 %THEN ST_LINK=DDX %ELSE ST_LINK=DDBIT!DTX %FINISH P_DEST=X'60001' P_P2=STOREX PAGEFREES=PAGEFREES-1 %IF MONLEVEL&12=12 %THENSTART *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH RETURN EPAGE(P) %IF MONLEVEL&12=12 %THENSTART *LSS_(5); *IRSB_IT; *IMYD_1; *ST_ %TOS *IAD_(RETIT); *ST_(RETIT) *LSD_(PTIT); *ISB_ %TOS; *ST_(PTIT) *LSS_(6); *IRSB_IC; *IMYD_1; *ST_ %TOS *IAD_(RETIC); *ST_(RETIC) *LSD_(PTIC); *ISB_ %TOS; *ST_(PTIC) RETCALLN=RETCALLN+1 %FINISH RAMTX: ! RETURN AMTX IF UNUSED %IF AMT_USERS=0 %AND AMT_OUTS=0 %THENSTART P_DEST=X'00080003' P_P2=AMTX %IF MULTIOCP=YES %THEN PON(P) %ELSESTART %IF MONLEVEL&12=12 %THENSTART *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH ACTIVE MEM(P) %IF MONLEVEL&12=12 %THENSTART *LSS_(5); *IRSB_IT; *IMYD_1; *ST_ %TOS *IAD_(AMIT); *ST_(AMIT) *LSD_(PTIT); *ISB_ %TOS; *ST_(PTIT) *LSS_(6); *IRSB_IC; *IMYD_1; *ST_ %TOS *IAD_(AMIC); *ST_(AMIC) *LSD_(PTIC); *ISB_ %TOS; *ST_(PTIC) AMCALLN=AMCALLN+1 %FINISH %FINISH %FINISH %IF MULTIOCP=YES %START; *TDEC_(STORESEMA); %FINISH %RETURN !----------------------------------------------------------------------- ACTIVITY(7): ! REPLY FROM DRUM/WRITE %IF SFCFITTED=YES %THENSTART ST==STORE(STOREX) %IF P_P2<0 %THENSTART; ! WRITE FAILURE AMTDDDDX=STOREX; ! RETURN DRUM PAGE BAD DRUM PAGE(DTX) DTX=-1 %FINISH ! ! NORMALLY DRUM AND DISC TRANSFERS ARE STARTED TOGETHER AND DRUM FINISHES ! FIRST. IN THESE CIRCUMSTANCES THE NEXT 2 LINES ARE DONE IN DRUM AND ! THERE IS NO REPLY. REPLIES COME IF DISC FININISHES FIRST OR DRUM ! TRANSFER FAILS OR THIS IS THE ONLY TRANSFER AS WHEN READONLY PAGE ! WRITTEN TO DRUM ON FIRST ACCESS ! 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 ->MUST WAIT %IF ST_FLAGS&X'E'#0 %THEN ->PAGEOUT; ! FURTHER UPDATES HAPPENED?? ->REP; ! RETURN EPAGE %FINISH !----------------------------------------------------------------------- ACTIVITY(8): ! REPLY FROM ZERO DISCPAGE ! IGNORE FAILURES SEE ACT 5 DCLEARS=DCLEARS-1 AMTDDDDX=AMTDDDDX&(\NEWEPBIT); ! CLEAR NEW MARKER AMT_OUTS=AMT_OUTS-1 ->RAMTX !---------------------------------------------------------------------- PUSHPIT: ! AWAIT TRANSFER USING THE PIT LIST I=NEWPPCELL PP==PARM(I) PP_DEST=SRCE PP_SRCE=X'40003' PP_P1=ID PP_P2=ST_REALAD&X'0FFFFFFF'; ! MAY BE FLAWED PP_P3=0; ! SUCCESS FLAG PP_P6=DTX; ! TELL IF DRUM OR DISC IN DUMP PP_LINK=ST_LINK ST_LINK=I *J_ %TOS %END !---------------------------------------------------------------------- %IF SFCFITTED=YES %THENSTART %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. RELEVANT SEMA IS ASSUMED CLAIMED! * !*********************************************************************** %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 %THENEXIT 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 %FINISH %INTEGERFN QUICK EPAGE(%INTEGER ZEROED,SMACMASK) !*********************************************************************** !* CAN BE CALLED BY ANYONE HOLDING STORESEMA TO GET THE NEXT FREE * !* NEXT FREE EPAGE. GIVES THE STORE INDEX OR -1 * !*********************************************************************** %RECORD (STOREF) %NAME ST %CONSTINTEGER CLEARTB=X'58000000'+1024*EPAGESIZE %INTEGER I,STAD,STOREX %IF FREE EPAGES=0 %THENRESULT=-1 STOREX=FSTASL ST==STORE(STOREX) %IF SSERIES=YES %OR RECONFIGURE=NO %OR SMACMASK=-1 %START FSTASL=STORE(FSTASL)_FLINK STORE(FSTASL)_BLINK=0 %FINISHELSESTART %CYCLE %IF 1<<(ST_REALAD>>22&15)&SMACMASK#0 %START %IF SMAC RCONFIG#0 %AND FSTASL#STOREX#BSTASL %START STORE(ST_FLINK)_BLINK=0 STORE(ST_BLINK)_FLINK=0 STORE(BSTASL)_FLINK=FSTASL STORE(FSTASL)_BLINK=BSTASL BSTASL=ST_BLINK FSTASL=ST_FLINK %FINISHELSESTART STORE(ST_FLINK)_BLINK=ST_BLINK STORE(ST_BLINK)_FLINK=ST_FLINK %FINISH %EXIT %FINISH STOREX=ST_FLINK %IF STOREX=0 %THENRESULT=-1 ST==STORE(STOREX) %REPEAT %FINISH ST_USERS=1 %IF ST_FLAGS=1 %THENSTART; ! RECAPTURABLE FLAG I=ST_LINK %IF SFC FITTED=NO %OR I&DDBIT=0 %THEN AMTDD(I)=AMTDD(I)!STXMASK %ELSE I=I&(\DDBIT) %AND DRUMT(I)=STXMASK ST_FLAGS=0 %FINISH %IF ZEROED=0 %THENSTART; ! CLEAR TO ZERO STAD=PUBSEG!(SEG64+ST_REALAD) *LDTB_CLEARTB *LDA_STAD *MVL_ %L = %DR,0,0 %FINISH FREEEPAGES=FREEEPAGES-1 %IF FREEEPAGES=0 %THEN INHIBIT(5) %RESULT=STOREX %END %ROUTINE GET EPAGE(%RECORD (PARMF) %NAME P) !*********************************************************************** !* CAN BE PONNED (BUT NOT CALLED!) TO PROVIDE AN EPAGE. * !* REPLIES HAVE STORE INDEX IN P_P2 AND VIRTADDR IN P_P4 * !*********************************************************************** %INTEGER STOREX,PS %IF MULTIOCP=YES %THENSTART *INCT_(STORESEMA) *JCC_8, SEMALOOP(STORESEMA,0) SEMACL: %FINISH %IF FREEEPAGES=0 %THENSTART; ! SHOULD ONLY OCCUR IN MULTIOCPS %IF MULTIOCP=YES %START; *TDEC_(STORESEMA); %FINISH PON(P); ! SERVICE NOW INHIBITED %RETURN %FINISH %IF MONLEVEL&2#0 %AND KMON&1<<5#0 %THEN PKMONREC("GET EPAGE:",P) STOREX=QUICK EPAGE(P_P2,-1) P_P2=STOREX; ! LEAVE P1 & P3 & P5 & P6 INTACT P_P4=(STORE(STOREX)_REALAD+SEG64)!PUBSEG P_DEST=P_SRCE P_SRCE=X'50000' PS=P_DEST %IF PS=X'40003' %THEN PS=P_P5 %IF LOCSN0>16<=LOCSN1 %THEN GETEPN=GETEPN-1 %IF MULTIOCP=YES %START; *TDEC_(STORESEMA); %FINISH PON(P) %END !----------------------------------------------------------------------- %INTEGERFN NEW EPAGE !*********************************************************************** !* HANDS OUT A NEW EPAGE TO EXTEND A VITAL RESIDENT TABLE * !*********************************************************************** %INTEGER I %IF MULTIOCP=YES %THENSTART *INCT_(STORESEMA) *JCC_7,; ! CAN NOT LOOP HERE %FINISH %IF FREE EPAGES>0 %THENSTART I=QUICK EPAGE(0,COM_SMACS>>16); ! ZEROED & IN SYSTEM SMAC %IF I<0 %THEN ->USE SPARE %IF MULTI OCP=YES %START; *TDEC_(STORESEMA); %FINISH STORE(I)_USERS=255 %RESULT=STORE(I)_REALAD&X'0FFFFFFF'; ! MAY BE FLAWED %FINISH USE SPARE: ! try emergency spare page %IF MULTIOCP=YES %START; *TDEC_(STORESEMA); %FINISH %IF SPSTOREX>0 %START I=STORE(SPSTOREX)_REALAD; ! CANNOT BE FLAWED(SEE RETURNEPAGE) SPSTOREX=0 %RESULT=I %FINISH %RESULT=-1 %END !----------------------------------------------------------------------- %ROUTINE RETURN EPAGE(%RECORD (PARMF) %NAME 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 * !*********************************************************************** %CONSTINTEGER CLEARTB=X'58000000'+1024*EPAGESIZE %RECORD (STOREF) %NAME ST %INTEGER I,STOREX,STAD,ACT ACT=P_DEST&1 %IF MULTIOCP=YES %AND ACT=0 %THENSTART *INCT_(STORESEMA) *JCC_8, SEMALOOP(STORESEMA,0) SEMACL: %FINISH %IF MONLEVEL&2#0 %AND KMON&1<<6#0 %THEN PKMONREC("RETURNEPAGE:",P) STOREX=P_P2 ST==STORE(STOREX) ST_USERS=0 ! IF PAGE IS IN SMAC BEING ! RECONFIGURED THEN DISCARD %IF RECONFIGURE=YES %AND 0#SMAC RCONFIG=ST_REALAD>>22&15 %START SMAC RPAGES=SMAC RPAGES-1 *JLK_ ->RETURN %FINISH %IF ST_REALAD<=0 %THENSTART %IF STOREX=0 %THEN MONITOR("PAGE 0 RETURNED???") OPMESS("PAGE ".STRINT(STOREX)." ABANDONED") *JLK_ ->RETURN %FINISH ! ! REPLENSISH THE SPARE PAGE FROM THE ALLOWED SYSTEM SMACE ONLY ! %IF SPSTOREX=0 %AND (SSERIES=YES %OR RECONFIGURE=NO %OR COM_SMACS&X'10000'<<(ST_REALAD>>22&15)#0) %START *JLK_ STAD=VIRTAD+ST_REALAD; ! CANNOT BE FLAWED *LDTB_CLEARTB *LDA_STAD *MVL_ %L = %DR,0,0 SPSTOREX=STOREX %FINISHELSESTART %IF ST_FLAGS&1#0 %START; ! RECAPTURABLE TO BACK ST_FLINK=0 ST_BLINK=BSTASL STORE(BSTASL)_FLINK=STOREX BSTASL=STOREX %FINISHELSESTART; ! NOT RECAPTURABLE ON FRONT ST_BLINK=0 ST_FLINK=FSTASL STORE(FSTASL)_BLINK=STOREX FSTASL=STOREX %FINISH %IF FREEEPAGES=0 %THEN UNINHIBIT(5) FREEEPAGES=FREEEPAGES+1 %FINISH RETURN: %IF MULTIOCP=YES %AND ACT=0 %START; *TDEC_(STORESEMA); %FINISH %RETURN STOP RECAPTURE: ! JLK SUBROUTINE TO BREAK LINK %IF ST_FLAGS=1 %THENSTART; ! RECAPTURABLE I=ST_LINK %IF SFC FITTED=NO %OR I&DDBIT=0 %THEN AMTDD(I)=AMTDD(I)!STXMASK %ELSE 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 (PARMF) P %INTEGER I,N,K %IF MULTIOCP=YES %THENSTART *INCT_(STORESEMA) *JCC_8, SEMALOOP(STORESEMA,0) SEMAGOT: %FINISH %UNLESS PAGEFREES<=1 %AND GETEPN>=MPLEVEL+1-COM_NOCPS %START %IF MULTIOCP=YES %START; *TDEC_(STORESEMA); %FINISH %RETURN; ! NOT A TRUE DEADLOCK %FINISH N=GETEPN GETEPN=GETEPN-1; ! ASSUMES WE WILL CURE DEADLOCK %IF MULTIOCP=YES %START; *TDEC_(STORESEMA); %FINISH %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 LOCSN0>16<=LOCSN1 %START ! 4-3=PAGEIN. P_P5 IS PT SRCE ! LC ACT 9 IS GET PAGE FOR PTS ! LC ACTF IS GET LOCKED PAGE 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 ") K=1+COM_SEPGS//100; ! 1% OF STORE %IF K>OVERALLOC %THEN K=OVERALLOC OVERALLOC=OVERALLOC-K UNALLOCEPS=UNALLOCEPS-K %RETURN %FINISH PON(P); ! NOT SUITABLE: RETURN TO QUEUE %REPEAT GETEPN=GETEPN+1 OPMESS("DEADLOCK UNRECOVERABLE") %END %ROUTINE OVERALLOC CONTROL !*********************************************************************** !* THIS ROUTINE IS KICKED PERIODICALLY TO TRY TO INCREASE THE STORE * !* OVERALLOCATION. EACH TIME THERE IS A DEADLOCK THE OVERALLOCATION * !* IS DECREASED. SYSTEM SHOULD SELF TUNE TO OCCAISIONAL DEADLOCKS * !* (1 EVERY 10-15MINS) WHICH IS OPTIMAL STORE USE. * !*********************************************************************** %INTEGER K K=1+COM_SEPGS//400; ! 0.25% OF STORE %IF OVERALLOC+K SEMALOOP(STORESEMA,0) ASEMAGOT: %FINISH DACT=P_DEST&X'F' ->ACT(DACT) !----------------------------------------------------------------------- ACT(0): ! INITIALISE %IF MULTIOCP=YES %START; *TDEC_(STORESEMA); %FINISH REALAD=NEW EPAGE LIM=MAXAMTAK-1 PST(AMTASEG)=X'4110038080000001'!LIM<<42!REALAD %IF MULTIOCP=YES %THEN PST(AMTASEG)=PST(AMTASEG)!NONSLAVED ! ! SET UP PUBLIC SEGMENT 'AMTASEG' FOR AMTA RECORD ARRAY WITH ! PAGE TABLE FOR IT AT BEGINNING OF FIRST EPAGE OF ITSELF ! AMTAPT==ARRAY((REALAD+SEG64)!PUBSEG,PTF) APPENDAMTA(EPAGESIZE<<10-MAXAMTAK<<2,REALAD) REALAD=NEW EPAGE LIM=MAXAMTDDK-1 ! ! PUBLIC SEGMENT 'AMTDDSEG' FOR AMTDD ARRAY WITH ! PAGE TABLE FOR IT AT BEGINNING OF FIRST EPAGE OF ITSELF ! PST(AMTDDSEG)=X'4110038080000001'!LIM<<42!REALAD %IF MULTIOCP=YES %THEN PST(AMTDDSEG)=PST(AMTDDSEG)!NONSLAVED AMTDDPT==ARRAY((REALAD+SEG64)!PUBSEG,PTF) APPENDAMTDD(EPAGESIZE<<10-MAXAMTDDK<<2,REALAD) %IF SFCFITTED=YES %THENSTART %IF DRUMSIZE=0 %THEN DRUMTASL=DTEND %ELSESTART %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 %IF MONLEVEL&1#0 %THENSTART DISPLAY TEXT(0,2,36,"DRMF") DISPLAY TEXT(0,3,36," 99%") %FINISH %FINISH %FINISH %RETURN !----------------------------------------------------------------------- ACT(1): ! GET AMTX DA=P_P2 LEN=P_P3&(MAXBLOCK-1)+1 MASK=P_P3; ! "NEW" EPAGE BIT MASK (TOP BITS) *LSS_DA; *IMDV_509; *LSS_ %TOS; *AND_511; *ST_HASH AMTX=AMTHASH(HASH) %WHILE AMTX#0 %CYCLE; ! SCAN DOWN LIST AMT==AMTA(AMTX) %IF AMT_DA=DA %THENSTART; ! THIS DA ALREADY IN TABLE %IF AMT_LEN#LEN %THENSTART %IF AMT_USERS#0 %THEN AMTX=-3 %AND ->RETURN %IF AMT_LENRETURN; ! EXTEND ? %CYCLE I=AMT_DDP+LEN,1,AMT_DDP+AMT_LEN-1 ! RETURN IF STILL IN USE %IF AMTDD(I)&STXMASK#STXMASK %THEN AMTX=0 %AND ->RETURN %REPEAT DEALLOCDD(AMT_DDP+LEN,AMT_LEN-LEN) AMT_LEN=LEN %FINISH %IF AMT_USERS=0 %AND AMT_OUTS>0 %START %CYCLE I=AMT_DDP,1,AMT_DDP+LEN-1 %IF AMTDD(I)&NEWEPBIT#0 %THEN AMTX=-4 %AND ->RETURN %REPEAT %FINISH AMT_USERS=AMT_USERS+1; ! USERS ->RETURN %FINISH AMTX=AMT_LINK %REPEAT %IF AMTASL=0 %THENSTART; ! 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 %CYCLE %IF DDASL(LEN)#0 %THENSTART DDX=DDASL(LEN) DDASL(LEN)=AMTDD(DDX) ->SETAMT %FINISH ! TAKE SPACE FROM A BIGGER HOLE I=LEN+1 %WHILE I<=MAXBLOCK %CYCLE DDX=DDASL(I) %IF DDX#0 %THENSTART 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 COLLECT DD GARBAGE ! TRY TO APPEND EPAGE TO AMTDD %IF FREEMAX<32 %AND AMTDDNEXT0 %THEN APPENDAMTDD(EPAGESIZE<<10,REALAD) %FINISH %REPEAT 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 %REPEAT RETURN: P_P1=ID P_P2=AMTX %IF MULTIOCP=YES %START; *TDEC_(STORESEMA); %FINISH %IF SRCE>0 %THEN P_DEST=SRCE %AND P_SRCE=X'80001' %AND PON(P) %RETURN !----------------------------------------------------------------------- ACT(2): ! RETURN AMTX IN P_P2 ! P_P3=0 FILE KEPT #0 DESTROY %BEGIN %INTEGERARRAY CLEARS(0:MAXBLOCK) AMTX=P_P2 AMT==AMTA(AMTX) %IF AMT_DA=X'FF000000' %OR AMT_DA=0 %THEN OPMESS("RETURNED AMT??") CN=0; ! NO CLEARS AS YET %IF P_P3=0 %THENSTART; ! FILE BEING KEPT %CYCLE I=AMT_DDP,1,AMT_DDP+AMT_LEN-1; ! CHECK "NEW" EPAGE BIT ! "NEW" SECTIONS NEVER SHARED %IF AMTDD(I)&NEWEPBIT#0 %THENSTART CLEARS(CN)=AMTX<<16!(I-AMT_DDP) CN=CN+1 AMT_OUTS=AMT_OUTS+1 %FINISH %REPEAT %FINISH AMT_USERS=AMT_USERS-1 ! ! NOW IF THERE WERE ANY CLEARS SET THEM OFF. THIS IS DONE LATER ! SO THAT THE STORE SEMA CAN BE FREE ON DUALS. IMPORTANT AS IT MAY ! BE NECESSARY TO EXTEND THE PARM ASL IF VERY LARGE NO OF CLEARS ! ARE REQUIRED ! P_P6=CN; ! SO L-C CAN ACCOUNT FOR CLEARS %IF CN>0 %START DCLEARS=DCLEARS+CN %IF MULTIOCP=YES %START; *TDEC_(STORESEMA); %FINISH Q_DEST=X'40004'; ! ZERO PAGE Q_SRCE=X'80080002' %CYCLE I=0,1,CN-1 Q_P1=CLEARS(I) PON(Q); ! PON to limit call depth & so %REPEAT; ! avoid possible LC stack o'flow %FINISH %END %IF CN>0 %THENRETURN; ! SEMA ALREADY RELEASED ! IF THERE WERE NO CLEARS THEN ! DROP THROUGH INTO ACT 3 !----------------------------------------------------------------------- ACT(3): ! RETURN AMTX AFTER TRANFERS END AMTX=P_P2 AMT==AMTA(AMTX) %UNLESS AMT_USERS=AMT_OUTS=0 %AND AMT_DA#X'FF000000' %START %IF MULTIOCP=YES %START; *TDEC_(STORESEMA); %FINISH %RETURN; ! AWAIT TRANSFERS %FINISH DEALLOCDD(AMT_DDP,AMT_LEN) DEALLOCAMT %IF MULTIOCP=YES %START; *TDEC_(STORESEMA); %FINISH %RETURN !----------------------------------------------------------------------- ACT(4): ! ENTERED EVERY 10 SECS %IF MULTIOCP=YES %START; *TDEC_(STORESEMA); %FINISH %IF SFCFITTED=YES %AND DRUMSIZE#0 %THEN I=100*DRUMALLOC//DRUMSIZE %ELSE I=0 %IF SFCFITTED=YES %AND MONLEVEL&1#0 %AND DRUMSIZE#0 %THEN DISPLAY TEXT(0,3,37,STRINT(100-I)."% ") RESIDENCES=MINRESIDENCES+(99-I)//2 RESIDENCES=MAXRESIDENCES %IF RESIDENCES>MAXRESIDENCES ! ! EXAMINE PROCESS LIST EVERY 10 SECS. ALL PROCESSES THAT HAVE ! BEEN INACTIVE FOR MORE THAN 2 MINS ARE TOLD TO DEACTIVATE ! THEIR ACTIVE MEMORY FREEING DRUM & TABLESPACE ! P_SRCE=X'80000' K=(RESIDENCES-MINRESIDENCES+2)>>1; ! HOW LONG CAN HE HANG ON TO DRUM ! MAX 7 MIN 1 IN 20 SEC TICKS I=1; J=0 %UNTIL J=COM_USERS %OR I>MAXPROCS %CYCLE PROC==PROCA(I) %IF PROC_USER#"" %THENSTART %IF PROC_STATUS&AMTLOST=0 %AND K=MAXBLOCK %THENSTART AMTDD(FROM)=DDASL(MAXBLOCK) DDASL(MAXBLOCK)=FROM FREEMAX=FREEMAX+1 FROM=FROM+MAXBLOCK %FINISHELSESTART %IF FROM<=TO %THEN AMTDD(FROM)=DDASL(LEN) %AND DDASL(LEN)=FROM %RETURN %FINISH %REPEAT %END !----------------------------------------------------------------------- %ROUTINE DEALLOCAMT !*********************************************************************** !* DEALLOCATE AMT ENTRY AND RETURN TO FREE LIST. RESETTING THE HASH * !* CHAIN IS THE ONLY PROBLEM * !*********************************************************************** %INTEGER HASH,DA %RECORD (AMTF) %NAME AMT %HALFINTEGERNAME PTR AMT==AMTA(AMTX) DA=AMT_DA AMT_DA=X'FF000000' *LSS_DA; *IMDV_509; *LSS_ %TOS; *AND_511; *ST_HASH PTR==AMTHASH(HASH) PTR==AMTA(PTR)_LINK %WHILE PTR#AMTX PTR=AMT_LINK; ! RESET CHAIN OMITTING THIS ENTRY AMT_LINK=AMTASL; ! RETURN CELL AMTASL=AMTX %END !----------------------------------------------------------------------- %ROUTINE DEALLOCDD(%INTEGER DDX,LEN) !*********************************************************************** !* DEALLOCATE A SECTION OF AMTDD. DIFFICULT IN DUALS AS STORE * !* SEMA IS NEEDED TO CLEAR BACKLINKS * !*********************************************************************** %INTEGER I,J,DTX %CYCLE I=DDX,1,DDX+LEN-1 %IF SFCFITTED=YES %AND AMTDD(I)&DTXBIT#0 %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 %FINISHELSESTART 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 !----------------------------------------------------------------------- %IF MONLEVEL&X'3C'#0 %THENSTART %EXTRINSICLONGINTEGER SEMATIME %ROUTINE TIMEOUT !*********************************************************************** !* PRINT OUT THE SESSION TIMING MEASUREMENTS * !*********************************************************************** %CONSTSTRING (15) %ARRAY SERVROUT(0:LOCSN0+3)="IDLE TIME", "NOWORK TIME","DEADLOCK RCVRY","SCHEDULE", "PAGETURN","GET EPAGE","RETURN EPAGE","FILE SEMAPHORE","ACTIVE MEM", "","ELAPSEDINT","UPDATE TIME","DPONPUTONQ","TURNON ER", "ACTIVEMEM(POLL)","SCHEDULE(OPER)","OVERALLOC CNTRL",""(14), "DAP DRIVER", "DISC","DISC TRANSFERS","DISC INTERRUPT","","MOVE REQUESTS", "MOVE TRANSFERS",""(2), "DRUM TRANSFERS","CSU","DRUM INTERRUPT",""(5),"GPC REQUESTS","TAPE", "OPER","LP ADAPTOR","CR ADAPTOR","CP ADAPTOR","PRINTER", "COMMS CONTROL","COMBINE","FEP ADAPTOR","GPC INTERRUPT", ""(2),"BMREP","COMREP",""(2),"LOCAL CONTROL","FOREGRND USERS", "BACKGRND USERS" %INTEGER I,J,K %LONGREAL PERIOD,TOTAL,IDLETIME,PROCTIME,SERVTIME %STRING (15) S %STRING (31) %FNSPEC STRPRINT(%LONGREAL X, %INTEGER A,B) %IF MULTIOCP=YES %THEN RESERVE LOG %IF MONLEVEL&4#0 %THENSTART PERIOD=CLOCK-PERFORM_CLOCK0 I=ADDR(COM_DATE0)+3 NEWPAGE PRINT STRING(" EMAS2900 SUP".SUPID." TIMING MEASUREMENTS ".STRING(I)." ".STRING(I+12)." PERIOD=".STRPRINT(PERIOD/1000000,1,3)." SECS") %IF MULTIOCP=YES %THEN PERIOD=PERIOD*COM_NOCPS PERFORM_SERVIC(0)=IDLEN PERFORM_SERVIC(1)=NOWORKN IDLETIME=COM_ITINT*(IDLEIT+NOWORKIT) PROCTIME=COM_ITINT*(FLPIT+BLPIT) PRINT STRING(" SERVICE CALLS TIME AVERAGE % OF "."% OF % OF INSTRNS AVERAGE (SECS) (MSECS) TOTAL "."NON-IDLE SUPVSR ") TOTAL=0 %CYCLE I=0,1,LOCSN0+3 S=SERVROUT(I) J=PERFORM_SERVN(I) %IF S#"" %AND J>0 %THENSTART PRINT STRING(" ".S.STRSP(16-LENGTH(S)).STRPRINT(J,9,0)) SERVTIME=COM_ITINT*PERFORM_SERVIT(I) PRINT STRING(STRPRINT(SERVTIME/1000000,6,3).STRPRINT((SERVTIME/1000)/J,6, 3).STRPRINT(100*SERVTIME/PERIOD,7,1)."%".STRPRINT(100*SERVTIME/(PERIOD-IDLETIME),6, 1)."%".STRPRINT(100*SERVTIME/(PERIOD-IDLETIME-PROCTIME),6,1)."%".STRPRINT(PERFORM_SERVIC(I),11, 0).STRPRINT(PERFORM_SERVIC(I)/J,8,0)." ") TOTAL=TOTAL+SERVTIME %FINISH %REPEAT PRINT STRING(" INTERRUPT/ACTIVATE ETC.=".STRPRINT((PERIOD-TOTAL)/1000000,1,3)." SECS (".STRPRINT(100*(PERIOD-TOTAL)/PERIOD,1,1)."%) SEMALOCKOUT=".STRPRINT(SEMATIME/1000000,1,3)."SECS(".STRPRINT(100*SEMATIME/PERIOD,1,1)."%) ") %IF SFC FITTED=YES %THEN PRINTSTRING("DRUMSIZE=".STRINT(DRUMSIZE)) PRINTSTRING(" OVERALLOC=".STRINT(OVERALLOC)." PAGEINS=".STRINT(PERFORM_PTURNN)." RECAPTURES=".STRINT(PERFORM_RECAPN)." SHARED PAGES=".STRINT(PERFORM_PSHAREN)." NEW PAGES=".STRINT(PERFORM_NEWPAGEN)." WRITEOUTS=".STRINT(PERFORM_PAGEOUTN)." PAGES ZEROED=".STRINT(PERFORM_PAGEZN)." PAGES SNOOZED=".STRINT(PERFORM_SNOOZN)." PAGES ABORTED=".STRINT(PERFORM_ABORTN)) PRINTSTRING(" SNOOZES COMPLETE =".STRINT(PERFORM_SNOOZOK)." SNOOZES TIMEDOUT =".STRINT(PERFORM_SNOOZTO)." SNOOZES ABANDONED=".STRINT(PERFORM_SNOOZAB)." SOFTWARE INWARD CALLS=".STRINT(INTEGER(X'800000E0'))." ") %FINISH %IF MONLEVEL&32#0 %THENSTART NEWPAGE PRINTSTRING(" CATEGORY TABLE TRANSITIONS ") SPACES(3) %CYCLE I=1,1,MAXCAT WRITE(I,5) %REPEAT NEWLINE %CYCLE I=1,1,MAXCAT WRITE(I,2) %CYCLE J=1,1,MAXCAT K=CATREC(I,J) WRITE(K,5) %REPEAT NEWLINE SPACES(3) %CYCLE J=1,1,MAXCAT K=FLYCAT(I,J) %IF K#0 %THEN WRITE(K,5) %ELSE SPACES(6) %REPEAT NEWLINE %REPEAT %FINISH %IF MONLEVEL&16#0 %THENSTART PRINTSTRING(" CAT SEQOUT STROBES EPSEXAMINED EPSOUT ") %CYCLE I=1,1,MAXCAT %IF STROBEN(I)#0 %START WRITE(I,2) WRITE(SEQOUT(I),7) WRITE(STROBEN(I),7) WRITE(STREPN(I),11) WRITE(STROUT(I),6) %IF STROUT(I)#0 %THEN WRITE(STREPN(I)//STROUT(I),6) NEWLINE %FINISH %REPEAT %FINISH NEWPAGE PPROFILE %IF MULTIOCP=YES %THEN RELEASE LOG CLEAR TIME %RETURN %STRING (31) %FN STRPRINT(%LONGREAL X, %INTEGER N,M) !*********************************************************************** !* PRINTS A REAL NUMBER (X) ALLOWING N PLACES BEFORE THE DECIMAL * !* POINT AND M PLACES AFTER.IT REQUIRES (M+N+2) PRINT PLACES * !* UNLESS (M=0) WHEN (N+1) PLACES ARE REQUIRED. * !* * !* A LITTLE CARE IS NEEDED TO AVOID UNNECESSARY LOSS OF ACCURACY * !* AND TO AVOID OVERFLOW WHEN DEALING WITH VERY LARGE NUMBERS * !*********************************************************************** %LONGREAL ROUND,Y,Z %STRING (127) S %INTEGER I,J,L,SIGN,SPTR SIGN=' '; ! '+' IMPLIED %IF X<0 %THEN SIGN='-' Y=MOD(X); ! ALL WORK DONE WITH Y ROUND=0.5/10.0**M; ! ROUNDING FACTOR Y=Y+ROUND I=0; Z=1 %UNTIL Z>Y %CYCLE; ! COUNT LEADING PLACES I=I+1; Z=10*Z; ! NO DANGER OF OVERFLOW HERE %REPEAT SPTR=1 %WHILE SPTR<=N-I %CYCLE CHARNO(S,SPTR)=' ' SPTR=SPTR+1 %REPEAT CHARNO(S,SPTR)=SIGN SPTR=SPTR+1 J=I-1; Z=10.0**J %CYCLE %UNTIL J<0 %CYCLE L=INT PT(Y/Z); ! OBTAIN NEXT DIGIT Y=Y-L*Z; Z=Z/10; ! AND REDUCE TOTAL CHARNO(S,SPTR)=L+'0' SPTR=SPTR+1 J=J-1 %REPEAT %IF M=0 %THENEXIT; ! NO DECIMAL PART TO BE O/P CHARNO(S,SPTR)='.' SPTR=SPTR+1 J=M-1; Z=10.0**(J-1) M=0 Y=10*Y*Z %REPEAT LENGTH(S)=SPTR-1 %RESULT=S %END %END !----------------------------------------------------------------------- %ROUTINE CLEAR TIME !*********************************************************************** !* CLEAR OUT THE TIMING MEASUREMENTS * !*********************************************************************** %INTEGER I,J %IF MONLEVEL&4#0 %THENSTART %CYCLE I=0,1,LOCSN0+3 PERFORM_SERVIT(I)=0 PERFORM_SERVIC(I)=0 PERFORM_SERVN(I)=0 %REPEAT PERFORM_RECAPN=0 PERFORM_PTURNN=0 PERFORM_PSHAREN=0 PERFORM_NEWPAGEN=0 PERFORM_PAGEOUTN=0 PERFORM_PAGEZN=0 PERFORM_SNOOZN=0 PERFORM_ABORTN=0 PERFORM_SNOOZOK=0 PERFORM_SNOOZTO=0 PERFORM_SNOOZAB=0 SEMATIME=0 PERFORM_CLOCK0=CLOCK %FINISH %IF MONLEVEL&32#0 %THENSTART %CYCLE I=0,1,MAXCAT %CYCLE J=0,1,MAXCAT FLYCAT(I,J)=0; CATREC(I,J)=0 %REPEAT %REPEAT %FINISH %IF MONLEVEL&16#0 %THENSTART %CYCLE I=0,1,MAXCAT STROBEN(I)=0 STREPN(I)=0 STROUT(I)=0 SEQOUT(I)=0 %REPEAT %FINISH %END %FINISH !----------------------------------------------------------------------- %IF DAP FITTED=YES %THENSTART %ROUTINE DAP DRIVER(%RECORD (PARMF) %NAME P) !*********************************************************************** !* THIS ROUTINE(SERVICE 31 X1F) HANDLES THE DAP * !* ACT=0 INITIALISE * !* ACT=1 ALLOCATE (SOME OF) THE DAP * !* ACT=2 DEALLOCTE (SOME OF) THE DAP * !* ACT=3 DAP INTERRUPT * !* ACT=4 START THE DAP * !* ACT=5 STOP THE DAP * !* ACT=6 CLOSE DOWN THE DAP FOR RECONFIGN * !* ACT=7 CLOCK TICK TO RETURN IDLE DAP TO STORE * !* ACT=8 SET TIMEOUT TO P_P1 * !* ACT=9 FROM LOCAL CNTRLR WHEN PROCESS DIES WITH DAP * !* ACT=10 RETURN PROCESS LIST NOS OF DAP USERS * !*********************************************************************** %ROUTINESPEC DREPLY(%INTEGER LDAPNO,FAIL) %ROUTINESPEC DSTATUS %INTEGER I,J,DACT,PROCNO,FAIL,PT0,PT1,LDAPNO,INIT,STEP,FINAL %INTEGER STATUS,STATUS2,STATUS3,ADVIOL,IT,IC,ILOG1,ILOG2,DLOG1,DLOG2,DPC %RECORD (PROCF) %NAME PROC %RECORD (CDRF) %NAME LDAP %RECORD (PARMXF) %NAME PCELL %INTEGERNAME LINK %OWNINTEGER TOUT=180; ! AFTER 3 MINS REVERTS TO STORE %OWNINTEGER HWTOUT=60; ! AFTER 60 SECS INT IS CLASSED AS MISSING %STRING (5) DAPID %CONSTINTEGER MAXDACT=12 %CONSTINTEGER SWOP DAP=X'80' %SWITCH ACT(0:MAXDACT) %OWNINTEGER CLOSING=0,PENDING=0,RESTART BITS=0 DACT=P_DEST&15 LDAPNO=P_DEST>>8&15 %IF 1<=LDAPNO<=MAXLDAP %THEN LDAP==COM_CDR(LDAPNO) %IF 1<MAXLDAP) %THEN ->REQERR %IF MONLEVEL&2#0 %AND KMON>>31&1#0 %THEN PKMONREC("DAP DRIVER:",P) PROCNO=(P_SRCE>>16-LOCSN0)&(MAXPROCS-1) PROC==PROCA(PROCNO) %IF 0<=DACT<=MAXDACT %THEN ->ACT(DACT) REQERR: ! ERROR IN REQUEST OPMESS("INVALID DAP REQUEST") PKMONREC("DAP ERR:",P) DSTATUS %RETURN ACT(0): ! INITIALISE(NO PARAMS) *LSS_(3); *USH_-26 *AND_3; *ST_I %IF I#COM_OCP PORT 0 %THEN DPON(P,1) %ANDRETURN CLOSING=CLOSING&(\(1<>J; ! INT PORT MASK BIT %IF BASIC PTYPE<=3 %START; ! DAP ON 2970 *LSS_(X'600A') *SLSS_J; *NEQ_-1; *AND_ %TOS *ST_(X'600A') %FINISHELSESTART; ! DAP ON P4 *LSS_(X'4012') *OR_J *ST_(X'4012') %FINISH J=LDAP_DAP1+5 *LB_J; *LSS_10; *ST_(0+ %B ); ! DIAG ALLOW AND STOP DAP *ADB_X'EA'; *LSS_2; *ST_(0+ %B ); ! CLEAR FAILS AND GEN RES DSTATUS %IF PENDING=0 ->DSCHED ACT(1): ! ALLOCATE P_P1 BLOCKS OF DAP ! ! REPLIES ARE P_P1=1 NO DAP AVAILABLE ! P_P1=2 NOT ENOUGH CONTIGUOUS BLOCKS ! P_P1=3 DAP IS CLOSING DOWN ! P_P1=4 USER ALREADY HAS DAP ! P_P1=0 DAP ALLOCATED WHEREUPON: ! P_P2=LDAP<<16!PHYSICAL DAP NO ! P_P3=FIRST BLOCK ALLOCATED ! P_P4=NO OF BLOCKS ALLOCATED ! INIT=1; STEP=1; FINAL=MAXLDAP %IF 2<=COM_CDR(1)_DAPSTATE<=3 %THENSTART STEP=-1; INIT=MAXLDAP; FINAL=1 %FINISH %CYCLE LDAPNO=INIT,STEP,FINAL; ! TRY FROM ALL DAPS ! TESTING BUSY ONES LAST LDAP==COM_CDR(LDAPNO) FAIL=0 %IF LDAP_IPDAPNO=0 %OR LDAP_DAPSTATE=0 %THEN FAIL=1 %IF P_P1<=0 %OR P_P1>LDAP_DAPBLKS %THEN FAIL=2 %IF CLOSING&1<15 %START; ! DAP AS STORE GET IT BACK P_DEST=X'110001' P_SRCE=X'1F0001' P_P1=4<<16!LDAP_IPDAPNO&15 PON(P) %RETURN %FINISH DSCHED: ! TRY TO SCHEDULE ALL DAPS %FOR LDAPNO=1,1,MAXLDAP %CYCLE LDAP==COM_CDR(LDAPNO) %CONTINUEUNLESS LDAP_DAPSTATE=1; ! DAP AVAILABLE TO BE SCHEDULED LINK==PENDING %WHILE LINK>0 %CYCLE; ! DAP JOBS ON QUEUE I=LINK P<-PARM(I) %IF P_P1>LDAP_DAPBLKS %THEN LINK==PARM(I)_LINK %ANDCONTINUE PROCNO=(P_SRCE>>16-LOCSN0)&(MAXPROCS-1) PROC==PROCA(PROCNO) LINK=PARM(I)_LINK RETURN PP CELL(I) %IF PROC_USER#STRING(ADDR(P_P5)) %THENCONTINUE; ! CLAIMER HAS GONE AWAY LDAP_DAPSTATE=2 %EXIT %REPEAT %IF LDAP_DAPSTATE=2 %START; ! DAP SCHEDULED UPDISP(PROCNO,10,TOSTRING((LDAP_IPDAPNO>>4)*2+52)); !< OR > PROC_STATUS=PROC_STATUS!2****10 LDAP_DAPUSER=PROCNO P_P4=P_P1 P_P2=LDAP_IPDAPNO&15!LDAPNO<<16 P_P3=0 DREPLY(LDAPNO,0) %FINISH %IF LDAP_DAPSTATE=1 %START; ! DAP IS IDLE P_DEST=X'000A0002' P_P1=X'1F0007'!LDAPNO<<8 P_P2=TOUT P_SRCE=X'1F0001' PON(P); ! TIMEOUT BACK TO STORE %FINISH %REPEAT; ! FOR ALL DAPS %RETURN ACT(2): ! DEALLOCATE P_P3 BLKS OF DAP %UNLESS P_P1&X'FFFF'=LDAP_IPDAPNO&15 %AND LDAP_DAPUSER=PROCNO %THEN DREPLY(LDAPNO,1) %ANDRETURN DREPLY(LDAPNO,0) RESET: ! ENTER AFTER PROC FAILS(ACT10) UPDISP(PROCNO,10," ") LDAP_DAPUSER=0 LDAP_DAPSTATE=1 PROC_STATUS=PROC_STATUS&(\(2****10)) J=LDAP_DAP1+X'EF'; ! gen res DAP in case *LB_J; *LSS_2; *ST_(0+ %B ); ! ended in disorder %IF CLOSING&(1<DSCHED ACT(11): ! FORM ELAPSED INT: INT LONG OVERDUE %IF LDAP_DAPSTATE=3 %START; ! DAP IS RUNNING DAPID="DAP".TOSTRING(LDAP_IPDAPNO>>4+48) OPMESS(DAPID." TIMES OUT".TOSTRING(17)) P_DEST=LDAP_DAPINT P_SRCE=X'1F000B' PON(P) LDAP_DAPINT=0 LDAP_DAPSTATE=2 J=LDAP_DAP1+5 *LB_J; *LSS_10; *ST_(0+ %B ); ! STOP DAP AND DIAG ALLOW *ADB_X'EA'; *LSS_2; *ST_(0+ %B ); ! AND GEN RES IT %FINISHELSE OPMESS("SPURIOUS DAP TIMEOUT") %RETURN ACT(3): ! DAP INTERRUPT ! P_P3 HAS INT STAT %IF LDAP_DAPSTATE=3 %START; ! DAP IS RUNNING %IF CLOSING&(1<SET TOUT %FINISH J=LDAP_DAP1+9 *LB_J; *LSS_(0+ %B ); *ST_STATUS *ADB_2; *LSS_(0+ %B ); *ST_ADVIOL *ADB_X'2E'; *LSS_(0+ %B ); *ST_IC *ADB_2; *LSS_(0+ %B ); *ST_IT *ADB_2; *LSS_(0+ %B ); *ST_DPC *ADB_2; *LSS_(0+ %B ); *ST_DLOG1 *ADB_2; *LSS_(0+ %B ); *ST_DLOG2 *ADB_2; *LSS_(0+ %B ); *ST_ILOG1 *ADB_2; *LSS_(0+ %B ); *ST_ILOG2 *ADB_8; *LSS_(0+ %B ); *ST_STATUS3 *ADB_2; *LSS_(0+ %B ); *ST_STATUS2 %IF P_P3&8#0 %START; ! HARDWARE DAPID="DAP".TOSTRING(LDAP_IPDAPNO>>4+48)." " OPMESS(DAPID."H-W ERROR".TOSTRING(17)) PRINTSTRING(DAPID."H-W FAILURE INSTAT=".STRHEX(P_P3)) PRINTSTRING(" STATUS =".STRHEX(STATUS)) NEWLINE %FOR I=x'10',2,x'ee' %CYCLE %CONTINUEIF x'60'<=I<=x'7f' J=LDAP_DAP1+I %IF SAFEISREAD(J,PT0)!SAFEISREAD(J+1,PT1)=0 %AND PT0!PT1#0 %START PRINTSTRING(STRHEX(J)." ".STRHEX(PT0).STRHEX(PT1)) NEWLINE %FINISH %REPEAT %FINISH %IF ILOG1=X'F7F00000' %AND 1<SET TOUT %FINISH P_DEST=LDAP_DAPINT; P_SRCE=X'1F0003' LDAP_DAPINT=0 P_P1=P_P3<<24!ADVIOL&X'00FFFF00'!STATUS %IF PENDING#0 %THEN P_P1=P_P1!SWOP DAP P_P2=DPC P_P3=DLOG1<<15!DLOG2&X'7FFF'; P_P4=IC P_P5=ILOG1 P_P6=ILOG2 PON(P) %IF MONLEVEL&2#0 %AND KMON>>31&1#0 %THEN PKMONREC("DAP INT :",P) LDAP_DAPSTATE=2 P_DEST=X'A0001' P_SRCE=X'1F0003' P_P1=X'1F000B'!LDAPNO<<8 P_P2=-1; ! CANCELL ELAPSED INT REQUEST PON(P); ! REMOVE TIMEOUT ON INT %FINISHELSESTART OPMESS("SURPRISE DAP INTERRUPT") PKMONREC("SPUR DAPINT:",P) %FINISH %RETURN ACT(4): ! START THE DAP ! P_P1=DATUM,P_P2=LIMIT ! P_P3=COB(ASE),P_P4=COL(IMIT) ! P_P5=DAPPC,P_P6=DAPIC DREPLY(LDAPNO,1) %ANDRETURNUNLESS PROCNO=LDAP_DAPUSER %AND LDAP_DAPSTATE=2 DREPLY(LDAPNO,2) %ANDRETURNIF CLOSING&(1<0 %CYCLE PCELL==PARM(LINK) %IF PROCNO=(PCELL_SRCE>>16-LOCSN0)&(MAXPROCS-1) %START; ! FOUND RIGHT USER PCELL_DEST=PCELL_SRCE PCELL_SRCE=X'1F0005' PCELL_P1=-1 J=LINK; LINK=PCELL_LINK FASTPON(J) %RETURN %FINISH LINK==PCELL_LINK %REPEAT %RETURN; ! ALREADY STOPPED ACT(6): ! CLOSE THE DAP CLOSING=CLOSING!1<DSCHED; ! SET FURTHER TIMEOUT IN CASE ! NO OF USERS INCREASES ACT(8): ! SET TIMEOUT HWTOUT=P_P2 %IF P_P2>10 TOUT=P_P1 %IF P_P1>1 %RETURN ACT(9): ! PROCESS DIES WITH DAP ! ALLOW RESET BY HAIRY PON %FOR LDAPNO=1,1,MAXLDAP %CYCLE LDAP==COM_CDR(LDAPNO) %IF PROCNO=LDAP_DAPUSER %THEN ->RESET %REPEAT %RETURN ACT(10): ! RETURN CURRENT DAP USER LIST FAIL=0 %FOR I=1,1,MAXLDAP %CYCLE LDAP==COM_CDR(I) %IF LDAP_DAPUSER>0 %THEN BYTEINTEGER(ADDR(P_P2)+FAIL)=LDAP_DAPUSER %AND FAIL=FAIL+1 %REPEAT LINK==PENDING %WHILE LINK>0 %CYCLE PCELL==PARM(LINK) BYTEINTEGER(ADDR(P_P2)+FAIL)=PCELL_P4 FAIL=FAIL+1 LINK==PCELL_LINK %REPEAT DREPLY(0,FAIL) %RETURN ACT(12): ! FROM DIR ASYNCH IO COMPLETE %IF LDAP_DAPSTATE=3 %THEN RESTART BITS=RESTART BITS!(1<0 %START; ! IF REPLY WANTED P_P1=FAIL P_P6=PROC_STATUS *LSS_(3); *ST_I P_P5=I P_DEST=P_SRCE P_SRCE=X'1F0000'!DACT!LDAPNO<<8 PON(P) %IF MONLEVEL&2#0 %AND KMON>>31&1#0 %THEN PKMONREC("DAP REPLY :",P) %FINISH %END %ROUTINE DSTATUS %INTEGER I %STRING (40) S %FOR I=1,1,MAXLDAP %CYCLE LDAP==COM_CDR(I) S="LDAP".STRINT(I) %IF LDAP_IPDAPNO=0 %THEN S=S." NONE" %ELSE %C S=S." DAC".STRINT(LDAP_IPDAPNO&15)." BLKS ".STRINT(LDAP_DAPBLKS)." USER".STRINT(LDAP_DAPUSER). %C " STATE".STRINT(LDAP_DAPSTATE) OPMESS(S) %REPEAT %END %END %FINISH %IF MULTIOCP=YES %THENSTART %INTEGERFN REMOTE ACTIVATE(%INTEGER REMOTE PORT,ADDR) !*********************************************************************** !* ACTIVATES A REMOTE OCP. ITS SSN+1 IS AT ADDR * !*********************************************************************** %INTEGER I,ISAD,STKAD,VAL,RES %RECORD (ISTF) %NAME SSNP1 STKAD=ADDR&X'FFF80000'; ! REMOVE ODD BIT FROM SEGNO SSNP1==RECORD(ADDR) SSNP1=GSSNP1; ! COPY IN CONTEXT SSNP1_LNB=SSNP1_LNB&X'3FFFF'!STKAD SSNP1_SF=SSNP1_SF&X'3FFFF'!STKAD %CYCLE I=0,4,60 INTEGER(X'81000080'+I)=INTEGER(ADDR+I) %REPEAT; ! COPY SSN+1 TO REAL ADRR 80 %IF SSERIES=YES %START %IF REMOTE PORT=COM_OCPPORT1 %THEN REMOTE PORT=COM_OCP1 SCU PORT %ELSE REMOTE PORT=COM_OCP0 SCU PORT ISAD=X'40000000'!REMOTE PORT<<22 %FINISHELSE ISAD=X'42000000'!REMOTE PORT<<20 %IF SSERIES=YES %OR BASIC PTYPE<=3 %START; ! P2&P3 ISAD=ISAD!X'6014' VAL=X'80' %FINISHELSESTART; ! P4 PROCESSORS ISAD=ISAD+2 VAL=X'40000000' %FINISH RES=SAFE IS WRITE(ISAD,VAL) %CYCLE I=1,1,10000; %REPEAT %CYCLE I=0,4,60 INTEGER(X'81000080'+I)=INTEGER(X'801C0000'+I) %REPEAT; ! RESTORE RESTART REGS %RESULT=RES %END %FINISH %ROUTINE CONFIG CONTROL(%RECORD (PARMF) %NAME P) !*********************************************************************** !* KERNEL SERVICE 17 DYNAMIC CONFIGURATION CHANGING * !* CONFIGURE OFF(DACT=0) OR ON(DACT=1) A MAJOR UNIT * !* P_P1=DEVICE<<16! IDENT NO * !* WHERE DEV=1 FOR OCP * !* DEV=2 FOR SAC * !* DEV=3 FOR SMAC * !* DEV=4 FOR DAP * !* OTHER DACTS DESCRIBED IN COMMENTS * !*********************************************************************** %IF RECONFIGURE=YES %OR DAP FITTED=YES %THENSTART %INTEGERFNSPEC SMAC PORT(%INTEGER OPEN,PORT) %INTEGERFNSPEC MAPDAP %SWITCH DACT(0:7),CIN,COFF(1:4) %INTEGER DEV,IDENT,I,J,K,MYPORT,HISPORT,STACK,ACT,TOPST,BLKSIZE,CONFIG,BLKS,REALAD,LDAPNO %LONGINTEGER PSTE %RECORD (STOREF) %NAME ST %RECORD (CDRF) %NAME LDAP %OWNINTEGER PAGESONOFF,OCPGOING=-1,TRIES=0 %STRING (9) DEVNAME,ONOFF %CONSTSTRING (5) %ARRAY DEVS(1:4)="OCP ","SAC ","SMAC ","DAP "; %IF MONLEVEL&2#0 %AND KMON&1<<17#0 %THEN PKMONREC("CONFIG CONTROL",P) DEV=P_P1>>16 IDENT=P_P1&X'FFFF' %IF 1<=DEV<=4 %THEN DEVNAME=DEVS(DEV) %ELSE DEVNAME="??? " %AND ->FAIL %IF DEV=3 %OR DEV=4 %THEN TOPST=(((PST(STORESEG)>>32&X'3FF80'+128)-ADDR(STORE(0))&X'3FFFF')//STOREFSIZE)-1 *LSS_(3); *USH_-26 *AND_3; *ST_MYPORT HISPORT=MYPORT!!1 ACT=P_DEST&15 %IF DEV=4 %AND MAPDAP=0 %THEN ->FAIL; ! DOES MAPPING OF LDAP ->DACT(ACT) DACT(0): ! CONFIGURE OFF ->COFF(DEV) DACT(1): ! CONFIGURE ON ->CIN(DEV) COFF(1): ! CONFIGURE OFF OCP %IF MULTI OCP=YES %START ->FAIL %UNLESS COM_NOCPS=2 %AND ((SSERIES=YES %AND 0<=IDENT<=1) %OR (SSERIES=NO %AND 2<=IDENT<=3)) %IF MYPORT#IDENT %START; ! CAN ONLY CONFIGURE OFF MYSELF P_P6=P_DEST; P_DEST=X'3F0001' PON(P); ! TRY AGAIN IN 1 SEC %RETURN %FINISH ! OCPGOING=MYPORT J=X'8000017C'+MY PORT<<18 I=INTEGER(J); INTEGER(J)=0; ! PROC I WAS RUNNING %IF I#0 %START I=I+LOCSN0 SERVA(I)_P=SERVA(I)_P&X'BFFFFFFF'; ! CLEAR EXECUTING BIT UNINHIBIT(I) P_DEST=I<<16!2; PON(P); ! SEND HIM A CONTINUE %FINISH %IF SSERIES=YES %START %IF MYPORT=COM_OCPPORT0 %START HALT OTHER OCP DCU1 RECOVERY(0); ! DCU1s to other OCP RESTART OTHER OCP(0) I=COM_OCP1 SCU PORT J=I %FINISHELSE I=COM_OCP0 SCU PORT %AND J=I I=X'4004601D'!I<<22 J=J<<22 *LB_I; *LSS_J; *ST_(0+ %B ); ! send mpint to other OCP & ! reset cross reporting %FINISHELSEIF BASIC PTYPE<=3 %START I=X'42056011'!HISPORT<<20 *LB_I; *LSS_X'80010000' *ST_(0+ %B ) %FINISHELSESTART *LSS_(X'4012'); *OR_X'100' *ST_(X'4012') %FINISH ! ! HAVE TOLD REMAINING OCP THAT I HAVE DIED. SO NOW LOOP FOR EVER ! %CYCLE *IDLE_X'F0FF' %REPEAT %RETURN %FINISHELSE ->FAIL CIN(1): ! CONFIGURE IN AN OCP %IF MULTI OCP=YES %START ->FAIL %UNLESS COM_NOCPS=1 %AND IDENT#COM_OCPPORT0 %AND ((SSERIES=YES %AND 0<=IDENT<=1) %OR %C (SSERIES=NO %AND 2<=IDENT<=3)) ->FAIL %IF SSERIES=NO %AND SMAC PORT(0,IDENT)#0; ! open relevant port ! ! MARK COMMS,GLA,BASE STACK&STORE ARRAY SEGS AS NONSLAVED. THESE ARE ! SET SLAVED BY CHOPSUPE UNLESS 2 OCPS ARE PRESENT AL IPL ! PST(4)=PST(4)!NONSLAVED PST(9)=PST(9)!NONSLAVED PST(STORESEG)=PST(STORESEG)!NONSLAVED PST(48)=PST(48)!NONSLAVED %IF SSERIES=YES %THEN STACK=2*IDENT+12 %ELSE STACK=2*IDENT+8 %IF SSERIES=NO %AND BASIC PTYPE<=3 %START *LSS_(X'600A'); *AND_X'CC'; *ST_(X'600A'); ! ALLOW ACTIVATES %FINISH COM_OCPPORT1=IDENT COM_NOCPS=2 %IF REMOTE ACTIVATE(IDENT,X'80000000'+(STACK+1)<<18)#0 %START COM_NOCPS=1 %IF SSERIES=NO %THEN J=SMACPORT(1,HISPORT) ->FAIL %FINISH %IF SSERIES=NO %START %IF BASIC PTYPE<=3 %START *LSS_1; *ST_(X'6009') %FINISHELSESTART *LSS_(X'4012'); *OR_X'300C'; *ST_(X'4012'); ! ALLOW MP INTS *LSS_(X'4013'); *OR_X'8004'; *ST_(X'4013'); ! SET MULT&DD %FINISH %FINISH ->SUCC %FINISHELSE ->FAIL %IF SSERIES=NO %START COFF(2): ! CONFIGURE OFF A SAC ->FAIL %UNLESS COM_NSACS=2 %AND 0<=IDENT<=1 %IF BASIC PTYPE=4=COM_OCPTYPE %AND COM_CLKX>>20&15=IDENT %START ! PROBLEMS WITH CLOCK IN SAC %IF COM_NOCPS>1 %THEN OPMESS("STILL DUAL OCPS") %AND ->FAIL K=IDENT!!1; ! REMAINING SAC I=(IDENT-K)<<20 J=COM_CLKX; *LB_J *LSS_(0+ %B ); *SBB_I *ST_(0+ %B ); ! TRANSFER CLOCK REG TO OTHER SAC *STB_J; COM_CLKX=J; ! AND UPDATE ADDRESS J=COM_CLKY; *LB_J *LSS_(0+ %B ); *SBB_I *ST_(0+ %B ); ! TRANSFER CLOCK REG TO OTHER SAC *STB_J; COM_CLKY=J; ! AND UPDATE ADDRESS J=COM_CLKZ; *LB_J *LSS_(0+ %B ); *SBB_I *ST_(0+ %B ); ! TRANSFER CLOCK REG TO OTHER SAC *STB_J; COM_CLKZ=J; ! AND UPDATE ADDRESS J=X'80000000'>>K; ! EXTERNAL INT BIT *LSS_(X'4012'); *AND_X'0FFFFFFF' *OR_J; *ST_(X'4012') *LSS_(X'4013'); *AND_X'000FFFFF' *SLSS_K; *USH_20; *OR_ %TOS *ST_(X'4013'); ! FOR RRTC INSTRUCTION %FINISH P_DEST=X'200007' P_SRCE=X'110005' P_P2=IDENT PON(P) %RETURN DACT(5): ! REPLY FROM DISC ->SAC USED %IF P_P2#0 P_DEST=X'300007' P_SRCE=X'110003' P_P2=IDENT PON(P) %RETURN DACT(3): ! REPLY FROM GPC ->SAC USED %UNLESS P_P2=0 %IF SFC FITTED=YES %AND DRUMSIZE>0 %START P_DEST=X'280007' P_SRCE=X'110006' P_P2=IDENT PON(P) %RETURN %FINISH DACT(6): ! REPLY FROM DRUM(ALWAYS OK) %IF COM_NOCPS>1 %AND MYPORT#COM_OCPPORT0 %THEN DPON(P,1) %ANDRETURN I=X'8'>>IDENT %IF BASIC PTYPE<=3 %START I=I!I<<4 *LSS_(X'600A'); *OR_I; *ST_(X'600A') %FINISHELSESTART I=(I<<12!I<<2)!!(-1) *LSS_(X'4012'); *AND_I; *ST_(X'4012') %FINISH COM_NSACS=1 COM_SACPORT0=IDENT!!1 SAC MASK=SAC MASK&(\(1<FAIL %UNLESS SMAC PORT(1,IDENT)=0 ->SUCC SAC USED: ! SOMETHING STILL ON SAC OPMESS(STRING(ADDR(P_P2))." STILL ON SAC".STRINT(IDENT)) ACT=0; ->FAIL CIN(2): ! CONFIGURE IN A SAC ->FAIL %UNLESS COM_NSACS=1 %AND 0<=IDENT<=1 %AND IDENT#COM_SACPORT0 ->FAIL %UNLESS SMAC PORT(0,IDENT)=0 ->FAIL %UNLESS SAFE IS READ(X'44000400'!IDENT<<20,J)=0 DACT(7): ! CONTINUE TRYTING %IF COM_NOCPS>1 %AND MYPORT#COM_OCPPORT0 %START P_DEST=X'110007' P_SRCE=P_DEST DPON(P,1) %RETURN %FINISH I=X'8'>>IDENT %IF BASIC PTYPE=3 %START I=(I!I<<4)!!(-1) *LSS_(X'600A'); *AND_I; *ST_(X'600A') %FINISHELSESTART I=(I<<10!I)<<2 *LSS_(X'4012'); *OR_I; *ST_(X'4012') %FINISH %CYCLE I=16*IDENT,1,16*IDENT+15 K=CONTYPE(I) P_P1=I; ! NEW PORT-TRUNK P_P2=I; ! OLD PORT-TRUNK P_DEST=0 P_SRCE=0 %IF K=2 %THEN P_DEST=X'20000A'; ! DISC RESET FPC %IF K=3 %THEN P_DEST=X'30000A'; ! GPC RESET GPC %IF P_DEST#0 %THEN PON(P) %REPEAT COM_SACPORT1=IDENT SAC MASK=SAC MASK!(1<SUCC CIN(4): ! CONFIGURE IN A DAP %IF DAP FITTED=YES %START ->FAIL %UNLESS (IDENT=LDAP_IPDAPNO&15 %AND LDAP_DAPSTATE&15=0) %OR LDAP_IPDAPNO=0 %IF SMAC RCONFIG#0 %START %IF SMAC RCONFIG=IDENT %THEN ->FAIL; ! THIS ONE AGAIN DPON(P,5); ! WAIT 5 SECS & RETRY %RETURN %FINISH %IF MYPORT#COM_OCPPORT0 %THEN DPON(P,1) %ANDRETURN K=COM_SDR4!IDENT<FAIL %UNLESS SAFE IS READ(K,CONFIG)=0 ->FAIL %UNLESS CONFIG&X'02000000'#0 %FINISH COFF(3): ! CONFIGURE OFF A SMAC ->FAIL %UNLESS 0FAIL %UNLESS 1<FAIL %IF LDAP_IPDAPNO&15=IDENT %AND LDAP_DAPSTATE>0 %REPEAT %FINISH ->FAIL %IF (COM_OCPTYPE=4 %OR COM_OCPTYPE=6) %AND 1<<(IDENT!!8)&COM_SMACS#0; ! & not interleavable ! full check very difficult! ->FAIL %UNLESS X'10000'<150 %THEN SMAC RPAGES=0 %ANDRETURN; ! 2ND REQUEST=FORCE IT OFF ->FAIL %FINISH ->FAIL %UNLESS SAFE IS READ(COM_SDR4!IDENT<>22&15=IDENT %START PAGESONOFF=PAGESONOFF+1; ! IN RIGHT SMAC %IF ST_REALAD<0 %AND ST_USERS=0 %THEN J=J+1 ! forget abandoned flawed pages ! REMEMBER 8K PHOTO AREA IN SMAC1 %IF IDENT=1 %AND ST_USERS=255 %AND ST_REALAD&X'3FFFFF'FAIL; ! SHOULD NOT OCCUR %FINISH %REPEAT SMAC RCONFIG=IDENT SMAC RPAGES=PAGES ONOFF-J %IF MULTIOCP=YES %START; *TDEC_(STORESEMA); %FINISH; ! cannot hold thru 2 loops ! ! GRAB ANY FREE PAGES FROM FREE LIST AT ONCE ! %IF MULTI OCP=YES %THEN SEMALOOP(STORESEMA,1) SMAC RPAGES=SMAC RPAGES-1 %WHILE QUICK EPAGE(1,1<0 %IF MULTI OCP=YES %START; *TDEC_(STORESEMA); %FINISH P_DEST=X'3000D' P_SRCE=X'110004' PON(P); ! KICK SCHEDULE TO FREE STORE P_DEST=X'110004' P_P2=0 P_P3=SMAC RPAGES P_P4=PAGE FREES DPON(P,5); ! KICK SELF(P_P1 INTACT!) %RETURN DACT(4): ! CONTINUE CONFIGURING OFF STORE %IF P_P2=0 %THEN DONT SCHED=1; ! AFTER STOPPING SNOOZING ! NOW KEEP EVERYONE OUT P_P2=P_P2+1 TRIES=P_P2; ! COUNT OF ATTEMPTS %IF SMAC RPAGES#0 %START P_P3=SMAC RPAGES; ! DEBUGGING ONLY I=P_P4; P_P4=PAGE FREES DPON(P,1) %RETURNUNLESS MPLEVEL=0 %AND DONT SCHED#0 %AND (PAGEFREES=0 %OR (PAGEFREES=I %AND P_P2>8)) ! CONTINUE WAITING ! unless outs stuck (dfc dowm?) %FINISH ! ! AFTER 15 SECS OR WHEN ALL PAGES FREE CHANGE SCHEDULING PARAMETER ! AND RESTART SCHEDULING ! %IF DONT SCHED#0 %START; ! SCHEDULING NOT YET RESET UNALLOCEPS=UNALLOCEPS-OVER ALLOC-PAGES ONOFF MAX OVERALLOC=OVERALLOC PERCENT*UNALLOCEPS//100 OVER ALLOC=MAX OVERALLOC UNALLOCEPS=UNALLOCEPS+OVER ALLOC P_DEST=X'30006' DONT SCHED=0 PON(P); ! KICK SCHEDULE %RETURNUNLESS SMAC RPAGES=0 %FINISH ! ! CLEAR OUT STORE TABLES ! %CYCLE I=1,1,TOPST ST==STORE(I) %IF ST_REALAD>>22&15=SMAC RCONFIG %THEN ST=0 %REPEAT ! ! CLOSEUP BLOCK ARRAY AND RESET COUNT ! COM_SEPGS=COM_SEPGS-PAGES ONOFF MAXP4PAGES=P4PERCENT*COM_SEPGS//100 J=0 %CYCLE I=0,1,COM_SBLKS-1 K=BLOCKAD(I) %IF K>>22&15#SMAC RCONFIG %THEN BLOCKAD(J)=K %AND J=J+1 %REPEAT BLKS=COM_SBLKS-J; ! DAP SIE COM_SBLKS=J ->DAPIN %IF DAP FITTED=YES %AND DEV=4; ! DAP IN NOT SMAC OFF J=64+16*SMAC RCONFIG PST(I)=0 %FOR I=J,1,J+15 ! ! FINISH OFF INCLUDING CLOSING SAC PORT UNLESS INTERLEAVED ! COM_SMACS=COM_SMACS!!1<SUCC COFF(4): ! CONFIGURE OFF A DAP %IF DAP FITTED=YES %START ->FAIL %UNLESS IDENT=LDAP_IPDAPNO&15 %AND LDAP_DAPSTATE>0 ->FAIL %IF SMAC RCONFIG#0 %IF 1SUCC LDAP_DAPSTATE=LDAP_DAPSTATE&16; ! NO LONGER A DAP J=X'80000000'>>(LDAP_IPDAPNO>>4) ! ! NOW ACTIVE DAPS PRESENT. CLOSE OFF INTERRUPTS ! %IF BASIC PTYPE<=3 %START; ! DAP ON 2970 *LSS_(X'600A') *OR_J *ST_(X'600A') %FINISHELSESTART; ! DAP ON P4 ARCHITECTURE *LSS_(X'4012') *SLSS_J; *NEQ_-1; *AND_ %TOS *ST_(X'4012') %FINISH ! AND DROP THRO TO ADD AS STORE %FINISH CIN(3): ! CONFIGURE IN A SMAC ->FAIL %UNLESS DEV=4 %OR COM_SMACS&1<FAIL %UNLESS J=0 BLKS=0 BLKSIZE=COM_BLKSIZE CONFIG=CONFIG!COM_BLOCKZBIT; ! MUST BE A BLOCK ZERO ! %IF CONFIG&X'01000000'#0 %THEN BLKSIZE=X'40000'; ! 16K CHIP STORE ! ! COUNT THE NUMBER OF (128K) BLOCKS AND ADD TO BLOCK ARRAY ! DONT UP THE BLOCK COUNT YET. ADDING THE SMAC CAN STILL FAIL ! %CYCLE I=0,1,15 %IF CONFIG&COM_BLOCKZBIT<<(I*COM_BLKSHIFT)#0 %START ! BLOCK I IS PRESENT J=COM_SBLKS+BLKS BLOCKAD(J)=IDENT<<22+I*BLKSIZE; ! BLOCKS REAL ADDRESS %IF BLKSIZE=X'40000' %THEN BLOCKAD(J+1)=BLOCKAD(J)+X'20000' BLKS=BLKS+BLKSIZE//X'20000' %FINISH %REPEAT PAGES ONOFF=(128//EPAGESIZE)*BLKS ! ! CHECK THE EMPTY SLOTS IN THE STORE ARRAY. IF NOT ENOUGH THEN GRAB ! EXTRA PAGES TO EXTEND AS NECESSARY ! %CYCLE J=0 %CYCLE I=1,1,TOPST %IF STORE(I)_REALAD=0 %THEN J=J+1 %REPEAT %EXITIF J>=PAGES ONOFF K=QUICK EPAGE(0,COM_SMACS>>16); ! PAGE IN SYSTEM SMACS ->FAIL %IF K<0; ! NO STORE TO EXTEND TABLE K=STORE(K)_REALAD!X'80000001' I=PST(STORESEG)>>42&255; ! PAGE NO OF LAST 1K PAGE %CYCLE J=0,1,EPAGESIZE-1; ! FILL IN PAGE TABLE INTEGER(X'80000004'+STORESEG<<18+4*(I+J))=K+1024*J %REPEAT PST(STORESEG)=PST(STORESEG)+LENGTHENI(EPAGESIZE*1024)<<32 TOPST=TOPST+1024*EPAGESIZE//STOREFSIZE J=COM_PSTB; *LB_J *LSS_(0+ %B ); *ST_(0+ %B ); ! CLEAR ATU SLAVE STORE %REPEAT ! ! CYCLE UP THE BLOCK ARRAY COMPLETEING STORE&PST ENTRIES ! PSTE=PST(64)&X'FFFC000080000001' K=1; P_DEST=X'60001' %IF MULTI OCP=YES %THEN SEMALOOP(STORESEMA,1) %CYCLE I=COM_SBLKS,1,COM_SBLKS+BLKS-1 REALAD=BLOCKAD(I) %IF DEV=3 %START; ! DPAS HAVE PST SET J=X'20000'; ! HALF A SEGMENT %IF REALAD&X'20000'#0 %THEN J=X'40000' PST(64+REALAD>>18)=PSTE!(REALAD&X'FFFC0000')!LENGTHENI(J-X'80')<<32 %FINISH ! clear store to remove parities *LDTB_X'38002000'; *LDA_REALAD; *INCA_VIRTAD; *LB_0; *LSQ_0 AGN: *ST_(%DR + %B ); *CPIB_X'1FFF'; *JCC_4, %CYCLE J=0,1,SEGEPSIZE//2-1 K=K+1 %WHILE STORE(K)_REALAD#0 STORE(K)_REALAD=REALAD+EPAGESIZE*1024*J %IF IDENT=1 %AND J<=1 %AND REALAD&X'3FFFFF'=0 %THEN STORE(K)_USERS=255 %ELSESTART ! DONT USE PHOTO ATEA IN SMAC 1 P_P2=K; ! STORE INDEX RETURN EPAGE(P) %FINISH %REPEAT %REPEAT ! CHANGE SCHEDULING PARAMS ! FOR REALLOCATED STORE J=PAGES ONOFF*OVERALLOC PERCENT//100 UNALLOCEPS=UNALLOCEPS+PAGESONOFF+J OVERALLOC=OVERALLOC+J MAX OVERALLOC=MAXOVERALLOC+J COM_SEPGS=COM_SEPGS+PAGESONOFF MAXP4PAGES=P4PERCENT*COM_SEPGS//100 COM_SBLKS=COM_SBLKS+BLKS COM_SMACS=COM_SMACS!1<SUCC %IF DAP FITTED=YES %START DAPIN: ! DAP STORE MUST BE CONTIGUOUS ! OR DAP CAN ONLY BE USED AS SMAC %CYCLE I=1,1,COM_SBLKS-1 ->FAIL %UNLESS BLOCKAD(I)=BLOCKAD(I-1)+X'20000' %OR BLOCKAD(I)>>22#IDENT %OR IDENT#BLOCKAD(I-1)>>22 %REPEAT LDAP_IPDAPNO=IDENT LDAP_DAP1=(COM_SDR4!(LDAP_IPDAPNO&15)<SUCC %FINISH %FINISH DACT(2): ! FINISH CONFIGURIN OFF HIM %IF MULTI OCP=YES %START %IF OCPGOING<0 %THEN DEVNAME=DEVNAME.TOSTRING(17) OCPGOING=-1; ! IF DUE TO FAILURE FLASH MSG %IF SSERIES=YES %AND MYPORT#COM_OCPPORT0 %START; ! swap SCU ports J=COM_OCP0 SCU PORT COM_OCP0 SCU PORT=COM_OCP1 SCU PORT COM_OCP1 SCU PORT=J %FINISH COM_NOCPS=1; COM_OCPPORT0=MYPORT COM_OCPPORT1=HISPORT %IF SSERIES=NO %THEN J=SMACPORT(1,HISPORT); ! CLOSE OFF HIS SMAC PORT %FINISH SUCC: %IF ACT&1#0 %THEN ONOFF="ON" %ELSEIF DEV=4 %THEN ONOFF="AS STORE" %ELSE ONOFF="OFF" OPMESS(DEVNAME.STRINT(IDENT)." CONFIGURED ".ONOFF) %IF DEV=1 %START; ! update oper info %IF ACT&1=0 %THEN ONOFF=" ".STRINT(COM_OCPPORT0)." " %ELSE %C ONOFF="s ".STRINT(COM_OCPPORT0)." ".STRINT(COM_OCPPORT1) P_DEST=x'320006'; ! display text with pon P_P1=x'04100000'; ! lest race with oper init STRING(ADDR(P_P1)+3)=ONOFF PON(P) { == display text(0,4,16,onoff) } %FINISH %RETURN CIN(*): COFF(*): DACT(*): FAIL: ! UNKNOWN DEVICE OR OTHERS OPMESS("CANNOT CONFIGURE ".DEVNAME.STRINT(IDENT)) %RETURN %INTEGERFN MAPDAP !*********************************************************************** !* FINDS THE LOGICAL DAP NO CORRESPONDING TO THE DAC(SMAC) NO * !*********************************************************************** %IF DAP FITTED=YES %START %FOR LDAPNO=1,1,MAXLDAP %CYCLE LDAP==COM_CDR(LDAPNO) %IF LDAP_IPDAPNO&15=IDENT %THENRESULT=LDAPNO %REPEAT %IF ACT=1 %OR ACT=4 %START; ! CONFGR ON EMPTY SLOT OK %FOR LDAPNO=1,1,MAXLDAP %CYCLE LDAP==COM_CDR(LDAPNO) %IF LDAP_IPDAPNO=0 %THENRESULT=LDAPNO %REPEAT %FINISH %FINISH %RESULT=0 %END %INTEGERFN SMAC PORT(%INTEGER OPEN,PORT) !*********************************************************************** !* OPEN (OPEN=0) %OR CLOSE A SMAC PORT IN ALL ONLINE SMACS * !*********************************************************************** %INTEGER I,J,K,L,P,VAL,RES,DAPS K=X'20'>>PORT P=K L=K!!(-1) %IF OPEN=0 %THEN K=0 RES=0; DAPS=0 %IF DAP FITTED=YES %START %FOR I=1,1,MAXLDAP %CYCLE %IF COM_CDR(I)_IPDAPNO>0 %THEN DAPS=DAPS!1<1 %THEN HALT OTHER OCP *LSS_X'382E'; *ST_(3); ! No unwanted interrupts %IF SSERIES=NO %START %FOR I=0,1,31 %CYCLE; ! Master clear all controllers J=BYTEINTEGER(COM_CONTYPEA+I); ! controller type %UNLESS J=0 %START %IF COM_NSACS=1 %AND I>>4#COM_SACPORT0 %THENCONTINUE; ! SAC gone %IF ACT=2 %START; ! disconnect DFC & GPC devices PP=0 PP_P1=I; ! port/trunk %IF J=2 %THEN PP_DEST=11 %AND DISC(PP) %ELSEIF J=3 %THEN PP_DEST=9 %AND GDC(PP) %FINISH J=X'40000800'!I<<16 *LB_J; *LSS_2; *ST_(0+ %B ) %FINISH %REPEAT %FINISH %CYCLE *IDLE_X'DEAF'; ! Go to sleep %REPEAT %END !* !* !* %ROUTINE UPDISP(%INTEGER PROCESS,OFFSET, %STRING (13) S) %INTEGER LINE,POS PROCESS=PROCESS-1 LINE=PROCESS//3; ! 3 PER LINE +HEADER POS=(PROCESS-3*LINE)*13; ! 40CHARS FOR EACH 3 PROCS DISPLAY TEXT(-1,LINE+5,POS+OFFSET,S); ! CURRENTLY 5 HEADER LINES %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 192 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 %RECORDFORMAT SIGOUTPF(%INTEGER DEST,SRCE,P1,P2,P3,P4,P5,P6,TYPE,SSN,SSNAD,SUSP) %CONSTRECORD (SIGOUTPF) %NAME SIGOUTP=SIGOUTPAD !----------------------------------------------------------------------- ! CLAIMED BLOCK TABLES %CONSTHALFINTEGERARRAYNAME SST=SSTAD %RECORDFORMAT CBTF(%INTEGER DA, %HALFINTEGER AMTX, %BYTEINTEGER TAGS,LINK) %CONSTRECORD (CBTF) %ARRAYNAME CBTA=CBTAD %RECORD (CBTF) %NAME CBT %INTEGER CBTP !----------------------------------------------------------------------- ! CONSOLE IO & ACCOUNTS RECORDS %RECORD (IOSTATF) %NAME IOSTAT %RECORDFORMAT ACNTF(%LONGINTEGER LTIME, %INTEGER PTURNS) %RECORD (ACNTF) %NAME ACNT %INTEGERNAME ICREVS,SEMAHELD; ! INSTRUCTION COUNTER REVS WORD !----------------------------------------------------------------------- ! ACTIVE SEGMENT TABLES %CONSTINTEGER MAXAS=31 %CONSTINTEGER SMULTIPLE CON=X'20'; ! SYSTEM SHRD COMPONENT %CONSTINTEGER ADVISORY SEQ=X'40'; ! ADVISORY SEQUENTIAL ACCESS BIT %CONSTINTEGER CONTINUATN BLK=X'80'; ! CBT BLOCK IS NOT THE FIRST %LONGINTEGERARRAY AS(0:MAXAS) %BYTEINTEGERARRAY ASEG(0:MAXAS) %INTEGER ASFREE,ASWAP,ASWIP,ASSHR; ! %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,UEPN,RTLIM,RTN !----------------------------------------------------------------------- %CONSTINTEGER SMALL SEQUENTIAL=8; !USED TO DECIDE TO RECAP OR NOT %INTEGERFNSPEC CHECK RES(%INTEGER WRITE,LEN,AD) %INTEGERFNSPEC CHECKDA(%INTEGER DA) %ROUTINESPEC PAGEOUT(%INTEGER VSSEG,VSEPAGE, %RECORD (CBTF) %NAME CBT) %ROUTINESPEC ASOUT(%INTEGER ASP) %ROUTINESPEC STROBE(%INTEGER SFLAGS) %ROUTINESPEC WORKSET(%INTEGER RECAP) %ROUTINESPEC CLEAR ACCESSED BITS %ROUTINESPEC DEACTIVATE(%INTEGER MASK) %ROUTINESPEC FREE AS %ROUTINESPEC RETURN PTS %INTEGERFNSPEC FIND PROCESS %INTEGERFNSPEC CURSSN %ROUTINESPEC WAIT(%INTEGER DACT,N) !----------------------------------------------------------------------- %RECORD (PARMF) P; ! FOR POFFING PARAMETERS %RECORD (PROCF) %NAME PROC %RECORD (PARMF) %NAME ALLOUTP; ! MAPPED ONTO DIROUTP OR ! SIGOUTP AS STACKS SWOP %RECORD (SERVF) %NAME SERV0,SERV,SERV3 %RECORD (PARMF) POUT %RECORD (SSNP1F) %NAME SSNP1 %RECORD (STOREF) %NAME ST %CONSTLONGINTEGERARRAYNAME LST=LSTVAD %INTEGERARRAYNAME PT %INTEGER PROCESS,ME,LSN3,PTAD,VSPARM,PEPARM,VSSEG,VSEPAGE,EPX,I,J,K,NEWSTK,STOREX,DEST,SRCE,SUSP,SNOOZES,DA,LASTDA, NONSEQVSIS,LCERRS,XSTROBE,SEGLEN,PTEPS,ASDESTROY,PTP,ASP,ASB,OUTN,PTE,PROCACTAD1,PROCACTAD2,HIGHSEG,LOCKST, LOCKSTX,LTAD,TSTPTR %IF MONLEVEL&4#0 %THENSTART %INTEGER IT,ITT,IC,ICC,MONVAD,MONPTAD,MONLIM %ROUTINESPEC GARNER(%INTEGER EVENT,PARAM) %LONGINTEGERNAME LPIT %FINISH %STRING (15) INTMESS %SWITCH ACTIVITY(0:16),VSCAUSE(0:4),ASYN0(1:3),AMTXSW(-4:0) %CONSTINTEGER MAXDIROUT=28 %CONSTLONGINTEGER DGLAEPAGES=4; ! EPAGES OF DIRECTOR GLA SPACE %CONSTLONGINTEGER LONGONE=1; ! FOR COMPILE TIME COMPUTATIONS %SWITCH DIROUT(0:MAXDIROUT) %CONSTINTEGER MAXOUTACR=DIRACR; ! UP TO DIRECTOR LEVEL %CONSTBYTEINTEGERARRAY PAGEOUT DELAY(0:10)=1,2,4,8,15(7) ! TOTAL PAGEOUT DELAY>120 SECS ! TO ALLOW TIME TO AUTOLOAD DFC ! !----------------------------------------------------------------------- ! 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 ENABLE %MONITOR TO FIND ! GLOBAL VARIABLES PROC==PROCA(PROCESS) ME=(PROCESS+LOCSN0)<<16 LSN3=PROCESS+LOCSN3 SERV0==SERVA(PROCESS+LOCSN0) SERV3==SERVA(LSN3) ! ***** SEMAPHORE?******** SUPPOFF(SERV0,P); ! OBTAIN STARTUP RECORD ! ! INITIALIZE LOCAL STACKS INFO ! LSTKSSN(1)=4; ! DIRECTOR/USER STACK SEGMENT LST(5)=LST(1)+X'80'+(DIRACR-LCACR)<<56; ! AND SSN+1 LSTKSSN(2)=6; ! SIGNAL STACK LST(7)=LST(5)+X'80'; ! AND SIGNAL SSN+1 %CYCLE I=3,1,LSTKN LSTKSSN(I)=0 %REPEAT LST(DIRCSEG)=LST(0)&X'FFFC0000FFFFFFFF'+8+(DIRACR-LCACR)<<56+LENGTHENI(DIRCSEGL)<<32 ALLOUTP==DIROUTP %IF MONLEVEL&4#0 %START MONVAD=0 %IF PROC_STATUS&4=0 %THEN LPIT==PERFORM_SERVIT(LOCSN0+2) %ELSE LPIT==PERFORM_SERVIT(LOCSN0+3) %FINISH !----------------------------------------------------------------------- ! INITIALISE CLAIMED BLOCK TABLES %CYCLE I=0,1,LSTLEN-1 SST(I)<-X'FFFF'; ! ALL SEGMENTS UNCONNECTED LST(I)=LST(I)!X'7F00000000'; ! ALL SEGMENTS INACTIVE %REPEAT ASFREE=X'FFFFFFFF'; ! ALL FREE ASWAP=0 ASSHR=0 ASWIP=0 PEPARM=-1 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 ! AND J-VECTOR FOR SCTI(3) LONG INTEGER(SCTJ30)=0 LONG INTEGER(SCTJ30+8)=0 ! REQUEST INPUT AS J=1 ENTRY LONG INTEGER(SCTJ30+16)=X'80F0000000140001' LONG INTEGER(SCTJ30+24)=RTDR(REQUEST INPUT); ! YIELDS DESCR-DESCR ! REQUEST OUTPUT AS J=2 ENTRY LONG INTEGER(SCTJ30+32)=X'80F0000000140001' LONG INTEGER(SCTJ30+40)=RTDR(REQUEST OUTPUT); ! YIELDS DESCR-DESCR ! CHANGE CONTEXT AS J=3 ENTRY LONG INTEGER(SCTJ30+48)=X'80F0000000140001' LONG INTEGER(SCTJ30+56)=RTDR(CHANGE CONTEXT) !----------------------------------------------------------------------- ! CONNECT DIRECTOR FILES ! CODE AS SEG2 USING TOP 2 CBTS ! GLA AS SEG3 USING CBT0 ! STACK AS SEG4 USING CBT1 SST(2)=CBTLEN-2; SST(3)=0; SST(4)=1 LST(2)=X'5003FFFF00000000'!DIRACR<<52; ! EXECUTE &READ CBTA(CBTLEN-2)_DA=P_P2 CBTA(CBTLEN-2)_TAGS=MAXBLOCK-1 CBTA(CBTLEN-2)_LINK=SMULTIPLE CON; ! SYSTEM SHARING OF DIRECTOR CBTA(CBTLEN-1)_DA=P_P2+MAXBLOCK CBTA(CBTLEN-1)_TAGS=MAXBLOCK-1 CBTA(CBTLEN-1)_LINK=CONTINUATN BLK!SMULTIPLE CON LST(3)=X'400003FF00000000'!DIRACR<<52!DIRACR<<56!(DGLAEPAGES*EPAGESIZE-1)<<42 CBTA(0)_DA=P_P3 CBTA(0)_TAGS=(DGLAEPAGES-1)!X'80'; ! GLA IS 'NEWCOPY' LST(4)=X'4FF003FF00000000'!(LONGONE*MAXBLOCK*EPAGESIZE-1)<<42 CBTA(1)_DA=P_P4 CBTA(1)_TAGS=(MAXBLOCK-1)!X'80'; ! STACK IS 'NEWCOPY' !----------------------------------------------------------------------- %IF PROCESS=1 %THENSTART; ! SET UP IST ENTRIES ONCE ONLY ! BUT WRITE TO BOTH IST SEGMENTS ! FOR MULTI-PROCESSOR INSTALLATIONS ! SET UP DUMMY IST VECTOR *STLN_I ISTDUM_LNB=I ISTDUM_PSR=X'00140001' ISTDUM_PC=0 ISTDUM_SSR=X'01803BAE'; ! ONLY EVENT PENDING,PE,VSE&SYSERR *STSF_I ISTDUM_SF=I ISTDUM_IT=MAXIT ISTDUM_IC=MAXIT ISTDUM_CTB=0 J=X'80000000'!COM_OCPPORT0<<18; ! IST ADDRESS FOR IPL PROC K=J!!X'40000'; ! TOTHER OCP IIST ! SET VS ERROR IST ENTRY *JLK_; *LSS_ %TOS; *ST_I ISTDUM_PC=I RECORD(J+X'80')<-ISTDUM %IF MULTIOCP=YES %THEN RECORD(K+X'80')<-ISTDUM ! SET INTERVAL TIMER IST ENTRY *JLK_; *LSS_ %TOS; *ST_I ISTDUM_PC=I RECORD(J+X'A0')<-ISTDUM %IF MULTIOCP=YES %THEN RECORD(K+X'A0')<-ISTDUM ! SET PROG ERROR IST ENTRY *JLK_; *LSS_ %TOS; *ST_I ISTDUM_PC=I RECORD(J+X'C0')<-ISTDUM %IF MULTIOCP=YES %THEN RECORD(K+X'C0')<-ISTDUM ! SET UP OUT IST ENTRY *JLK_; *LSS_ %TOS; *ST_I ISTDUM_PC=I RECORD(J+X'100')<-ISTDUM %IF MULTIOCP=YES %THEN RECORD(K+X'100')<-ISTDUM ! SET INSTRUCTION COUNTER IST ENTRY *JLK_; *LSS_ %TOS; *ST_I ISTDUM_PC=I ISTDUM_IC=0 RECORD(J+X'160')<-ISTDUM %IF MULTIOCP=YES %THEN RECORD(K+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(J+X'E0')<-ISTDUM %IF MULTIOCP=YES %THEN RECORD(K+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'01803BAE' *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 TO ENTRY DESCRIPTOR SSNP1_DR1=X'000C0000'; ! AT START OF GLA PROC_STACK=NEWSTK; ! DIRECTOR STACK ON INITIAL ENTRY !----------------------------------------------------------------------- ! ! 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 : USED 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' !----------------------------------------------------------------------- ! 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 DIRLOADER ENTRY POINT SSNP1_SSR=X'01800800'; ! NO INSTRUCTION COUNTER INTS SSNP1_SF=NEWSTK!X'14' SSNP1_IT=0 SSNP1_IC=MAXIT SSNP1_B=0; ! ZERO FOR 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 BYTEINTEGER(ADDR(DIROUTP_P3)+3)=PROC_INCAR DIROUTP_P4=SIGOUTPAD DIROUTP_P5=SCTI0 DIROUTP_P6=1; ! DACT FOR INT MESSGES FROM FE SIGOUTP_DEST=LSTLEN SIGOUTP_SRCE=SSTAD SIGOUTP_P1=CBTLEN-1; ! HIGHEST CBT ENTRY ! WAS ADDR(CBTASL) SIGOUTP_P2=CBTAD SIGOUTP_P3=ADDR(ACNT) SIGOUTP_P4=ADDR(ICREVS) SIGOUTP_P5=ADDR(IOSTAT) SIGOUTP_P6=ADDR(SEMAHELD) !----------------------------------------------------------------------- ! REPLY TO SCHEDULE POUT=0 POUT_DEST=X'30002'; ! SCHEDULE PROCESS CREATED POUT_SRCE=ME POUT_P1=PROCESS PON(POUT) !----------------------------------------------------------------------- RETURN: ! INTERRUPT BACK TO KERNEL *LSS_X'01803FFF'; ! NO SYSTEM ERROR INTS *ST_(3) LSSNP1P=LSSNP1; ! LOCAL CNTRLR 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 %IF MONLEVEL&4#0 %THENSTART *LSS_(6); *ST_IC; *LSS_(5); *ST_IT LCIC=LCIC+MAXIT-IC LCIT=LCIT+MAXIT-IT %FINISH *ACT_ %TOS *IDLE_X'B00B' !----------------------------------------------------------------------- ENTERI:*JLK_ %TOS ! NORMAL CALLS REACTIVATE TO HERE ! ****SEMAPHORE******** SUPPOFF(SERV0,P); ! OBTAIN PARAMETER RECORD %IF MONLEVEL&2#0 %AND KMON&1#0 %THEN PKMONREC("LOCALC:",P) ->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 ! 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&(\(HADTONFLY!HADPONFLY!X'11')) ! RESET FOR NEW RESIDENCE XSTROBE=0 %IF SNOOZING=YES %THEN SNOOZES=0 %AND NONSEQVSIS=-1000 PTEPS=0 PTP=0 LASTDA=0 EPN=0; UEPN=0 PROC_EPN=0 HIGHSEG=2 RETIME: ! START NEW TIMESLICE SSNP1==RECORD(PROC_STACK!X'40000'); ! PROCESS CONTEXT %IF SSNP1_IT&X'FF800000'=0 %THENSTART %IF MONLEVEL&4#0 %THEN LPIT=LPIT-SSNP1_IT ACNT_LTIME=ACNT_LTIME-COM_ITINT*SSNP1_IT; ! UNUSED TIME %FINISH SSNP1_IT=TIMESLICE; ! START NEW TIMESLICE %IF MONLEVEL&4#0 %THEN LPIT=LPIT+TIMESLICE ACNT_LTIME=ACNT_LTIME+COM_ITINT*TIMESLICE RTN=0 ! SEMAPHORE FOR TESTING SERV? %IF SERV3_P<<2#0 %AND PROC_STACK#LSTKSSN(2)<<18 %THEN ->ASYNCH %IF SUSP#0 %THEN ->DIRPONREPLY ACT: ! ACTIVATE INTO USER PROCESS %IF KERNELQ#0 %THEN ->ONFRUNQ; ! DO ANY KERNEL SERVICES ! ! COUNT ACTIVATIONS TO PROCESS ! %IF MONLEVEL&4#0 %THENSTART %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 %FINISH *LSS_(3); *AND_X'FFFFCFF5'; *ST_(3); ! UNMASK PERI&EXTERNAL INT *LXN_PROCACTAD2; ! ADRRESS OF ACTIVATE WORDS *ACT_(%XNB +0) !----------------------------------------------------------------------- ACTIVITY(2): ! CONTINUE WITH CORE RESIDENCE PROC_STATUS=PROC_STATUS&(\2); ! IN CASE CAME FROM ONFRUNQ ACTIVATE: ! CHECK ASYNCH MESSAGE ! **** SEMAPHORE FOR CHECK? %IF SERV3_P<<2=0 %OR PROC_STACK=LSTKSSN(2)<<18 %THEN ->ACT %IF SST(LSTKSSN(2))=X'FFFF' %THEN ->ACT; ! SIGNAL STACK NOT CREATED(STARTUP) ! OR HAS BEEN DESTROYED(CLOSEDOSN) !----------------------------------------------------------------------- ASYNCH: ! ASYNCHRONOUS MESSAGE POFFABLE SUPPOFF(SERV3,P) I=P_DEST&X'FFFF' %IF I=0 %THEN ->ASYN0(P_P1) %IF I=X'FFFF' %THEN OPMESS("PROCESS ".STRINT(PROCESS)." TERMINATED") %AND NEWSTK=PROC_STACK %AND ->TERMINATE %IF I=X'FFFE' %THENSTART *OUT_99; ! CRASH WITH MASKED OUT INT %FINISH %IF I=X'FFFD' %START *PUT_0; *PUT_0; ! FAIL WITH ILLEGAL INSTRN %FINISH %UNLESS I=1 %THEN ->SIGINT INTMESS<-P_INTMESS %IF LENGTH(INTMESS)=1 %THENSTART %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 SIGACT: ! SWOP IT & IC ALLOUTP==SIGOUTP 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 %OR SSNP1_PSR&3=0 %THEN PRINT STRING(" ACTIVATE CONTEXT INVALID") %AND ->TERMINATE ->ACTIVATE %FINISHELSESTART %IF LENGTH(INTMESS)>1 %THEN IOSTAT_INTMESS=INTMESS %IF P_P2>=0 %AND IOSTAT_IAD#P_P2 %THENSTART IOSTAT_IAD=P_P2 %IF SUSP<0 %THEN SUSP=0 %FINISH RESUSP: ! **** SEMAPHORE NEEDED FOR TEST? %IF SERV3_P<<2#0 %THEN ->ASYNCH %IF SUSP=0 %THEN ->ACT ! AVOID RESUSPENDING IF UNNECESSARY %IF SUSP&X'7FFFFFFF'<=LOCSN3 %THENSTART SERV==SERVA(SUSP) %IF SERV_P<<2#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); ! IE ALL USED ACTIVATE BLKS PROC_STATUS=PROC_STATUS!24; ! SET AMT GOING & AMT GONE BITS ->RESUSP ASYN0(3): ! DUMMY AWAKEN FOR RECONFIGTN %IF SUSP#0 %THEN SRCE=SUSP %AND ->SUSPWS %IF LOCKST=0 %THEN ->DEAD; ! DEPART IF NO LOCKED DOWN AREA ->ACT; ! RESUME TO FREE LOCKED DOWN AREA !----------------------------------------------------------------------- ACTIVITY(3): ! CONTINUE AFTER SUSP ON FLY %IF SNOOZING=YES %THENSTART %IF MONLEVEL&4#0 %THEN PERFORM_SNOOZN=PERFORM_SNOOZN+EPN EPLIM=P_P1 RTLIM=P_P2 ! SNOOZES=SNOOZES+1 NONSEQVSIS=0 CLEAR ACCESSED BITS ! STROBE %IF SNOOZES&15=0 ACNT_PTURNS=ACNT_PTURNS+EPN PROC_STATUS=PROC_STATUS&(\(HADPONFLY!HADTONFLY)) ! RESET FOR NEW RESIDENCE ->RETIME %FINISH !---------------------------------------------------------------------- VSERRI:*JLK_ %TOS ! VIRTUAL STORE INTS ENTER HERE *LSS_ %TOS; *ST_I; ! OLD STACK *LSS_ %TOS; ! PARAMETER *ST_VSPARM %IF I=0 %THEN ->LCPE; ! LC CAN HAVE NO VSIS! %IF VSPARM<0 %THEN PEPARM=9 %AND ->PE; ! PUBLIC VSI VSSEG=VSPARM>>18 %IF 0>32&127 VSEPAGE=VSPARM>>EPAGESHIFT&(SEGEPSIZE-1) %IF MONLEVEL&4#0 %AND MONVAD>0 %THEN GARNER(0,VSPARM) ->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 %THENSTART PRINT STRING("VS ERROR ON SIGNAL STACK PARM=".STRHEX(VSPARM)." ") ->TERMINATE %FINISH ->SIGACT !----------------------------------------------------------------------- VSCAUSE(1): ! SEGMENT NOT AVAILABLE %IF SST(VSSEG)=X'FFFF' %THEN ->VSE; ! NO CONNECTION SEGLEN=LST(VSSEG)>>(32+EPAGESHIFT)&(SEGEPSIZE-1)+1 ! ! IF THE SEGMENT IS NOT AVAILABLE THE HARDWARE HAS NOT CHECKED THAT ! THE PAGE IS WITHIN THE SEGMENT LIMIT. DO THIS BY SOFTWARE ! %IF VSEPAGE>=SEGLEN %THEN VSPARM=VSPARM!3 %AND ->VSE %IF SEGLEN<=PTEPS %THEN ->OLDPTP %IF EPN>=EPLIM %THEN ->NOPAGES %IF MULTIOCP=YES %THENSTART *INCT_(STORESEMA) *JCC_8, SEMALOOP(STORESEMA,0) SSEMAGOT: %FINISH %IF FREE EPAGES>0 %START STOREX=QUICK EPAGE(0,-1) %IF MULTI OCP=YES %START; *TDEC_(STORESEMA); %FINISH ->ACT9 %FINISH POUT_SRCE=ME!9 POUT_P2=0; ! CLEAR TO ZERO GET EPN=GET EPN+1 %IF MULTIOCP=YES %START; *TDEC_(STORESEMA); %FINISH %IF PAGEFREES<=1 %AND GETEPN>=MPLEVEL+1-COM_NOCPS %THEN POUT_DEST=X'20000' %AND PON(POUT) POUT_DEST=X'50000' PON(POUT) ->RETURN !----------------------------------------------------------------------- ACTIVITY(9): ! REPLY FROM GET EPAGE FOR PT STOREX=P_P2 %IF STOREX=0 %THEN ->DEAD; ! DEADLY EMBRACE RECOVERY ACT9: ! PAGE TABLE EPAGE HERE ST==STORE(STOREX) ST_LINK=PTP; ! LIST OF PAGE TABLE PAGES PTP=STOREX PTAD=ST_REALAD ST_USERS=1 EPN=EPN+1 UEPN=UEPN+1 PROC_EPN=EPN PTEPS=256 OLDPTP: ! ROOM IN OLD PAGETABLE PAGE 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 ON INTO A VSCAUSE(4) !----------------------------------------------------------------------- VSCAUSE(4): ! PAGE NOT AVAILABLE %IF EPN>=EPLIM %THEN ->NOPAGES CBTP=SST(VSSEG)+VSEPAGE//MAXBLOCK EPX=VSEPAGE&(MAXBLOCK-1) CBT==CBTA(CBTP) %IF CBT_TAGS&X'20'=0 %THENSTART; ! BLOCK NOT ACTIVE %IF TSTPTR&127=127 %THENSTART; ! SEGMENT NOT ACTIVE %IF ASFREE=0 %THEN FREE AS; ! NO FREE SLOTS *LSS_ASFREE *SHZ_ASP TSTPTR=ASP I=LSTVAD+8*VSSEG INTEGER(I)=INTEGER(I)&X'FFFFFF80'!ASP ASEG(ASP)=VSSEG AS(ASP)=0 ASB=TOPBIT>>ASP ASWIP=ASWIP!ASB; ! INSERT BIT %IF CBT_LINK&SMULTIPLE CON#0 %THEN ASSHR=ASSHR!ASB 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_TAGS&X'80')<<24!CBT_TAGS ! NEWBIT<<31 ! LENGTH ! %IF CBT_TAGS&X'80'#0 %AND LST(VSSEG)>>56&15=0 %THEN %START ! OPMESS(PROC_USER."CONNECT MODE?? CALL PDS") ! OPMESS("DA=".STRHEX(CBT_DA)) ! %FINISH %IF MONLEVEL&12=12 %THENSTART *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH ACTIVE MEM(POUT) %IF MONLEVEL&12=12 %THENSTART *LSS_(5); *IRSB_IT; *IMYD_1; *ST_ %TOS *IAD_(AMIT); *ST_(AMIT) *LSD_(LCIT); *ISB_ %TOS; *ST_(LCIT) *LSS_(6); *IRSB_IC; *IMYD_1; *ST_ %TOS *IAD_(AMIC); *ST_(AMIC) *LSD_(LCIC); *ISB_ %TOS; *ST_(LCIC) AMCALLN=AMCALLN+1 %FINISH %IF POUT_P2<=0 %THEN ->AMTXSW(POUT_P2) CBT_AMTX=POUT_P2 CBT_TAGS=CBT_TAGS&X'7F'!X'20'; ! NO LONGER NEW BUT ACTIVE %FINISH POUT_DEST=X'40001'; ! PAGETURN/PAGE-IN POUT_SRCE=ME!X'8000000A'; ! REPLY TO ACTIVITY 10 POUT_P1=CBT_AMTX<<16!EPX %IF MONLEVEL&2#0 %THEN POUT_P2=VSPARM; ! NOT USED.FOR KMON ONLY %IF MONLEVEL&12=12 %THENSTART *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH PAGETURN(POUT) %IF MONLEVEL&12=12 %THENSTART *LSS_(5); *IRSB_IT; *IMYD_1; *ST_ %TOS *IAD_(PTIT); *ST_(PTIT) *LSD_(LCIT); *ISB_ %TOS; *ST_(LCIT) *LSS_(6); *IRSB_IC; *IMYD_1; *ST_ %TOS *IAD_(PTIC); *ST_(PTIC) *LSD_(LCIC); *ISB_ %TOS; *ST_(LCIC) PTCALLN=PTCALLN+1 %FINISH %IF POUT_DEST#0 %THEN PTE=X'80000001'!POUT_P2 %AND ->ACT10 %IF CBT_LINK&ADVISORY SEQ#0 %OR (VSSEG#PROC_STACK>>18 %AND AS(TSTPTR)<>(64-VSEPAGE)&3=3) %THEN PAGEOUT(VSSEG,VSEPAGE-2,CBT) %ELSE NONSEQVSIS=NONSEQVSIS+1 PROC_STATUS=PROC_STATUS!2; ! DEMAND PAGE PRIORITY ->RETURN !----------------------------------------------------------------------- ACTIVITY(10): ! EPAGE HERE ! P_P1=RUBBISH IDENT ! P_P2=STORE(EPAGE)_REALAD ! VSSEG,VSEPAGE&TSTPTR INTACT !! EPH: PROC_STATUS=PROC_STATUS&X'FFFFFFFD' PTE=X'80000001'!P_P2 ACT10: ! ENTERS HERE IF PAGE NOT TRANFRD ASP=TSTPTR AS(ASP)=AS(ASP)!LTOPBIT>>VSEPAGE ASB=TOPBIT>>ASP ASWAP=ASWAP!ASB ASWIP=ASWIP&(\ASB) EPN=EPN+1 %IF CBT_LINK&SMULTIPLE CON=0 %THEN UEPN=UEPN+1 PROC_EPN=EPN 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 ! THIS HAND CODE 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 %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(0); ! DEPART TO FREE STORE POUT_DEST=X'3000E' POUT_P1=PROCESS PON(POUT) ->RETURN !----------------------------------------------------------------------- AMTXSW(0): ! CHANGE BLOCK SIZE IN SITU ? AMTXSW(-4): ! clears still in progress 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 %IF MONLEVEL&4#0 %THEN LPIT=LPIT+TIMESLICE>>3 ACNT_LTIME=ACNT_LTIME+COM_ITINT*(TIMESLICE>>3) ->ACT %FINISH RTN=RTN+1 %IF RTN=1 %THENSTART PROC_RUNQ=CATTAB(PROC_CATEGORY)_RQTS2 %IF MONLEVEL&1#0 %THEN UPDISP(PROCESS,11,"R".TOSTRING(PROC_RUNQ+'0')) %FINISHELSESTART %IF RTN=RTLIM %THENSTART POUT_DEST=X'3000B'; ! MORE TIME ON THE FLY ? POUT_SRCE=0 POUT_P1=PROCESS POUT_P2=EPN %IF MONLEVEL&4#0 %AND MONVAD>0 %THEN GARNER(7,2<<24!PROC_CATEGORY<<16!EPN) %IF MONLEVEL&12=12 %THENSTART *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH SCHEDULE(POUT) %IF MONLEVEL&12=12 %THENSTART *LSS_(6); *ST_ICC; *LSS_(5); *ST_ITT PERFORM_SERVIT(3)=PERFORM_SERVIT(3)+(IT-ITT) LCIT=LCIT-(IT-ITT) PERFORM_SERVIC(3)=PERFORM_SERVIC(3)+(IC-ICC) LCIC=LCIC-(IC-ICC) PERFORM_SERVN(3)=PERFORM_SERVN(3)+1 %FINISH %IF POUT_P1=0 %THENSTART WORKSET(0) 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 RTN=0 STROBE(0) %IF POUT_P3#0; ! NEWCAT_STROBEI#0 %FINISHELSESTART I=CATTAB(PROC_CATEGORY)_STROBEI %IF I#0 %AND RTN-(RTN//I)*I=0 %THEN STROBE(0) %FINISH %FINISH SSNP1==RECORD(PROC_STACK!X'40000') SSNP1_IT=TIMESLICE %IF MONLEVEL&4#0 %THEN LPIT=LPIT+TIMESLICE ACNT_LTIME=ACNT_LTIME+COM_ITINT*TIMESLICE %IF PROCESS>1 %AND (RUNQ1#0 %OR (PREEMPTED!RUNQ2#0 %AND PROC_RUNQ=2)) %START POUT_DEST=ME!2 ->ONBRUNQA %FINISH ->ACTIVATE; ! START NEXT TSLICE AT ONCE !----------------------------------------------------------------------- ONFRUNQ: ! PUT ON FRONT OF RUNQ POUT_DEST=ME!2 ONFRUNQA: PROC_STATUS=PROC_STATUS!2; ! SET PRIORITY BIT ONBRUNQA: ! TO THE BACK OF RUNQ PON(POUT) ->RETURN !----------------------------------------------------------------------- NOPAGES: ! NO EPAGES FOR PAGEFLT %IF MONLEVEL&4#0 %AND MONVAD>0 %THEN GARNER(7,3<<24!PROC_CATEGORY<<16!EPN) %IF EPLIMACTIVATE %FINISH %FINISH %IF XSTROBE<0 %THENSTART; ! HAD A CHANGE CONTEXT SINCE LAST STROBE STROBE(1) %IF EPNACTIVATE; ! GOT SOME BACK ! %FINISH WORKSET(1) POUT_DEST=X'30003'; ! OUT OF EPAGES POUT_SRCE=ME!1 POUT_P1=PROCESS POUT_P2=RTN; ! TIMESLICES USED SO FAR %IF EPLIM>=MAXEPAGES %AND RTN=0 %AND PROCESS>=FIRST UPROC %THEN DPON(POUT,COM_USERS//10) %ELSE PON(POUT) ->RETURN !----------------------------------------------------------------------- ACTIVITY(7): ! MORE ALLOCATION AVAILABLE !----------------------------------------------------------------------- PROGERRI:*JLK_ %TOS ! PROGRAM ERROR INTERRUPTS ENTER HERE *LSS_ %TOS *ST_I; ! CHECK OLD STACK FOR L-C STACK *LSS_ %TOS *ST_PEPARM ! ! SOME P4 TAKES PHOTO ON PROGERRORS SO CLEAR INHIBIT PHOTOT BIT OR WE ! MAY LOSE THE PHOTO ON SUBSEQUENT M-C FAILURE ! %IF BASICPTYPE=4 %START *LSS_(X'4012'); *AND_X'FEFFFFFF'; *ST_(X'4012') %FINISH LCPE: ! L-C HAS PE OR ILLEAGL VSI %IF I=0 %START; ! I IS OLD STACK NO *ASF_16; ! preserve stack top for diags OPMESS("LOCAL CNTRLR FAILS".STRHEX(PEPARM)) *LSS_(3); *USH_-26; *AND_3; *ST_J OPMESS("OCP".TOSTRING(J+48)." STK ".STRHEX(I)) DUMPTABLE(0,LST(1)&X'0FFFFF80'+X'81000000',72); ! REGS DUMPTABLE(1,INTEGER(X'660')&X'0FFFFF80'+X'81000000',4096) ! PAGE 1 OF LCSTACK PEPARM=22; ! PASS TO DIRECTOR LCERRS=LCERRS+1 %IF LCERRS>3 %THEN ->RETURN %FINISH PE: ! SOFTWARE DETECTED ERRORS JOIN ! 16 = ILLEGAL SYSTEM CALL ! 17 = EXCESS INTRUCTIONS ! 18 = DISC READ FAILS ! 19 = CHANGE BLOCK SIZE ! 20 = H-W ERROR (OCP OR STORE) ! 21 = ILLEGAL OUT ! 22 = LOCAL CONTROLLER FAILS 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 %THENSTART PRINT STRING("PROGRAM ERROR ON SIGNAL STACK CLASS=".STRINT(PEPARM&255)." SUBCLASS=".STRINT(PEPARM>>8&255)." ") ->TERMINATE %FINISH ->SIGACT !----------------------------------------------------------------------- OUTI: *JLK_ %TOS ! LOCAL OUTS ENTER HERE *LSS_ %TOS *ST_J *LSS_ %TOS *ST_OUTN %IF 0<=OUTN<=MAXDIROUT %THENSTART %IF PROC_STACK=LSTKSSN(2)<<18 %AND 1<ILLEGAL OUT ! ALLOWS OUT 0,1,3,6,8,10,14,15 ! 16,19,20,27,28 FROM SIGNAL STACK ->DIROUT(OUTN) %IF INTEGER(J!X'40004')>>20&X'F'<=MAXOUTACR %FINISH ILLEGAL OUT: ! GIVE PROGRAM ERROR OUT ACR CHK PEPARM=21!OUTN<<8 ->PE FREACT: ! REACTIVATE AFTER INVALID OUT ! NB OUT19 USES SIGOUTP! ALLOUTP_DEST=-1 ->ACTIVATE REACT: ! REACTIVATE AFTER VALID OUT ALLOUTP_DEST=0 ->ACTIVATE !----------------------------------------------------------------------- TERMINATE: ! STOP THE PROCESS(EMERGENCY!) J=NEWSTK>>18+1; ! SSN+1 NUMBER J=LST(J)&X'0FFFFF80'; ! ITS REAL ADDRESS PRINTSTRING(PROC_USER." FAILING SSN+1") DUMP TABLE(0,X'81000000'+J,72) ! NEXT 2 LINES ARE TO HELP TONY PRINTSTRING("SEGMENT 5") DUMPTABLE(1,X'81000000'+LST(5)&X'0FFFFF80',72) ! CREATE STOPPING MSGE TO DIRECT ALLOUTP_P1=PROCESS ALLOUTP_P2=PROC_INCAR STRING(ADDR(ALLOUTP_P3))=PROC_USER ASDESTROY=0; ! PRESERVE EVERYTHING DOUT0: ! NORMAL STOPS JOIN HERE DEACTIVATE(\ASFREE) ASDESTROY=0 %IF SEMAHELD#0 %THEN OPMESS("PROC".STRINT(PROCESS)." DIES WITH SEMA") RETURN PTS ALLOUTP_DEST=(LOCSN1+1)<<16!X'17'; ! DIRECT=PROCESS 1 ! X'17' NOT YET PARAMETERISED !!! ALLOUTP_SRCE=(LOCSN1+PROCESS)<<16 PON(ALLOUTP) %IF DAP FITTED=YES %AND PROC_STATUS&2****10#0 %START; ! STILL HAS DAP POUT_DEST=X'1F0009' POUT_SRCE=ME PON(POUT) %FINISH POUT_DEST=X'30008'; ! SCHEDULE/DESTROY POUT_SRCE=ME POUT_P1=PROCESS PON(POUT) ->RETURN !----------------------------------------------------------------------- DIROUT(0): ! DIRECTOR STOPS PROCESS(NORMAL) ASDESTROY=1; ->DOUT0; ! DESTROY ALL (REMAINING) FILES DIROUT(1): ! PRINT STRING FOR DIRECTOR %IF ALLOUTP_DEST>>24>31 %THEN ->FREACT PRINT STRING(STRING(ADDR(ALLOUTP_DEST))) ->REACT !----------------------------------------------------------------------- DIROUT(2): ! INPUT REQUEST MESSAGE %IF ALLOUTP_P3#IOSTAT_IAD %THEN ->ACTIVATE; ! INPUT ALREADY HERE POUT=ALLOUTP 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 ! ALLOUTP_P1=SEG, P2#0 DESTROY VSSEG=ALLOUTP_P1 ->FREACT %UNLESS 0<=VSSEG>32&127 DA=CBTA(SST(VSSEG))_DA J=ACNT_PTURNS %IF TSTPTR#127 %THEN ASOUT(TSTPTR) J=ACNT_PTURNS-J; ! NO OF TRANSFERS STARTED BY DCONNECT ASDESTROY=0 LST(VSSEG)=LST(VSSEG)&X'FFFFFFFF00000000' %IF J=0 %OR PROCESS<=3 %THEN ->REACT POUT_DEST=ME!16 ->ONBRUNQA; ! WILL REENTER AT ACTIVITY(16) ! ! SINCE PROCESSES ARE ARE ALLOWED TO RUN ON AFTER DISCONNECT VERY ! LARGE NUMBERS OF PAGEOUTS AND CLEARS CAN BUILD UP. THIS RUINS RESPONSE ! SO IF THERE ARE A LARGE NUMBER OF CLEARS HOLD THIS PROCESS UNTIL ! PREVIOUS DISCONNECT(WHICH INVOLVED TRANSFERS) HAS COMPLETED ! ACTIVITY(16): ! RE-ENTRY AFTER WAIT FOR CLEARS %IF DCLEARS+PAGEFREES>100 %AND LASTDA#0 %AND CHECKDA(LASTDA)>0 %THEN WAIT(16,1) %AND ->RETURN LASTDA=DA ->REACT !----------------------------------------------------------------------- DIROUT(4): ! reactivate for director ->REACT !----------------------------------------------------------------------- DIROUT(5): ! PON FOR DIRECTOR SRCE=PROCESS+LOCSN1 DIRPONS: ! OTHER PONS JOIN HERE DEST=ALLOUTP_DEST>>16 %IF DEST=X'FFFF' %THENSTART; ! RELAY MESSAGE %IF FIND PROCESS=0 %THEN ->ACTIVATE; ! NOT LOGGED ON %FINISHELSESTART J=DEST; %IF J=63 %THEN J=ALLOUTP_P6>>16 %UNLESS 0<=JFREACT %FINISH %IF DEST#0 %THENSTART I=ALLOUTP_SRCE&X'FFFF' %IF SRCE=LSN3 %AND (I=0 %OR I=X'FFFF') %THEN ->FREACT ALLOUTP_SRCE=SRCE<<16!I PON(ALLOUTP) %FINISH POUT_DEST=ME!12 %IF LOCKST#0 %THEN ->ONBRUNQA; ! FOR EDAR AND TAPES ->ONFRUNQA !----------------------------------------------------------------------- ACTIVITY(12): ! RE-ENTRY AFTER DIRECTOR PON PROC_STATUS=PROC_STATUS&(\2) %IF SRCE>LOCSN3 %THENSTART %IF SERV3_P<<2#0 %THEN ->ASYNCH %FINISHELSESTART SERV==SERVA(SRCE) %IF SERV_P<<2#0 %THEN SUPPOFF(SERV,ALLOUTP) %AND ->ACTIVATE %FINISH SUSPWS: !SUSPEND AWAITING A REPLY ! TRY TO STAY IN STORE IF CORE ! IS PLENTIFUL %IF SNOOZING=YES %THENSTART ->DEPART %IF PROC_STATUS&AMTLOST#0 %IF NONSEQVSIS>1 %OR XSTROBE<0 %THEN STROBE(1) I=UEPN*COM_USERS ->DEPART %UNLESS I0 %THEN GARNER(5,EPN) SUSP=SRCE; ->RETURN %FINISH %FINISH ACTIVITY(8): DEPART: ! suspended but must now go %IF MONLEVEL&4#0 %AND MONVAD>0 %THEN GARNER(7,1<<24!PROC_CATEGORY<<16!EPN) WORKSET(1) 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 POUT_P5=EPN POUT_P6=PROC_CATEGORY 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,ALLOUTP) SUSP=0 ->ACTIVATE !----------------------------------------------------------------------- DIROUT(6): ! PON & CONTINUE SRCE=PROCESS+LOCSN1 DIRPONC: ! OTHER PONS JOIN HERE DEST=ALLOUTP_DEST>>16 %IF DEST=X'FFFF' %THENSTART %IF FIND PROCESS=0 %THEN ->ACTIVATE %FINISHELSESTART J=DEST; %IF J=63 %THEN J=ALLOUTP_P6>>16 %UNLESS 0<=JFREACT %FINISH %IF DEST#0 %THENSTART; ! DEST#0 PON &CONTINUE I=ALLOUTP_SRCE&X'FFFF' %IF SRCE=LSN3 %AND (I=0 %OR I=X'FFFF') %THEN ->FREACT ALLOUTP_SRCE=SRCE<<16!I PON(ALLOUTP) ->ACTIVATE; ! PDS THINKS THIS WILL BE BETTER ! THAN THE ORIGINAL LINE ->ONFRUNQ %FINISH ! DEST=0 TOFF & CONTINUE %IF SRCE>LOCSN3 %THENSTART %IF SERV3_P<<2#0 %THEN ->ASYNCH ALLOUTP_DEST=0 %FINISHELSESTART SERV==SERVA(SRCE) %IF SERV_P<<2#0 %THEN SUPPOFF(SERV,ALLOUTP) %ELSE ALLOUTP_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 IN STORE PONWAIT: DEST=ALLOUTP_DEST>>16 %UNLESS 0FREACT SRCE=ALLOUTP_SRCE ALLOUTP_SRCE=ME!13 PON(ALLOUTP) J=PROC_RUNQ; PROC_RUNQ=1 %IF MULTIOCP=YES %THENSTART *INCT_SCHEDSEMA *JCC_8, SEMALOOP(SCHEDSEMA,0) SSEMAGOT1: %FINISH MPLEVEL=MPLEVEL-1; ! DECREASE MPLEVEL&CHECK DEADLOCKS %IF PAGEFREES<=2 %AND 0=MPLEVEL-1 %THEN P_DEST=X'20000' %AND PON(P) %IF MULTIOCP=YES %START; *TDEC_SCHEDSEMA; %FINISH ->RETURN; ! WAIT IN STORE FOR REPLY !----------------------------------------------------------------------- ACTIVITY(13): ! REPLY TO PON & WAIT IN STORE %IF MULTIOCP=YES %THENSTART *INCT_SCHEDSEMA *JCC_8, SEMALOOP(SCHEDSEMA,0) SSEMAGOT2: %FINISH MPLEVEL=MPLEVEL+1 PROC_RUNQ=J %IF MULTIOCP=YES %START; *TDEC_SCHEDSEMA; %FINISH ALLOUTP=P ALLOUTP_DEST=SRCE %IF PROCESS>=FIRST UPROC %START I=PROC_STACK+X'40014' INTEGER(I)=(INTEGER(I)-OUT18CHARGE)&X'1FFFFFF' INTEGER(I+4)=(INTEGER(I+4)-OUT18INS)&X'1FFFFFF' %FINISH ->ACT !----------------------------------------------------------------------- DIROUT(12): ! NOMINATE STACK SSN I=ALLOUTP_P1; ! STACK NO J=ALLOUTP_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=ALLOUTP_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 DIROUT(19): ! SWOP STACK FROM SIGNAL STACK I=ALLOUTP_P1; ! NEW LOCAL STACK NO K=ALLOUTP_P2 %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 SSNP1_PSR&3=0 %THEN ->FREACT NEWSTK=J<<18 ! MOVE IT & IC TO NEW STACK LONG INTEGER(NEWSTK!X'40014')=LONG INTEGER(PROC_STACK!X'40014') PROC_STACK=NEWSTK SUSP=K; ! GO BACK TO CORRECT SUSPEND STATUS %IF PROC_STACK=LSTKSSN(2)<<18 %THEN ALLOUTP==SIGOUTP %ELSE ALLOUTP==DIROUTP ->RESUSP !----------------------------------------------------------------------- DIROUT(15): ! SYSTEM CALL ERROR ! (AFTER STACK SWITCH) J=INTEGER(PROC_STACK!X'40020')>>2; ! sub-ident. in old XNB OPMESS(PROC_USER." bad syscall:".STRINT(J)) PEPARM=J<<8!16 ->PE !----------------------------------------------------------------------- DIROUT(16): ! INSTRUCTION COUNTER INTERRUPT ! (AFTER STACK SWITCH) PEPARM=17; ! TREAT AS PROGRAM ERROR ->PE !----------------------------------------------------------------------- DIROUT(17): ! CHECK ACTIVE BLOCKS ON DESTROY J=0 %CYCLE I=0,1,7 RECHECK: K=INTEGER(DIROUTPAD+4*I) %IF K=0 %THENEXIT K=CHECKDA(K) %IF K#0 %THENSTART %IF K<0 %AND J>0 %THEN OPMESS("? BLK ACTIVTY ".STRHEX(INTEGER(DIROUTPAD+4*I))) %AND ->FREACT ! ! CAN BE A RACE CONDITIONS BETWEEN PONS ON STOPPING A PROCESS. SO ! IF AMT BLOCK STILL HAS USERS WAIT JUST ONCE TO CLEAR ANY BACKLOG ! OF PONNED DEALLOCATES. CONDITION SEEN ON A DUAL SUSPECTED AT KENT ! %IF J=10 %THEN OPMESS("BLOCK PAGE-OUTS ?") %AND ->FREACT WAIT(14,PAGEOUT DELAY(J)) ->RETURN %FINISH %REPEAT ->REACT !----------------------------------------------------------------------- ACTIVITY(14): ! REPLY FROM DESTROY CHECK J=J+1 ->RECHECK !----------------------------------------------------------------------- DIROUT(18): ! CHECK & FORWARD I-O REQUEST ! P5=WRIT<<31!ACR<<24!LEN ! P6=ADDRESS %IF CHECK RES(ALLOUTP_P5>>31,ALLOUTP_P5&X'FFFFFF',ALLOUTP_P6)#0 %THEN ->FREACT; ! NOT RESIDENT ALLOUTP_P5=PROC_ACTW0!ALLOUTP_P5<<4>>28; ! LSTBR!ACR ALLOUTP_P6=PROC_LSTAD ->PONWAIT !------------------------------------------------------------------- !----------------------------------------------------------------------- DIROUT(20): ! PROCMON ENABLE %IF MONLEVEL&4#0 %START; ! ENABLE INPROCESS MONITORING MONVAD=ALLOUTP_P1 ->REACT %IF MONVAD<=0 MONVAD=0 %AND ->FREACT %UNLESS CHECKRES(0,4096,MONVAD)=0 ->FREACT %IF LOCKST=0 MONLIM=MONVAD+INTEGER(MONVAD+8) MONPTAD=INTEGER(LOCKST&X'0FFFFFF0'+VIRTAD+8*(MONVAD>>18)+4)&X'0FFFFFF0'+VIRTAD %FOR I=0,1,(INTEGER(MONVAD+8)-1)>>10 %CYCLE ->FREACT %IF INTEGER(MONPTAD+4*I)&1=0 %REPEAT ->REACT %FINISH DIROUT(21): ! DISABLE PROCMON DIROUT(22): ! PROCMON ON DIROUT(23): ! PROCMON OFF ->FREACT DIROUT(24): ! SPECIAL FOR REQUEST OUTPUT SRCE=PROCESS+LOCSN2 ->DIRPONS %UNLESS ALLOUTP_DEST=X'370007' ALLOUTP_SRCE=X'80000000'!SRCE<<16 %IF MONLEVEL&12=12 %START *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH COMMS CONTROL(ALLOUTP) %IF MONLEVEL&12=12 %START *LSS_(6); *ST_ICC; *LSS_(5); *ST_ITT PERFORM_SERVIT(55)=PERFORM_SERVIT(55)+(IT-ITT) LCIT=LCIT-(IT-ITT) PERFORM_SERVIC(55)=PERFORM_SERVIC(55)+(IC-ICC) LCIC=LCIC-(IC-ICC) PERFORM_SERVN(55)=PERFORM_SERVN(55)+1 %FINISH ->ACTIVATE DIROUT(25): ! LOCK IO AREA AND RETURN ST ADDR ! P_P5/P_P6=DESCR TO AREA. ALLOUTP_P5=ALLOUTP_P5&X'FFFFFF'; ! P_P1=1 LOCK ,=-1 UNLOCK %IF ALLOUTP_P1>0 %AND CHECK RES(0,ALLOUTP_P5,ALLOUTP_P6)#0 %THEN ->FREACT %IF LOCKST=0 %THENSTART; ! NO SEG TABLE AROUND ->FREACT %UNLESS ALLOUTP_P1>0 %IF MULTIOCP=YES %THENSTART *INCT_(STORESEMA) *JCC_8, SEMALOOP(STORESEMA,0) SSEMAGOT3: %FINISH %IF FREE EPAGES>0 %THENSTART STOREX=QUICK EPAGE(0,-1) %IF MULTIOCP=YES %START; *TDEC_(STORESEMA); %FINISH ->ACTF %FINISH POUT_SRCE=ME!X'F' POUT_P2=0; ! CLEAR TO ZERO GET EPN=GET EPN+1 %IF MULTIOCP=YES %START; *TDEC_(STORESEMA); %FINISH %IF PAGEFREES<=1 %AND GETEPN>=MPLEVEL+1-COM_NOCPS %THEN POUT_DEST=X'20000' %AND PON(P) POUT_DEST=X'50000' PON(POUT) ->RETURN !----------------------------------------------------------------------- ACTIVITY(15): ! REPLY FROM GET EPAGE ! WITH PAGE FOR LOCKED SEG TABLE STOREX=P_P2 %IF STOREX=0 %THEN ALLOUTP_DEST=-1 %AND ->DEAD ! DEADLOCK PAGE. DIR WILLTRY AGN ACTF: LOCKSTX=STOREX LOCKST=STORE(STOREX)_REALAD&X'0FFFFFFF'; ! COULD BE FLAWED 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 %FINISHELSE K=LOCKST&X'0FFFFFF0'+VIRTAD VSSEG=ALLOUTP_P6>>18 %IF ALLOUTP_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'EFFFFF8080000001'!(LTAD-VIRTAD) %FINISHELSESTART; ! 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_DEST=X'60000' POUT_P2=LOCKSTX P_SRCE=ME!15 %IF MONLEVEL&12=12 %THENSTART *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH RETURN EPAGE(POUT) %IF MONLEVEL&12=12 %THENSTART *LSS_(5); *IRSB_IT; *IMYD_1; *ST_ %TOS *IAD_(RETIT); *ST_(RETIT) *LSD_(LCIT); *ISB_ %TOS; *ST_(LCIT) *LSS_(6); *IRSB_IC; *IMYD_1; *ST_ %TOS *IAD_(RETIC); *ST_(RETIC) *LSD_(LCIC); *ISB_ %TOS; *ST_(LCIC) RETCALLN=RETCALLN+1 %FINISH LOCKST=0 %FINISH %FINISH PT==ARRAY(VIRTAD+LST(VSSEG)&X'0FFFFFF8',PTF) J=ALLOUTP_P6-VSSEG<<18 %CYCLE I=J>>10,1,(J+ALLOUTP_P5-1)>>10 %IF ALLOUTP_P1>0 %THEN K=PT(I) %ELSE K=0 INTEGER(LTAD+4*I)=K %REPEAT %CYCLE VSEPAGE=J>>EPAGESHIFT,1,(J+ALLOUTP_P5-1)>>EPAGESHIFT CBTP=SST(VSSEG)+VSEPAGE//MAXBLOCK EPX=VSEPAGE&(MAXBLOCK-1) CBT==CBTA(CBTP) %IF CBT_AMTX=0 %THEN ->FREACT %IF ALLOUTP_P1>0 %START POUT_DEST=X'40001'; ! PAGE IN AGAIN TO LOCK POUT_SRCE=ME!X'8000000A' POUT_P3=0 %FINISHELSESTART 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 %IF MONLEVEL&12=12 %THENSTART *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH PAGETURN(POUT) %IF MONLEVEL&12=12 %THENSTART *LSS_(5); *IRSB_IT; *IMYD_1; *ST_ %TOS *IAD_(PTIT); *ST_(PTIT) *LSD_(LCIT); *ISB_ %TOS; *ST_(LCIT) *LSS_(6); *IRSB_IC; *IMYD_1; *ST_ %TOS *IAD_(PTIC); *ST_(PTIC) *LSD_(LCIC); *ISB_ %TOS; *ST_(LCIC) PTCALLN=PTCALLN+1 %FINISH %IF POUT_DEST=0 %AND ALLOUTP_P1>0 %THEN MONITOR("LOCK GOES WRONG?") %REPEAT ALLOUTP_P5=PROC_ACTW0 ALLOUTP_P6=LOCKST&X'0FFFFFF0' ->REACT !----------------------------------------------------------------------- DIROUT(26): ! CHANGE CONTEXT CLEAR ACCESSED BITS %IF MONLEVEL&4#0 %AND MONVAD>0 %THEN GARNER(6,EPN) XSTROBE=XSTROBE!X'80000000'; ! NOTE CHANGED CONTEXT ->ACTIVATE DIROUT(27): ! EXIT TO NOMINATED ENV(SAME STK) ! ALLOUTP_P1-5==LNB->SF K=PROC_STACK ->FREACT %UNLESS K=ALLOUTP_P1>>18<<18=ALLOUTP_P5>>18<<18 K=K+X'40000' %CYCLE I=0,4,16 INTEGER(K+I)=INTEGER(ADDR(ALLOUTP)+8+I) %REPEAT ->ACTIVATE !----------------------------------------------------------------------- DIROUT(28): ! HARD STORE ERROR IN PROCESS ! FROM ROUTINE SYSERR ACTIVITY(4): ! L-C HAS CRASHED ONE OCP IN DUAL ! FROM MULTIPROCESSOR INT ROUTINE PEPARM=20 ->PE !----------------------------------------------------------------------- ICOUNTERI:*JLK_ %TOS ! INSTRUCTION COUNTER INTERRUPTS ! 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 CHECKDA(%INTEGER DA) !*********************************************************************** !* CHECKS A DISC ADDRESSAND REPLIES AS FOLLOWS * !* RESULT=0 ADDRESS NOT ACTIVE * !* RESULT=1 TRANSFERS OR CLEARS IN PROGRESS * !* RESULT<0 OTHER USERS OF SAME * !*********************************************************************** %RECORD (PARMF) POUT POUT_DEST=X'80005' POUT_P1=DA %IF MONLEVEL&12=12 %THENSTART *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH ACTIVE MEM(POUT) %IF MONLEVEL&12=12 %THENSTART *LSS_(5); *IRSB_IT; *IMYD_1; *ST_ %TOS *IAD_(AMIT); *ST_(AMIT) *LSD_(LCIT); *ISB_ %TOS; *ST_(LCIT) *LSS_(6); *IRSB_IC; *IMYD_1; *ST_ %TOS *IAD_(AMIC); *ST_(AMIC) *LSD_(LCIC); *ISB_ %TOS; *ST_(LCIC) AMCALLN=AMCALLN+1 %FINISH %RESULT=POUT_DEST %END %INTEGERFN CHECK RES(%INTEGER WRIT,LEN,AD) !*********************************************************************** !* CHECKS THAT THE AREA OF LEN AT AD IS LOCKED DOWN AND ORS WRIT * !* INTO THE WRITE MARKER IN THE PAGE TABLES * !* RESULT=0 AREA LOCKED DOWN * !* RESULT#0 SOME OF THE AREA IS NOT RESIDENT * !*********************************************************************** %INTEGER I,J %INTEGERARRAYNAME PT %CYCLE I=AD>>10,1,(AD+LEN-1)>>10; ! THROUGH THE EPAGES PT==ARRAY(VIRTAD+(LST(I>>8)&X'0FFFFFF8'),PTF) J=I&X'FF' %IF PT(J)&1=0 %THENRESULT=1 PT(J)=PT(J)!WRIT<<28 %REPEAT %RESULT=0 %END !----------------------------------------------------------------------- %ROUTINE PAGEOUT(%INTEGER VSSEG,VSEPAGE, %RECORD (CBTF) %NAME CBT) !*********************************************************************** !* PAGES OUT A PAGE AS A RESULT OF WORKING ON A SEQUENTIAL FILE * !* NOTE PAGE<0 IS VALID INDICATING PREVIOUS SEGMENT(MUST CHECK!) * !*********************************************************************** %RECORD (PARMF) P %INTEGER I,ASP %LONGINTEGER L %IF VSEPAGE<0 %THENSTART; ! PREVIOUS SEGMENT %IF CBT_LINK&CONTINUATN BLK=0 %THENRETURN VSSEG=VSSEG-1 VSEPAGE=VSEPAGE+SEGEPSIZE %FINISH L=LST(VSSEG) ASP=L>>32&127 %IF ASP#127 %AND AS(ASP)&(LTOPBIT>>VSEPAGE)#0 %START; ! PAGE IN STORE I=VIRTAD+L&X'0FFFFFF8'+VSEPAGE*16 *LXN_I *LSS_(%XNB +0); *OR_(%XNB +1) *OR_(%XNB +2); *OR_(%XNB +3) *ST_I; *LSQ_0; *ST_(%XNB +0); ! CLEAR PT AFTER NOTING MARKERS I=I<<3>>31<<3 ! IF DEDUCED RATHER THAN ADVISED ! SEQUENTIAL MAKE PAGE RECAP ! DEDUCTION SOMETIME WRONG! %IF CBT_LINK&(CONTINUATN BLK!ADVISORY SEQ)=0 %THEN I=I!5 %IF CBT_LINK&SMULTIPLE CON#0 %THEN I=I!5 CBT==CBTA(SST(VSSEG)+VSEPAGE//MAXBLOCK) P_DEST=X'40002'; ! PAGETURN/PAGE-OUT P_P1=CBT_AMTX<<16!(VSEPAGE&(MAXBLOCK-1)) %IF SFC FITTED=YES %AND RESIDENCES>MIN RESIDENCES+1 %THEN I=I!4; ! TO DRUM IF THERE IS ONE P_P2=I %IF MONLEVEL&4#0 %AND MONVAD>0 %THEN GARNER(3+I>>3,VSSEG<<18!VSEPAGE<<12) %IF MONLEVEL&12=12 %THENSTART *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH PAGETURN(P) %IF MONLEVEL&12=12 %THENSTART *LSS_(5); *IRSB_IT; *IMYD_1; *ST_ %TOS *IAD_(PTIT); *ST_(PTIT) *LSD_(LCIT); *ISB_ %TOS; *ST_(LCIT) *LSS_(6); *IRSB_IC; *IMYD_1; *ST_ %TOS *IAD_(PTIC); *ST_(PTIC) *LSD_(LCIC); *ISB_ %TOS; *ST_(LCIC) PTCALLN=PTCALLN+1 %FINISH %IF I&8#0 %THEN ACNT_PTURNS=ACNT_PTURNS+1 %IF CBT_LINK&SMULTIPLE CON=0 %THEN UEPN=UEPN-1 EPN=EPN-1 %IF EPN>0 %THEN PROC_EPN=EPN AS(ASP)=AS(ASP)!!(LTOPBIT>>VSEPAGE) %IF MONLEVEL&16#0 %START I=PROC_CATEGORY SEQOUT(I)=SEQOUT(I)+1 %FINISH %FINISH %END %ROUTINE ASOUT(%INTEGER ASP) !*********************************************************************** !* DISCARD ONE SEGMENT (INDEXED BY ASP) FROM ACTIVE STORAGE. * !* MAY INVOLVE WRITING PAGES OUT FROM STORE AND WILL INVOLVE * !* RETURNING ANY AMTXS ALLOCATED * !*********************************************************************** %RECORD (CBTF) %NAME CBT !%INTEGERARRAYNAME PT; ! NOT USED IN HAND CODING %INTEGER MARK,VSSEG,VSEPAGE,SH,CBTP,PBLENS,ASB,POFL,I,PTAD,LASTEP %LONGINTEGER MASK VSSEG=ASEG(ASP) %IF ASDESTROY#0 %AND 16<=VSSEG<=31 %THEN %C ASDESTROY=0 %AND OPMESS("INDEX DESTROY BY PROC".STRINT(PROCESS).TOSTRING(17)) LASTEP=(LST(VSSEG)>>(32+EPAGESHIFT))&(SEGEPSIZE-1) %IF AS(ASP)=0 %THEN ->NOP MASK=AS(ASP) AS(ASP)=0 PTAD=VIRTAD+LST(VSSEG)&X'0FFFFFF8' ! PT==ARRAY(PTAD,PTF) CBTP=SST(VSSEG) CBT==CBTA(CBTP) PBLENS=MAXBLOCK VSEPAGE=-1 %WHILE MASK#0 %CYCLE *LSD_MASK; *SHZ_SH; *USH_1; *ST_MASK VSEPAGE=VSEPAGE+SH+1 %IF VSEPAGE>=PBLENS %START PBLENS=PBLENS+MAXBLOCK CBTP=CBTP+1 CBT==CBTA(CBTP) %FINISH ! 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 ! THIS HANDCODING ASSUMES EPAGESIZE=4 ! I=PTAD+4*EPAGESIZE*VSEPAGE *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 ! NOTE:- DRUM NOT UPDATED POUT_DEST=X'40002'; ! PAGETURN/PAGE-OUT POUT_P1=CBT_AMTX<<16!(VSEPAGE&(MAXBLOCK-1)) POUT_P2=POFL ! %IF CBT_AMTX=0 %OR CBT_TAGS&X'20'=0 %THEN %C OPMESS("CBT STATE ??") %AND %CONTINUE;! SHOULD NOT HAPPEN %IF MONLEVEL&4#0 %AND MONVAD>0 %THEN GARNER(1+POFL>>3,VSSEG<<18!VSEPAGE<<12) %IF MONLEVEL&12=12 %THENSTART *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH PAGETURN(POUT) %IF MONLEVEL&12=12 %THENSTART *LSS_(5); *IRSB_IT; *IMYD_1; *ST_ %TOS *IAD_(PTIT); *ST_(PTIT) *LSD_(LCIT); *ISB_ %TOS; *ST_(LCIT) *LSS_(6); *IRSB_IC; *IMYD_1; *ST_ %TOS *IAD_(PTIC); *ST_(PTIC) *LSD_(LCIC); *ISB_ %TOS; *ST_(LCIC) PTCALLN=PTCALLN+1 %FINISH %IF POFL&8#0 %THEN ACNT_PTURNS=ACNT_PTURNS+1 EPN=EPN-1 %IF CBT_LINK&SMULTIPLE CON=0 %THEN UEPN=UEPN-1 %REPEAT %IF EPN>0 %THEN PROC_EPN=EPN NOP: CBTP=SST(VSSEG) CBT==CBTA(CBTP) %CYCLE %IF CBT_TAGS&X'20'#0 %THENSTART POUT_DEST=X'80002'; ! RETURN AMTX POUT_SRCE=0 POUT_P1=PROCESS POUT_P2=CBT_AMTX POUT_P3=ASDESTROY; ! DESTROY FLAG %IF MONLEVEL&12=12 %THENSTART *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH ACTIVE MEM(POUT) %IF MONLEVEL&12=12 %THENSTART *LSS_(5); *IRSB_IT; *IMYD_1; *ST_ %TOS *IAD_(AMIT); *ST_(AMIT) *LSD_(LCIT); *ISB_ %TOS; *ST_(LCIT) *LSS_(6); *IRSB_IC; *IMYD_1; *ST_ %TOS *IAD_(AMIC); *ST_(AMIC) *LSD_(LCIC); *ISB_ %TOS; *ST_(LCIC) AMCALLN=AMCALLN+1 %FINISH CBT_AMTX=0; ! NEW BITS CBT_TAGS=CBT_TAGS&X'DF' ACNT_PTURNS=ACNT_PTURNS+POUT_P6; ! CHARGE FOR ANY CLEARS %FINISH %IF LASTEP>ASP ASWAP=ASWAP&(\ASB) ASWIP=ASWIP&(\ASB) ASSHR=ASSHR&(\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(%INTEGER SFLAGS) !*********************************************************************** !* 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 * !* 2**0 OF SFLAGS SET FOR NOT CLEARING PT USE BITS * !* 2**1 OF SFLAGS NOT USED * !*********************************************************************** %RECORD (CBTF) %NAME CBT !%INTEGERARRAYNAME PT; ! NOT USED IN HANDCODING ! %CONSTINTEGER USEMASK=X'DFFFFFFF' %CONSTLONGINTEGER DUSEMASK=X'DFFFFFFFDFFFFFFF' %INTEGER MARK,POFL,ASMASK,ASP,VSSEG,VSEPAGE,PTB,CBTP,PBLENS,ASB,PTEAD,I %IF MONLEVEL&16#0 %THENSTART %INTEGER CAT %FINISH %LONGINTEGER EPMASK ASMASK=ASWAP; ! ALL SLOTS WITH ACTIVE PAGES ASP=-1 %IF MONLEVEL&16#0 %THENSTART CAT=PROC_CATEGORY STROBEN(CAT)=STROBEN(CAT)+1 STREPN(CAT)=STREPN(CAT)+EPN %FINISH %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) CBTP=SST(VSSEG) CBT==CBTA(CBTP) %IF CBT_LINK&ADVISORY SEQ#0 %THENCONTINUE PBLENS=MAXBLOCK 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 %IF VSEPAGE>=PBLENS %START PBLENS=PBLENS+MAXBLOCK CBTP=CBTP+1 CBT==CBTA(CBTP) %FINISH ! PAGE=EPAGE*EPAGESIZE ! MARK=0 ! %CYCLE I=PAGE,1,PAGE+EPAGESIZE-1 ! MARK=MARK!PT(I); ! GANG MARKERS TOGETHER ! PT(I)=PT(I)&USEMASK %IF SFLAGS&1=0 ! %REPEAT ! ! THIS HAND CODE ASSUMES THAT EPAGESIZE IS 4 ! PTEAD=PTB+4*EPAGESIZE*VSEPAGE *LXN_PTEAD *LSD_(%XNB +0); *OR_(%XNB +2) *STUH_ %B; *OR_ %B *ST_MARK %IF SFLAGS&1=0 %START *LSD_(%XNB +0); *AND_DUSEMASK; *ST_(%XNB +0) *LSD_(%XNB +2); *AND_DUSEMASK; *ST_(%XNB +2) %FINISH POFL=MARK<<3>>31<<3!(1<<2!1); ! WRIT,UPDATE DRUM&RECAPTURE %IF MARK>>29&1=0 %START ! STROBE OUT NON USED AS(ASP)=AS(ASP)&(\(LTOPBIT>>VSEPAGE)) %IF MONLEVEL&16#0 %THEN STROUT(CAT)=STROUT(CAT)+1 POUT_DEST=X'40002'; ! PAGETURN/PAGE-OUT POUT_P1=CBT_AMTX<<16!(VSEPAGE&(MAXBLOCK-1)) POUT_P2=POFL %IF MONLEVEL&4#0 %AND MONVAD>0 %THEN GARNER(3+POFL>>3,VSSEG<<18!VSEPAGE<<12) %IF MONLEVEL&12=12 %THENSTART *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH PAGETURN(POUT) %IF MONLEVEL&12=12 %THENSTART *LSS_(5); *IRSB_IT; *IMYD_1; *ST_ %TOS *IAD_(PTIT); *ST_(PTIT) *LSD_(LCIT); *ISB_ %TOS; *ST_(LCIT) *LSS_(6); *IRSB_IC; *IMYD_1; *ST_ %TOS *IAD_(PTIC); *ST_(PTIC) *LSD_(LCIC); *ISB_ %TOS; *ST_(LCIC) PTCALLN=PTCALLN+1 %FINISH %IF POFL&8#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 %IF CBT_LINK&SMULTIPLE CON=0 %THEN UEPN=UEPN-1 %FINISH %REPEAT %IF AS(ASP)=0 %THENSTART ASB=TOPBIT>>ASP ASWAP=ASWAP&(\ASB) ASWIP=ASWIP!ASB %FINISH %REPEAT %IF EPN>0 %THEN PROC_EPN=EPN XSTROBE=XSTROBE&X'FFFF'+1; ! LOSE CHNGE CONTEXT BIT IF SET %END !----------------------------------------------------------------------- %ROUTINE WORKSET(%INTEGER RECAP) !*********************************************************************** !* PAGE OUT THE WORKING SET BY GOING THROUGH THE ACTIVE SEGMENT * !* LIST AND WRITING OUT ACTIVE EPAGES IN THAT SEGMENT * !*********************************************************************** %RECORD (CBTF) %NAME CBT !%INTEGERARRAYNAME PT; ! NEEDED IN ALL IMP VERSION ONLY %INTEGER MARK,POFL,ASMASK,VSSEG,VSEPAGE,ASP,CBTP,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) CBTP=SST(VSSEG) CBT==CBTA(CBTP) PBLENS=MAXBLOCK EPMASK=AS(ASP) AS(ASP)=0 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 %IF VSEPAGE>=PBLENS %START PBLENS=PBLENS+MAXBLOCK CBTP=CBTP+1 CBT==CBTA(CBTP) %FINISH ! 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+4*EPAGESIZE*VSEPAGE *LXN_I *LSD_(%XNB +0); *OR_(%XNB +2) *STUH_ %B; *OR_ %B *ST_MARK POFL=MARK<<3>>31<<3!1<<2!RECAP; ! WRIT & UPDATE DRUM & RECAPTURE POUT_DEST=X'40002'; ! PAGETURN/PAGE-OUT POUT_P1=CBT_AMTX<<16!(VSEPAGE&(MAXBLOCK-1)) POUT_P2=POFL %IF MONLEVEL&4#0 %AND MONVAD>0 %THEN GARNER(1+POFL>>3,VSSEG<<18!VSEPAGE<<12) %IF MONLEVEL&12=12 %THENSTART *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH PAGETURN(POUT) %IF MONLEVEL&12=12 %THENSTART *LSS_(5); *IRSB_IT; *IMYD_1; *ST_ %TOS *IAD_(PTIT); *ST_(PTIT) *LSD_(LCIT); *ISB_ %TOS; *ST_(LCIT) *LSS_(6); *IRSB_IC; *IMYD_1; *ST_ %TOS *IAD_(PTIC); *ST_(PTIC) *LSD_(LCIC); *ISB_ %TOS; *ST_(LCIC) PTCALLN=PTCALLN+1 %FINISH %IF POFL&8#0 %THEN ACNT_PTURNS=ACNT_PTURNS+1 %IF MARK&(1<<29)=0 %THENSTART EPN=EPN-1 %IF CBT_LINK&SMULTIPLE CON=0 %THEN UEPN=UEPN-1 %FINISH %REPEAT %REPEAT %IF EPN>0 %THEN PROC_EPN=EPN ASWAP=0 ! ! SHUFFLE DOWN LIST OF OLD ASWIPS AND REMOVE ANY SEGMENTS NOT USED OVER ! "RESIDENCES" RESIDENCES PERIODS FROM ACTIVE LIST ! J=ASWIP&(\ASSHR); ! ONLY PRIVATE SEGMENTS %CYCLE I=MAXRESIDENCES-1,-1,0 J=J&OLD ASWIPS(I) %IF I0 %THEN LST(I)=LST(I)&X'FFFFFFFF00000000' %REPEAT %FINISHELSESTART ! %CYCLE I=2,1,HIGHSEG ! LST(I)=LST(I)&X'FFFFFFFF00000000' ! %REPEAT *LD_X'2800000100000014' *LSS_0 *LB_HIGHSEG *SBB_1 RPA: *ST_(%DR ) *INCA_8 *DEBJ_ %FINISH RETURN PTS %END !----------------------------------------------------------------------- %IF MONLEVEL&4#0 %START %ROUTINE GARNER(%INTEGER FLAG, %INTEGER PARAM) !*********************************************************************** !* COLLECT PAGING MONITORING. A DOUBLE WORD OF FLAG<<28!ICCOUNT * !* FOLLOWED BY 32BIT PARAM(NORMALLY VIRTUAL ADDRESS) IS * !* WRITTEN INTO LOCKED DOWN FILE * !* FLAG=0 FOR DEMAND PAGE * !* FLAG=1&2 FOR PAGEOUTS & UPDATED PAGEOUTS * !* FLAG=3&4 FOR STROBEOUTS & UPDATED STROBEOUTS * !* FLAG=5 FOR A SNOOZE PARAM=EPN * !* FLAG=6 FOR A CHANGE CONTEXT REQUEST. PARAM=EPN * !*********************************************************************** %INTEGER AD,W1,PVAD0,PVAD1 PVAD0=INTEGER(MONPTAD)&X'0FFFFFF0'+VIRTAD; ! PUBLIC VIRTUAL AD OF P0 AD=MONVAD+INTEGER(PVAD0); ! CURRENT POSN W1=FLAG<<28!(ICREVS&15)<<24!INTEGER(PROC_STACK!X'40018') %IF AD>10&255))&X'0FFFFFF0'+VIRTAD+AD&X'3FF' INTEGER(PVAD1)=W1 INTEGER(PVAD1+4)=PARAM INTEGER(PVAD0)=INTEGER(PVAD0)+8 %FINISH %END %FINISH %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'DFFFFFFFDFFFFFFF' %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+4*EPAGESIZE*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 FREE AS !*********************************************************************** !* CALLED WHEN ASFREE IS ZERO. IT DEACTIVATES A SEGMENT. FIRST * !* TRY TO DEACTIVATE THE OLDEST CURRENTLY INACTIVE SEGMENT. * !* IF ALL SEGMENTS ARE ACTIVE ONE IS CHOSEN AT RANDOM * !*********************************************************************** %INTEGER I,J,K %IF ASWIP=0 %THENSTART *RRTC_0; *AND_31; ! USE BOTTOM 5 BITS OF CLOCK *ST_I; ! AS PSEUDO RANDOM NO I=1<>18 %CYCLE I=1,1,LSTKN %IF J=LSTKSSN(I) %THENRESULT=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 * !*********************************************************************** %EXTERNALINTEGERFN REQUEST INPUT(%INTEGER OUTPUT POSN,TRIGGER POSN) %UNLESS IOSTAT_OUTBUFLEN>0 %AND 0<=OUTPUT POSN0 %AND %C 0<=TRIGGER POSN0 %AND 0<=OUTPUT POSN