! ! TO MAKE S SERIES SUPERVISOR REQUIRES:- ! 1) CHANGE SSERIES=NO TO SSERIES=YES IN CTOPTIONS FILE ! 2) REPLACE COMF BY S SERIES COM IN ERCC08.COMSF ! ! ! 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, %C %INTEGER INBUFLEN,OUTBUFLEN,INSTREAM,OUTSTREAM) %RECORDFORMAT PARMF(%INTEGER DEST,SRCE,(%INTEGER P1,P2,P3,P4,P5,P6%C %OR %STRING(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 CALL ! 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="27I" ! 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 ! 2) CHANGES TO SPECS FOR SYSTEM CALLED ROUTINES TO DEFEAT ! OPTIMISING EFFORTS OF LATEST IMP80! ! ! ! %CONSTSTRING(3) CHOPID="21A"; ! EARLIEST COMPATABLE CHOPSUPE !----------------------------------------------------------------------- !* COMMUNICATIONS RECORD FORMAT - EXTANT FROM CHOPSUPE 21B ONWARDS * %RECORDFORMAT COMF(%INTEGER OCPTYPE,IPLDEV,SBLKS,SEPGS,NDISCS, %C DLVNADDR,GPCTABSIZE,GPCA,SFCTABSIZE,SFCA,SFCK,DIRSITE, %C DCODEDA,SUPLVN,TOJDAY,DATE0,DATE1,DATE2, %C TIME0,TIME1,TIME2,EPAGESIZE,USERS,CATTAD,SERVAAD, %C %BYTEINTEGER NSACS,RESV1,SACPORT1,SACPORT0, %C NOCPS,RESV2,OCPPORT1,OCPPORT0, %C %INTEGER ITINT,CONTYPEA,GPCCONFA,FPCCONFA,SFCCONFA, %C BLKADDR,RATION,SMACS,TRANS,%LONGINTEGER KMON, %C %INTEGER DITADDR,SMACPOS,SUPVSN,PSTVA,SECSFRMN,SECSTOCD, %C SYNC1DEST,SYNC2DEST,ASYNCDEST,MAXPROCS,INSPERSEC,ELAPHEAD, %C COMMSRECA,STOREAAD,PROCAAD,SFCCTAD,DRUMTAD,TSLICE,FEPS, %C MAXCBT,PERFORMAD,SP1,SP2,SP3,SP4,SP5,SP6, %C LSTL,LSTB,PSTL,PSTB,HKEYS,HOOT,SIM,CLKX,CLKY,CLKZ, %C HBIT,SLAVEOFF,INHSSR,SDR1,SDR2,SDR3, %C 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 or S1 ! 2 = 2960 or P2 ! 3 = 2970 or P3 ! 4 = 2980 or P4 ! 5 = 2972 or non-interleaved 2976 (P4/1) ! 6 = Interleaved 2976 or P4/1 ! ! IPLDEV The 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. ! 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. ! SP1->SP6 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, %C %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 %THEN %START %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 %THEN %START %INTEGERFNSPEC REMOTE ACTIVATE(%INTEGER PORT,AD) %EXTERNALROUTINESPEC HALT OTHER OCP %EXTERNALROUTINESPEC RESTART OTHER OCP(%INTEGER MODE) %FINISH %IF MONLEVEL&4#0 %START %LONGINTEGERNAME IDLEIT,NOWORKIT,LCIT,FLPIT,BLPIT,PTIT,DRUMIT, %C PDISCIT,RETIT,AMIT %LONGINTEGERNAME LCIC,PTIC,DRUMIC,PDISCIC,RETIC,AMIC %INTEGERNAME IDLEN,NOWORKN,LCN,FLPN,BLPN,PTCALLN,DRUMCALLN, %C PDISCCALLN,RETCALLN,AMCALLN %FINISH %HALFINTEGERNAME FSTASL,BSTASL %INTEGER I,J,K,FREEEPAGES,SHAREDEPS,UNALLOCEPS,OVERALLOC, %C NPQ,OLDLNB,IDLE,DONT SCHED,SMAC RCONFIG,SMACRPAGES, %C MPLEVEL,PAGEFREES,DCLEARS,GETEPN,PREEMPTED, %C MAX OVERALLOC,SNOOZTIME %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,%C 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=X'80040000'; ! PST SEG 8193(OCPPORT NEVER 1) %INTEGERARRAYFORMAT PTF(0:255); ! PAGE TABLE FORMAT !----------------------------------------------------------------------- ! STORE TABLE ETC. DECLARATIONS %RECORDFORMAT STOREF(%BYTEINTEGER FLAGS,USERS, %C %HALFINTEGER LINK,BLINK,FLINK,%INTEGER REALAD) %CONSTRECORD(STOREF)%ARRAYNAME STORE=STORE0AD;! ONE RECORD PER EPAGE %CONSTINTEGER OVERALLOC PERCENT=40 %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, %C %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 %THEN %START 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, %C 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&8#0 %THEN %START %HALFINTEGERARRAY FLYCAT,CATREC(0:MAXCAT,0:MAXCAT) %FINISH %IF MONLEVEL&16#0 %THEN %START %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 PPCELL(%INTEGER PPCELL) %IF MULTIOCP=YES %THEN %START %EXTERNALROUTINESPEC SEMALOOP(%INTEGERNAME SEMA) %EXTERNALROUTINESPEC RESERVE LOG %EXTERNALROUTINESPEC RELEASE LOG %FINISH %EXTERNALROUTINESPEC SUPPOFF(%RECORD(SERVF)%NAME SERV, %C %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) %IF SSERIES=NO %THEN %START %EXTERNALROUTINESPEC DISC(%RECORD(PARMF)%NAME P) %EXTERNALROUTINESPEC GPC(%RECORD(PARMF)%NAME P) %FINISH %ELSE %START %EXTERNALROUTINESPEC DISC MINDER(%RECORD(PARMF)%NAME P) %EXTERNALROUTINESPEC DCU(%RECORD(PARMF)%NAME P) %FINISH %EXTERNALROUTINESPEC PDISC(%RECORD(PARMF)%NAME P) %EXTERNALROUTINESPEC MOVE(%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) %EXTERNALROUTINESPEC CR ADAPTOR(%RECORD(PARMF)%NAME P) %EXTERNALINTEGERFNSPEC SAFE IS READ(%INTEGER ISAD,%INTEGERNAME VAL) %EXTERNALINTEGERFNSPEC SAFE IS WRITE(%INTEGER ISAD,VAL) %IF CPFITTED=YES %THEN %START %EXTERNALROUTINESPEC CP ADAPTOR(%RECORD(PARMF)%NAME P) %FINISH %IF MONLEVEL&256#0 %START %EXTERNALROUTINESPEC COMBINE(%RECORD(PARMF)%NAME P) %EXTERNALROUTINESPEC HARVEST( %C %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'1C'#0 %THEN %START %ROUTINESPEC TIMEOUT %ROUTINESPEC CLEAR TIME %FINISH %IF MONLEVEL&4#0 %THEN %START %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, %C %BYTEINTEGER INCAR, CATEGORY, P4TOP4, RUNQ, ACTIVE, %C %INTEGER ACTW0, LSTAD, %BYTEINTEGER EPA,EPN,%HALFINTEGER LAMTX,%C %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) ! 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=5 %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'01800FFE';! 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'01800BFE' 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 FREE EPAGES=STORE(0)_LINK; ! LEFT HERE BY CHOPSUPE %BEGIN %RECORD(PARMF)P %CYCLE I=J,1,K STORE(I)_FLAGS=0; ! NOT RECAPTURABLE P_DEST=X'60001' P_P2=I RETURN EPAGE(P) %REPEAT %END !----------------------------------------------------------------------- COM_PROCAAD=ADDR(PROCA(0)) %CYCLE I=0,1,MAXPROCS PROCA(I)=0 %REPEAT %IF SFC FITTED=YES %THEN COM_DRUMTAD=ADDR(DRUMT(0)) I=PPINIT(NEW EPAGE) OVERALLOC=OVERALLOC PERCENT*FREE EPAGES//100;! 25% OVERALLOCATION MAX OVERALLOC=OVERALLOC SHAREDEPS=0 UNALLOCEPS=FREEEPAGES+OVERALLOC NPQ=0 IDLE=0 %IF SNOOZING=YES %THEN SNOOZTIME=20 %BEGIN %RECORD(PARMF) P !----------------------------------------------------------------------- ! INITIALISE GPC, DRUM & DISC ROUTINES P_DEST=X'300002' %IF SSERIES=NO %THEN %START; ! ON P SERIES P_P1=COM_GPCA %FINISH %ELSE %START; ! ON S SERIES P_P1=COM_DCUA %FINISH P_P2=ADDR(PROC PICT(0)); ! SPACE FOR OPER PICTURE PON(P) P_DEST=X'370000' P_P1=EPAGESIZE P_P2=COMMS EPAGES; ! COMMSALLOC P_P3=ADDR(PARM(0)) PON(P) %IF SSERIES=NO %THEN %START; ! PSERIES INITIALISE DISC P_DEST=X'200000' PON(P) %FINISH %IF SFC FITTED=YES %AND DRUMSIZE>0 %THEN %START P_DEST=X'280000' P_P1=EPAGESIZE P_P2=COM_SFCA P_P3=ADDR(STORE(0)) P_P4=ADDR(PARM(0)) 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 %FINISH %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 ! 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'01800FFE' RECORD(X'80040000'+I<<18)<-GSSNP1;! CONTEXT FROM RECORD TO SSN+1 *STSF_J PST(I)=PST(4)&X'1FF000008FFFFF80'+X'1F8000000000'+ %C (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) GLOBAL CONTROL; ! DOES NOT RETURN !----------------------------------------------------------------------- LCCALL:*JLK_%TOS *STCT_(%LNB+5); ! DISPLAY PTR TO NEW STACK ! SO THAT THE LXN IN CALL SEQUENCE ! LINKS LOCAL TO GLOBAL CONTEXTS *STB_(%LNB+0); ! B HAS PROCESS NO IN IT PUTIN ! BY SCHEDULE AT CREATE ! AND IS PASSED ON BY THIS FRIG LOCAL CONTROL; ! INITIAL CALL(DOES NOT RETURN!) %ROUTINE GLOBAL CONTROL !%ROUTINESPEC UNQUEUE(%INTEGERNAME QUEUE,UNQUED SERVICE) %INTEGER I,J,K,PORT,SEIP,SELN,SESTK,KSERVICE,LSERVICE,TSERVICE, %C MY OCP PORT,HIS OCP PORT,IS DIAG,ISTAD %LONGINTEGER WORK %IF MONLEVEL&4#0 %THEN %START %INTEGER IT,IC,IT CORRN %INTEGERNAME KIT; ! IT IN KERNEL CONTEXT %CONSTINTEGER IC CORRN=20; ! INSTRNS NOT COUNTED IN IDLE %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 %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 MULTIOCP=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'01800FFE'; ! 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 LSSNP1P==RECORD(X'40000') ! ! MASK SYSERR& UNMASK OUT ON SYSERR. INTERRUPT ! ISTP_SSR=X'01800EFF' ISTP_SF=ISTP_SF+X'1000'; ! SET SYSTEM ERROR SF TO DISTANT PLACE ! ! INSERT PCS ! *LXN_ISTAD *JLK_; *LSS_%TOS; *ST_(%XNB+2) *JLK_; *LSS_%TOS; *ST_(%XNB+10) *JLK_; *LSS_%TOS; *ST_(%XNB+18) *JLK_; *LSS_%TOS; *ST_(%XNB+26) *JLK_; *LSS_%TOS; *ST_(%XNB+74) *JLK_; *LSS_%TOS; *ST_(%XNB+82) CURPROC==INTEGER(ISTAD+4*95); ! ONTO CTB FIELD FOR IC INT CURPROC=0 KSERVICE=0 %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 %THEN %START ! OPEN PATHS FOR MP INT ETC ! SET PORT DEPENDENT PHOTO(P4S) %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 %FINISH %ELSE %START *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 %IF MY OCP PORT#COM_OCPPORT0 %START;! IM NOT IPL PROCESSOR %IF BASIC PTYPE<=3 %THEN %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') J=COM_OCPPORT0 *LSS_J; *ST_(X'600F');! OPEN ROUTE FOR RRTC *ST_IS DIAG %FINISH %ELSE %START %IF COM_OCPTYPE=4 %THEN J=COM_SACPORT0 %ELSE %C 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 %THEN %START *LSS_X'FFFFFF'; ! SET IT & IC TO MAX. *ST_(5) *ST_(6) %FINISH *LSS_ALLOW PERI INTS; ! LET INTERRUPTS IN *ST_(3) *LSS_X'01800FFE' *ST_(3) %IF MULTIOCP=YES %THEN %START *INCT_(MAINQSEMA) *JCC_8, SEMALOOP(MAINQSEMA) MQGOT1: %FINISH KSKIP: ! TRY NEXT WITHOUT RECLAIMING SEMA %IF KSERVICE!KERNELQ=0 %THEN %START %IF CURPROC#0 %THEN %START ! 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 %THEN MAINQSEMA=-1 %IF MONLEVEL&4#0 %THEN %START %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 %THEN MAINQSEMA=-1 %IF MONLEVEL&4#0 %THEN %START %IF MPLEVEL+NPQIDLE0; ! IN CASE "EKS" SET %FINISH %ELSE %START; ! IDLE IN DUALS %IF SSERIES=NO %AND MY OCP PORT#COM_OCPPORT0 %START PORT=COM_SACPORT0 *LSS_X'01800FFE'; *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 %THEN %START ! UNQUEUE(KERNELQ,KSERVICE) *LD_KERNELQ; *JLK_ *STB_KSERVICE KSERV==SERVA(KSERVICE) %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 %THEN MAINQSEMA=-1 P_DEST=X'30007'; ! RESCHEDULE LOCAL CONTROLLER P_SRCE=0 P_P1=I-LOCSN3 SCHEDULE(P) TSERVICE=3 ->KTIMES %FINISH %IF MULTIOCP=YES %THEN MAINQSEMA=-1 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&4#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):SERVROUT(20):SERVROUT(21): SERVROUT(22):SERVROUT(23):SERVROUT(24):SERVROUT(25):SERVROUT(26): SERVROUT(27):SERVROUT(28):SERVROUT(29):SERVROUT(30):SERVROUT(31): ->INVALID SERVROUT(32): %IF SSERIES=NO %THEN DISC(P) %ELSE DISC MINDER(P) ->KEXIT SERVROUT(33): PDISC(P); ->KEXIT SERVROUT(34):SERVROUT(35): ->INVALID SERVROUT(36):SERVROUT(37): MOVE(P); ->KEXIT SERVROUT(38):SERVROUT(39): ->INVALID SERVROUT(40): %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): %IF SSERIES=NO %THEN GPC(P) %ELSE DCU(P); ->KEXIT SERVROUT(49): TAPE(P); ->KEXIT SERVROUT(50): OPER(P); ->KEXIT SERVROUT(51): LP ADAPTOR(P); ->KEXIT SERVROUT(52): CR ADAPTOR(P); ->KEXIT SERVROUT(53): %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 %START COMBINE(P); ->KEXIT %FINISH %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 %THEN %START *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) %WHILE LSERV_P&X'3FFFFFFF'#0 LSERV_P=LSERV_P&X'BFFFFFFF'; ! REMOVE EXECUTING BIT ! 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) *JLK_; *STB_LSERVICE LSERV==SERVA(LSERVICE) I=LSERV_P&X'BFFFFFFF'; ! WITHOUT "EXECUTING" BIT %IF I<=0 %THEN LSERV_P=I %AND ->KSKIP;! INHIBITED ! CAN L-C EVER BE INHIBITED?? %IF MULTIOCP=YES %THEN MAINQSEMA=-1 CURPROC=LSERVICE-LOCSN0 PROC==PROCA(CURPROC) %IF PROC_ACTIVE#255 %THEN ->LINVALID %IF MONLEVEL&4#0 %THEN %START LCN=LCN+1 *LSS_(6); *IRSB_MAXIT; *LUH_0; *IAD_(LCIC); *ST_(LCIC) *LSS_(5); *IRSB_MAXIT; *LUH_0; *IAD_(LCIT); *ST_(LCIT) %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 *ACT_%TOS !----------------------------------------------------------------------- ! EVENT PENDING (USED TO EXIT FROM LOCAL CONTROLLER) IST11I: *JLK_%TOS ! LOCAL CONTROL RETURNS TO HERE CURPROC=0 %IF MULTIOCP=YES %THEN %START *INCT_(MAINQSEMA) *JCC_8, SEMALOOP(MAINQSEMA) 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 %THEN %START %IF PROC_RUNQ=1 %THEN RUNQ==RUNQ1 %ELSE RUNQ==RUNQ2 %IF RUNQ=0 %THEN LSERV_L=LSERVICE %ELSE %START 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 %THEN MAINQSEMA=-1 ->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; ! EXCEPT IN S SERIES !!! !----------------------------------------------------------------------- IST2I:*JLK_%TOS ! EXTERNAL INTS (CLOCK) ENTER HERE *LSS_%TOS ; *ST_I *LSS_%TOS ; *ST_J %IF MONLEVEL&4#0 %AND IDLE#0 %THEN %START %IF MPLEVEL+NPQKSERVE %ELSE %START ELAPSEDINT(P) %IF MONLEVEL&4#0 %THEN TSERVICE=10 ->KTIMES %FINISH !----------------------------------------------------------------------- ! MULTIPROCESSOR IST3I:*JLK_%TOS %IF MULTIOCP=YES %THEN %START *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 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 %FINISH %ELSE %START %IF I=MY OCP PORT %START; ! MP INT FROM SELF *LSS_(X'4012'); *AND_X'FFFFFDFF' *ST_(X'4012') %FINISH %ELSE %START 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 ! ! IF REMAINING OCP IS NOT THE IPL OCP THEN SAC &CLOCK INT PATHS ! MUST BE OPENED UP. ALSO IF CLOCK IN OCP THEN SPARE CLOCK IN ! THIS OCP MUST BE SET UP ! %IF COM_OCP PORT0#MY OCP PORT %START 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') %FINISH %ELSE %START J=I<<12!I<<2 *LSS_(X'4012'); *OR_J; *ST_(X'4012') %FINISH %IF 5<=COM_OCPTYPE<=6 %START;! 2972&76 CHANGE PORT IN CLOCK IS REGS K=MY OCP PORT<<20 COM_CLKX=COM_CLKX&X'FF0FFFFF'!K COM_CLKY=COM_CLKY&X'FF0FFFFF'!K COM_CLKZ=COM_CLKZ&X'FF0FFFFF'!K K=X'80000000'>>MY OCP PORT *LSS_(X'4012'); *OR_K; *ST_(X'4012');! OPEN CLOCK INT PATH K=MY OCP PORT<<20 *LSS_(X'4013'); *AND_X'FFFFF'; *OR_K; *ST_(X'4013') %FINISH ! ! EXCEPT FOR 2980(WHICH HAS CLOCK IN SAC)SET & START CLOCK IN THIS OCP ! %IF COM_OCPTYPE#4 %START WORK=LENGTHENI(COM_TOJDAY)*86400+(COM_SECSFRMN+2) WORK=WORK*1000000 *LSD_WORK; *USH_-1; *STUH_%B; *ST_J K=COM_CLKX *LB_K; *LSS_WORK; *ST_(0+%B) K=COM_CLKY *LB_K; *LSS_J; *ST_(0+%B) K=COM_CLKZ *LB_K; *LSS_13; *ST_(0+%B) %FINISH %ELSE %START; ! 2980 I=X'80000000'>>COM_SACPORT0 *LSS_(X'4012'); *OR_I; *ST_(X'4012') %FINISH %IF BASIC PTYPE<=3 %START *LSS_MY OCP PORT; *ST_(X'600F') %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 %C SERVA(I)_P=SERVA(I)_P!!X'40000000' %C %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 %THEN %START 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 %THEN %START %IF MPLEVEL+NPQ>24 %START OPMESS("INT FROM DCU ".STRINT(I>>24)." ??") ->KSERVE %FINISH P_DEST=X'300003' P_P1=I DCU(P) TSERVICE=58 ->KTIMES %FINISH %ELSE %START; ! FOR P SERIES PORT=I>>20&3 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 %THEN %START 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' DISC(P) %IF MONLEVEL&4#0 %THEN TSERVICE=34 ->CONTINUE CONROUT(3): P_DEST=X'300003' P_SRCE=M'INT' GPC(P) %IF MONLEVEL&4#0 %THEN TSERVICE=58 CONTINUE: %IF I=0 %THEN ->KTIMES %IF MONLEVEL&4#0 %THEN %START *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)+ %C (MAXIT-IT) PERFORM_SERVIC(TSERVICE)=PERFORM_SERVIC(TSERVICE)+ %C (MAXIT-IC) %FINISH K=J+1 %REPEAT %FINISH !----------------------------------------------------------------------- ! EXTRACODE IST10I:*JLK_%TOS ; *IDLE_X'FA' !----------------------------------------------------------------------- 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 %IF SNOOZING=YES %THEN %START %ROUTINESPEC BOOT ON FLY %ROUTINESPEC OFF BOOTQ(%INTEGER PROC) %FINISH %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,BOOTQH=0,SCHTICKS=0 !----------------------------------------------------------------------- ! PRIORITY QUEUE ARRAY ETC. %OWNBYTEINTEGERARRAY PQ(1:MAXPROCS)=0(MAXPROCS) %OWNBYTEINTEGERARRAY PQH(1:PRIQS)=0(PRIQS);! NUMBER OF PRIORITIES=PRIQS %OWNINTEGER P4PAGES,MAXP4PAGES,NPL4=0 %OWNBYTEINTEGERARRAY PQN(1:PRIQS)=0(PRIQS) %IF MONLEVEL&1#0 %THEN %START %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,%C 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:18) %IF MONLEVEL&2#0 %AND KMON&1<<3#0 %THEN %C PKMONREC("SCHEDULE:",P) ACT=P_DEST&X'FFFF' PROCESS=P_P1 %IF 0 SEMALOOP(SCHEDSEMA) SSEMAGOT: %FINISH ->ACTIVITY(ACT&255) !----------------------------------------------------------------------- ACTIVITY(0): ! INITIALISE I=FREEEPAGES//2-LSTACKLEN %IF MAXEPAGES>I %THEN %START MAXEPAGES=I %CYCLE I=1,1,MAXCAT-2; ! DONT ADJUST TRASHING CAT %IF CATTAB(I)_EPLIM>MAXEPAGES %THEN %C CATTAB(I)_EPLIM=MAXEPAGES %REPEAT %FINISH MAXP4PAGES=P4PERCENT*COM_SEPGS//100 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 %THEN %START DISPLAY TEXT(0,2,0,"RQ1 RQ2 P1 P2 P3 P4 P5 SUSP STF") DISPLAY TEXT(0,3,0," 0 0 0 0 0 0 0 0 100") %IF SFCFITTED=NO %OR DRUMSIZE=0 %THEN %C DISPLAY TEXT(0,2,36,"OUTS") %FINISH 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 VIFEO & 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'400'; ! LSTACKDA(NEEDS 3 EPAGES ONLY) P_P4=0; ! USE DEFAULT DIRVSN P_P5=P_P3+LSTACKLEN; ! DSTACKDA(1SEG IN CBT BUT USES LESS) P_P6=P_P3+(X'40'-8); ! DGLADA (ALLOW LAST 8 PAGES) PON(P) %IF MULTIOCP=YES %THEN SCHEDSEMA=-1 %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 PROCESS>0 %START PROC==PROCA(PROCESS) %IF PROC_USER#"" %THEN P_P1=3 %AND ->STARTREP %FINISH %ELSE %START %CYCLE PROCESS=FIRST UPROC,1,MAXPROCS-1 PROC==PROCA(PROCESS) %IF PROC_USER="" %THEN %EXIT %REPEAT %FINISH LSTACKDA=P_P3 %IF P_P4<=0 %THEN DCODEDA=COM_DCODEDA %ELSE DCODEDA=P_P4 DSTACKDA=P_P5 DGLADA=P_P6 P_DEST=X'80001'; ! GET AMTX FOR LOCAL 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 %IF PROC_STATUS&4=0 %AND PROCESS>=FIRST UPROC %THEN NPL4=NPL4+1 PROC_ACTIVE=0; ! SUSPENDED PROC_CATEGORY=0 %IF MONLEVEL&1#0 %THEN SUSPN=SUSPN+1 %IF MULTIOCP=YES %THEN SCHEDSEMA=-1 UPDISP(PROCESS,4,USER) %IF ACT=16 %THEN UPDISP(PROCESS,10,"*") CLEAR PARMS(PROCESS+LOCSN0) CLEAR PARMS(PROCESS+LOCSN1) CLEAR PARMS(PROCESS+LOCSN2) CLEAR PARMS(PROCESS+LOCSN3) ! PON TO INITIALIZE LOCAL CONTROLLER P_DEST=(PROCESS+LOCSN0)<<16 P_SRCE=X'30002' P_P1=PROCESS P_P2=DCODEDA P_P3=DGLADA P_P4=DSTACKDA PON(P); ! INHIBITED AS YET THOUGH ! REPLY TO START-UP P_P1=0; ! PROCESS CREATED SUCCESSFULLY P_P2=(PROCESS+LOCSN1)<<16 P_P3=(PROCESS+LOCSN2)<<16 P_P4=(PROCESS+LOCSN3)<<16!1; ! ASYNCH SNO FOR INPUT CONTROL MESS P_P5=PROCESS STARTREP: %IF SRCE<=0 %THEN OPMESS(USER.STARTMESS(P_P1)) %C %ELSE P_DEST=SRCE %AND P_SRCE=X'30001' %AND PON(P) %IF P_P1=0 %THEN %START P_DEST=X'30007'; ! PON TO USUSPEND HIM P_P1=PROCESS; ! IN PROPRELY SEMAPHORED WAY PON(P) %FINISH %ELSE SCHEDSEMA=-1 %RETURN !----------------------------------------------------------------------- ACTIVITY(2): ! REPLY FROM CREATE PROCESS NEWCATSLOT=1+PROC_STATUS>>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; ! ALREADY IN MAX CATEGORY %IF MULTIOCP=YES %AND SMAC RCONFIG#0 %THEN ->WAYOUT %IF OLDCAT_PRIORITY<=3 %AND PROC_STATUS&HADPONFLY=0 %C %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 %THEN %C PROC_P4TOP4<-PROC_P4TOP4+1 %IF MONLEVEL&8#0 %THEN %C FLYCAT(NEWCATSLOT,OLDCATSLOT)<-FLYCAT(NEWCATSLOT,OLDCATSLOT)+1 WAYOUT: %IF MULTIOCP=YES %THEN SCHEDSEMA=-1 %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 P4PAGES>=MAXP4PAGES %AND OLDCAT_PRIORITY>=4 %AND %C PROCESS>=FIRST UPROC %THEN ->WAYOUT %IF MULTIOCP=YES %AND SMAC RCONFIG#0 %THEN ->WAYOUT NEWCATSLOT=OLDCAT_MORET NEWCAT==CATTAB(NEWCATSLOT) %IF PROC_STATUS&HADTONFLY=0 %AND %C (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 %C 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 %THEN %START ! %IF SHAREDEPS+UNALLOCEPS1 %C ! %THEN ->WAYOUT; ! NO ! %IF MULTIOCP=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 %C %OR (SFC FITTED=YES %AND DRUMSIZE>0)) %THEN ->WAYOUT NEWCATSLOT=OLDCAT_SUSP %IF MONLEVEL&1#0 %THEN %START 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&8#0 %THEN FLYCAT(NEWCATSLOT,OLDCATSLOT) <- %C FLYCAT(NEWCATSLOT,OLDCATSLOT)+1 MPLEVEL=MPLEVEL-1 %IF OLDCAT_PRIORITY>=4 %THEN P4PAGES=P4PAGES-OLDCAT_EPLIM;! PEDANTIC ! %IF BOOTQH=0 %THEN PQ(PROCESS)=PROCESS %C %ELSE PQ(PROCESS)=PQ(BOOTQH) %AND PQ(BOOTQH)=PROCESS BOOTQH=PROCESS 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 %C (PROCESS=FIRST UPROC %AND %C PROC_STATUS&4=0 %THEN NPL4=NPL4+1 ->STOUT !----------------------------------------------------------------------- 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 %IF MONLEVEL&4#0 %THEN PERFORM_SNOOZOK=PERFORM_SNOOZOK+1 %IF MONLEVEL&1#0 %THEN %C 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) OFF BOOT Q(PROCESS) %IF MONLEVEL&4#0 %THEN PERFORM_SNOOZN=PERFORM_SNOOZN+LSTACKLENP ->WAYOUT %FINISH PROC_ACTIVE=255 %IF OLDCAT_PRIORITY<4 %AND PROCESS>=FIRST UPROC %C %AND PROC_STATUS&4=0 %THEN NPL4=NPL4-1 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 %THEN %C PROC_P4TOP4<-PROC_P4TOP4+1 %IF MONLEVEL&8#0 %THEN %C 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) %EXIT %IF PQH(PTY)#0 PRATP=(PRATP+1)&PRATMAX %REPEAT %IF SFC FITTED=NO %AND PTY>=3 %AND PAGEFREES>=MAXEPAGES %START;! TOO MANY WRITEOUT PRATP=(PRATP+1)&PRATMAX; ! PASS OVER BIG JOB %IF MULTIOCP=YES %THEN SCHEDSEMA=-1 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 %THEN %START %IF P4PAGES>0 %AND P4PAGES+OLDCAT_EPLIM>MAXP4PAGES %AND %C NPL4*MAXEPAGES>SHAREDEPS+UNALLOCEPS %START %IF NPQ>PQN(4)+PQN(5) %THEN %C PRATP=(PRATP-31)&PRATMAX %AND ->AGN ->WAYOUT %FINISH %FINISH I=OLDCAT_EPLIM+LSTACKLEN %IF I>SHAREDEPS+UNALLOCEPS %AND MPLEVEL>0 %THEN %START; ! NOT ENOUGH ROOM %IF SNOOZING=YES %AND BOOTQH#0 %AND%C (SFC FITTED=YES %OR PAGEFREES>2) %AND %C PQN(1)+PQN(2)>0 %THEN BOOT ON FLY ->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 %C %ELSE PQ(PQH(PTY))=PQ(PROCESS) NPQ=NPQ-1 PQN(PTY)=PQN(PTY)-1 %IF SNOOZING=YES %AND BOOTQH#0 %AND PQN(1)+PQN(2)>0 %AND %C SHAREDEPS+UNALLOCEPSFREE EPAGES+PAGE FREES %C %AND PAGE FREES>2 %THEN BOOT ON FLY %IF MULTIOCP=YES %THEN SCHEDSEMA=-1 ! PAGE IN LOCAL CONTROLLER STACK P_DEST=X'40001'; ! PAGETURN/PAGE-IN 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 P_P1=PROC_LAMTX<<16!I P_P2=PROCESS<<8!I PON(P) %REPEAT %IF NPQ#0 %AND SHAREDEPS+UNALLOCEPS>=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 OFF BOOTQ(PROCESS) P_DEST=(PROCESS+LOCSN0)<<16!8 P_SRCE=X'3000C' PON(P) %FINISH %IF MULTIOCP=YES %THEN SCHEDSEMA=-1 %RETURN !----------------------------------------------------------------------- ACTIVITY(13): ! RESCHEDULE ALL RESIDENT TO FREE SMAC %CYCLE I=1,1,MAXPROCS PROC==PROCA(I) %IF PROC_USER#"" %AND(PROC_ACTIVE=255 %OR PROC_STATUS %C &(SNOOZED!STATEX)#0) %START P_DEST=(COM_ASYNCDEST+I)<<16 P_SRCE=X'3000D' P_P1=3; ! DUMMY ACT PON(P) %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 ".%C 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 %THEN %START PROC_STATUS=PROC_STATUS!!STATEX %IF MONLEVEL&4#0 %THEN PERFORM_SNOOZN=PERFORM_SNOOZN+LSTACKLENP I=LSTACKLENP %FINISH %ELSE 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 %C 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 %C UPDISP(PROCESS,11,"R".TOSTRING(PROC_RUNQ+'0')) MPLEVEL=MPLEVEL+1 %IF OLDCATSLOT=0 %THEN %START; ! 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 %FINISH %ELSE %START 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 %C PROC_P4TOP4>16 %THEN P_P2=P_P2*(320-PROC_P4TOP4)//320 PON(P) %FINISH %IF MULTIOCP=YES %THEN SCHEDSEMA=-1 %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#"" %THEN %START %IF I>=FIRST UPROC %AND PROC_ACTIVE=3*MINSINACTIVE %C %AND PROC_STATUS&4=0 %THEN %START P_DEST=(I+LOCSN3)<<16+1 P_P1=-1; P_P2=-1 P_P3=X'01570000'; ! SEND INT W PON(P) %FINISH PROC_ACTIVE=PROC_ACTIVE+1 %UNLESS PROC_ACTIVE>200 J=J+1 %FINISH I=I+1 %REPEAT %FINISH %IF NPQ#0 %AND RUNQ1=0=RUNQ2 %START; !*JM sheduler amend* P_DEST=X'30006'; ! kick process load P_P1=M'TICK' PON(P) %FINISH; !*JM sheduler amend* %IF MULTIOCP=YES %THEN SCHEDSEMA=-1 %IF MONLEVEL&1#0 %THEN %START %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#"" %THEN %START 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(SUSPN)." ") I=100*FREE EPAGES//COM_SEPGS DISPLAY TEXT(0,3,31,STRINT(I)."% ") %IF SFCFITTED=NO %OR DRUMSIZE=0 %THEN %C 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,%C PQN(1)<<24!PQN(2)<<16!PQN(3)<<8!PQN(4), %C PQN(5)<<24!SUSPN<<16!SNOOS<<8, %C PAGEFREES<<16!UNALLOCEPS,FREEEPAGES<<16) %C %IF TRACE = YES %AND TRACE EVENTS&(1<<1) # 0 %FINISH %END %FINISH %RETURN !----------------------------------------------------------------------- %IF SNOOZING=YES %THEN %START %ROUTINE BOOT ON FLY !*********************************************************************** !* THROWS OUT ONE PERSON SUSPENDED ON FLY * !*********************************************************************** %INTEGER PROCESS %RECORD(PARMF) P %RECORD(PROCF)%NAME PROC PROCESS=PQ(BOOTQH) %IF BOOTQH=PROCESS %THEN BOOTQH=0 %ELSE PQ(BOOTQH)=PQ(PROCESS) PQ(PROCESS)=0 PINH(PROCESS,X'E'); ! ALL EXCEPT L-CNTRLR PROC==PROCA(PROCESS) ! %IF PROC_STATUS&SNOOZED#0 %THEN MONITOR("BOOTING WHOM??") PROC_STATUS=PROC_STATUS&(\SNOOZED) PROC_ACTIVE=255 UNALLOCEPS=UNALLOCEPS+PROC_EPN-PROC_EPA MPLEVEL=MPLEVEL+1 %IF MONLEVEL&4#0 %THEN PERFORM_SNOOZAB=PERFORM_SNOOZAB+1 P_DEST=(PROCESS+LOCSN0)<<16!8 P_SRCE=X'30011' %IF MONLEVEL&1#0 %THEN SUSPN=SUSPN-1 PON(P) %END %ROUTINE OFF BOOTQ(%INTEGER PROC) !*********************************************************************** !* PROC HAS WOKEN UP WHILE IN STORE. REMOVE FROM BOOT Q * !*********************************************************************** %INTEGER ONE,TWO,BACK,COUNT COUNT=0 ONE=BOOTQH; BACK=ONE TWO=PQ(ONE) %IF ONE=TWO %THEN %START %IF ONE=PROC %THEN PQ(PROC)=0 %AND BOOTQH=0 %AND %RETURN MONITOR("BOOT Q STATE??") %FINISH %CYCLE %IF TWO=PROC %THEN %EXIT ONE=TWO; TWO=PQ(ONE) COUNT=COUNT+1 ! %IF COUNT>=255 %THEN MONITOR("BOOT QUEUE ??") %REPEAT PQ(ONE)=PQ(TWO) %IF BACK=TWO %THEN BOOTQH=ONE PQ(PROC)=0 %END %FINISH %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 %C P_P2+LEEWAY>CATTAB(NEWCAT_LESSP)_EPLIM %THEN %C PROC_CATEGORY=NEWCATSLOT %AND %RETURN 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 %C PQ(PROCESS)=PQ(PQH(PTY)) %AND PQ(PQH(PTY))=PROCESS PQH(PTY)=PROCESS %UNLESS (PROCESS=1 %OR PROC_STATUS&1#0) %C %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 * !* 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 %IF MONLEVEL&4#0 %THEN %START %INTEGER IT,IC %FINISH %HALFINTEGERNAME AMTDDDDX %RECORD(AMTF)%NAME AMT %RECORD(STOREF)%NAME ST %RECORD(PARMXF)%NAME PP %IF SFC FITTED=YES %THEN %START %RECORD(PARMF) TDRUM,TDISC %FINISH %ELSE %START %RECORD(PARMF) TDISC %FINISH %SWITCH ACTIVITY(0:8) %IF MONLEVEL&2#0 %AND KMON&1<<4#0 %THEN %C 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 %THEN %START *INCT_(STORESEMA) *JCC_8, SEMALOOP(STORESEMA) 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 %THEN %START *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(1): ! PAGE-IN (ALLOWS PAGETURN TO BE CALLED) %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 %THEN %START; ! PAGE-OUT IN PROGRESS PAGEFREES=PAGEFREES-1 %FINISH %ELSE %START 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 %C (SFCFITTED=YES %AND ST_FLAGS&X'30'=X'20') %START *JLK_ MUST WAIT: ! FOR FREE PAGE OR TRANSFER %IF MULTIOCP=YES %THEN STORESEMA=-1 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 ! P_P5=ST_USERS ! P_P6=ST_FLAGS %IF MULTIOCP=YES %THEN STORESEMA=-1 %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,-1) %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 %THEN STORESEMA=-1 %IF PAGEFREES<=1 %AND GETEPN>=MPLEVEL+1-COM_NOCPS %THEN %C 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 %THEN %START; ! DEADLOCK PAGE ZERO P_DEST=SRCE!1; ! FAILED TO PRODUCE PAGE P_P3=-1; ! PLEASE DEPART ! AMT_USERS=AMT_USERS-1 %IF MULTIOCP=YES %THEN STORESEMA=-1 PON(P) %RETURN %FINISH %IF STOREX#STXMASK %THEN %START; ! 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 %THEN %START;! 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 %THEN STORESEMA=-1 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 %THEN STORESEMA=-1 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 MONITOR("PAGEIN TO 0?") %IF STOREX=0 P_DEST=0 ->TRANSFER NEEDED !----------------------------------------------------------------------- ACTIVITY(6): ! FAILURE REPLY FROM DRUM/READ %IF SFCFITTED=YES %THEN %START ST==STORE(STOREX) BAD DRUM PAGE(DTX); ! DISCARD DRUM PAGE ->DRUMRF; ! AND FETCH FROM DISC %FINISH !----------------------------------------------------------------------- ACTIVITY(2): ! PAGE-OUT ST==STORE(STOREX) AMT_USERS=AMT_USERS-1 ST_FLAGS=ST_FLAGS!P_P2; ! INSERT WRITTEN ETC. MARKERS ST_USERS=ST_USERS-1 %IF ST_USERS>0 %THEN %START SHAREDEPS=SHAREDEPS-1 %IF MULTIOCP=YES %THEN STORESEMA=-1 %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 %THEN %START;! \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 %THEN %START %IF ST_FLAGS&4=0 %START; ! NO DRUM UPDATE %IF DTX>=0 %THEN %START; ! RETURN DRUM PAGE(IF ANY) AMTDDDDX=STOREX DRUMT(DTX)=DRUMTASL DRUMTASL=DTX DRUMALLOC=DRUMALLOC-1 DTX=-1 %FINISH %FINISH %ELSE %START; ! 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 %THEN %START; ! NO TRANSFERS INITIATED %IF ST_FLAGS&2#0 %THEN AMTDDDDX=NEWEPBIT!STXMASK %C %AND ST_FLAGS=0 ->REP; ! TO RETURN EPAGE %FINISH ST_FLAGS=ST_FLAGS&X'F1' %IF MULTIOCP=YES %THEN STORESEMA=-1 TRANSFER NEEDED: ! TO COMPLETE PAGETURN %IF FLAGS&X'80'#0 %THEN %START; ! DISC TRANSFER TO START %IF MONLEVEL&4#0 %THEN %START *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH PDISC(TDISC) %IF MONLEVEL&4#0 %THEN %START *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&4#0 %START *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH DRUM(TDRUM) %IF MONLEVEL&4#0 %THEN %START *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 %THEN STORESEMA=-1 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 %THEN %START; ! 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 %C AMTDDDDX=AMTDDDDX!STXMASK %ELSE DRUMT(DTX)=STXMASK %FINISH %ELSE %START %IF SFCFITTED=NO %OR DTX<0 %THEN ST_LINK=DDX %C %ELSE ST_LINK=DDBIT!DTX %FINISH P_DEST=X'60001' P_P2=STOREX PAGEFREES=PAGEFREES-1 %IF MONLEVEL&4#0 %THEN %START *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH RETURN EPAGE(P) %IF MONLEVEL&4#0 %THEN %START *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 %THEN %START P_DEST=X'00080003' P_P2=AMTX %IF MULTIOCP=YES %THEN PON(P) %ELSE %START %IF MONLEVEL&4#0 %THEN %START *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH ACTIVE MEM(P) %IF MONLEVEL&4#0 %THEN %START *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 %THEN STORESEMA=-1 %RETURN !----------------------------------------------------------------------- ACTIVITY(7): ! REPLY FROM DRUM/WRITE %IF SFCFITTED=YES %THEN %START ST==STORE(STOREX) %IF P_P2<0 %THEN %START; ! 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 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 %THEN %START %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 %THEN %EXIT I=J %REPEAT DRUMT ASL BTM=I %FINISH DRUMT(DRUMT ASL BTM)=DTX ENTER: DRUMT(DTX)=DTEND DRUMT ASL BTM=DTX DRUM ALLOC=DRUM ALLOC-1 %END %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 %THEN %RESULT=-1 STOREX=FSTASL ST==STORE(STOREX) %IF MULTIOCP=NO %OR SMACMASK=-1 %START FSTASL=STORE(FSTASL)_FLINK STORE(FSTASL)_BLINK=0 %FINISH %ELSE %START %CYCLE %IF 1<<(ST_REALAD>>22&15)&SMACMASK#0 %START STORE(ST_FLINK)_BLINK=ST_BLINK STORE(ST_BLINK)_FLINK=ST_FLINK %EXIT %FINISH STOREX=ST_FLINK %IF STOREX=0 %THEN %RESULT=-1 ST==STORE(STOREX) %REPEAT %FINISH %IF ST_FLAGS=1 %THEN %START; ! RECAPTURABLE FLAG I=ST_LINK %IF SFC FITTED=NO %OR I&DDBIT=0 %THEN %C AMTDD(I)=AMTDD(I)!STXMASK %ELSE %C I=I&(\DDBIT) %AND DRUMT(I)=STXMASK ST_FLAGS=0 %FINISH %IF ZEROED=0 %THEN %START; ! 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 %THEN %START *INCT_(STORESEMA) *JCC_8, SEMALOOP(STORESEMA) SEMACL: %FINISH %IF FREEEPAGES=0 %THEN %START; ! SHOULD ONLY OCCUR IN MULTIOCPS %IF MULTIOCP=YES %THEN STORESEMA=-1 PON(P); ! SERVICE NOW INHIBITED %RETURN %FINISH %IF MONLEVEL&2#0 %AND KMON&1<<5#0 %THEN %C 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 %THEN STORESEMA=-1 PON(P) %END !----------------------------------------------------------------------- %INTEGERFN NEW EPAGE !*********************************************************************** !* HANDS OUT A NEW EPAGE TO EXTEND A VITAL RESIDENT TABLE * !*********************************************************************** %INTEGER I %IF MULTIOCP=YES %THEN %START *INCT_(STORESEMA) *JCC_7,; ! CAN NOT LOOP HERE %FINISH %IF FREE EPAGES>0 %THEN %START I=QUICK EPAGE(0,COM_SMACS>>16);! ZEROED & IN SYSTEM SMAC %IF MULTIOCP=YES %THEN STORESEMA=-1 %IF I<0 %THEN ->USE SPARE STORE(I)_USERS=255 %RESULT=STORE(I)_REALAD&X'0FFFFFFF';! MAY BE FLAWED %FINISH %IF MULTIOCP=YES %THEN STORESEMA=-1 USE SPARE: ! TRY EMERGENCY SPARE PAGE %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 %THEN %START *INCT_(STORESEMA) *JCC_8, SEMALOOP(STORESEMA) SEMACL: %FINISH %IF MONLEVEL&2#0 %AND KMON&1<<6#0 %THEN %C PKMONREC("RETURNEPAGE:",P) STOREX=P_P2 ST==STORE(STOREX) ! IF PAGE IS IN SMAC BEING ! RECONFIGURED THEN DISCARD %IF MULTIOCP=YES %AND 0#SMAC RCONFIG=ST_REALAD>>22&15 %START SMAC RPAGES=SMAC RPAGES-1 *JLK_ ->RETURN %FINISH %IF ST_REALAD<0 %THEN %START %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 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 %FINISH %ELSE %START %IF ST_FLAGS&1#0 %START; ! RECAPTURABLE TO BACK ST_FLINK=0 ST_BLINK=BSTASL STORE(BSTASL)_FLINK=STOREX BSTASL=STOREX %FINISH %ELSE %START; ! 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 %THEN STORESEMA=-1 %RETURN STOP RECAPTURE: ! JLK SUBROUTINE TO BREAK LINK %IF ST_FLAGS=1 %THEN %START; ! RECAPTURABLE I=ST_LINK %IF SFC FITTED=NO %OR I&DDBIT=0 %THEN %C AMTDD(I)=AMTDD(I)!STXMASK %ELSE %C I=I&(\DDBIT) %AND DRUMT(I)=STXMASK ST_FLAGS=0 %FINISH *J_%TOS %END !----------------------------------------------------------------------- %ROUTINE DEADLOCK !*********************************************************************** !* CALLED WHEN THE NUMBER OF PROCESSES NOT WAITING ON A PAGE FAULT * !* IS LESS THAN THE NUMBER OF OCPS TO EXECUTE THEM.THIS ROUTINE GOES* !* DOWN THE LIST OF GET EPAGES UNTIL IT FIND A PROCESS AND GIVES IT * !* PAGE ZERO AS A SIGNAL TO DEPART. NEEDS STORE SEMA TO CHECK FOR * !* A DEADLOCK AND THE MAINQSEMA FOR SUPPOFFING * !*********************************************************************** %RECORD(PARMF) P %INTEGER I,N,K %IF MULTIOCP=YES %THEN %START *INCT_(STORESEMA) *JCC_8, SEMALOOP(STORESEMA) SEMAGOT: %FINISH %UNLESS PAGEFREES<=1 %AND GETEPN>=MPLEVEL+1-COM_NOCPS %START %IF MULTIOCP=YES %THEN STORESEMA=-1 %RETURN; ! NOT A TRUE DEADLOCK %FINISH N=GETEPN GETEPN=GETEPN-1; ! ASSUMES WE WILL CURE DEADLOCK %IF MULTIOCP=YES %THEN STORESEMA=-1 %CYCLE I=1,1,4*N; ! ALLOW FOR PLENTY OF OTHER RQS SUPPOFF(SERVA(5),P); ! TAKE A GET PAGE REQUEST %IF (P_SRCE=X'40003' %AND LOCSN0>16<=LOCSN1) %OR %C 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) ASEMAGOT: %FINISH ->ACT(P_DEST&X'F') !----------------------------------------------------------------------- ACT(0): ! INITIALISE %IF MULTIOCP=YES %THEN STORESEMA=-1 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 %THEN %START %IF DRUMSIZE=0 %THEN DRUMTASL=DTEND %ELSE %START %CYCLE I=0,1,DRUMSIZE-2 DRUMT(I)=I+1 %REPEAT DRUMT ASL BTM=DRUMSIZE-1 DRUMT(DRUMT ASL BTM)=DTEND DRUMTASL=0 DRUMALLOC=0 %IF MONLEVEL&1#0 %THEN %START 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 %THEN %START; ! THIS DA ALREADY IN TABLE %IF AMT_LEN#LEN %THEN %START %IF AMT_USERS#0 %THEN AMTX=-3 %AND ->RETURN %IF AMT_LENRETURN;! EXTEND ? %CYCLE I=AMT_DDP+LEN,1,AMT_DDP+AMT_LEN-1 ! RETURN IF STILL IN USE %IF AMTDD(I)&STXMASK#STXMASK %THEN %C AMTX=0 %AND ->RETURN %REPEAT DEALLOCDD(AMT_DDP+LEN,AMT_LEN-LEN) AMT_LEN=LEN %FINISH AMT_USERS=AMT_USERS+1; ! USERS ->RETURN %FINISH AMTX=AMT_LINK %REPEAT %IF AMTASL=0 %THEN %START; ! NO AMT CELLS FREE ! TRY TO APPEND EPAGE TO AMTA AMTX=-1 %IF AMTANEXT>=MAXAMTAK %THEN ->RETURN;! ALREADY MAX SIZE REALAD=NEW EPAGE %IF REALAD<=0 %THEN ->RETURN; ! NO FREE EPAGE APPENDAMTA(EPAGESIZE<<10,REALAD) %FINISH ! ALLOCATE NEW SPACE GARB=0; ! NOT GARBAGE COLLECTED YET %CYCLE %IF DDASL(LEN)#0 %THEN %START 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 %THEN %START DDASL(I)=AMTDD(DDX) AMTDD(DDX+LEN)=DDASL(I-LEN) DDASL(I-LEN)=DDX+LEN ->SETAMT %FINISH I=I+1 %REPEAT ! NO HOLES BIG ENOUGH %IF GARB#0 %THEN AMTX=-2 %AND ->RETURN;! STILL NOT ENOUGH SPACE 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 %THEN STORESEMA=-1 %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 %THEN %START; ! 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 %THEN %START AMTDD(I)=AMTDD(I)&(\NEWEPBIT) 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 %THEN STORESEMA=-1 Q_DEST=X'40004'; ! ZERO PAGE Q_SRCE=X'80080002' %CYCLE I=0,1,CN-1 Q_P1=CLEARS(I) %IF MULTIOCP=YES %THEN PON(Q) %ELSE %START %IF MONLEVEL&4#0 %THEN %START *LSS_(5); *ST_IT; *LSS_(6); *ST_IC %FINISH PAGETURN(Q) %IF MONLEVEL&4#0 %THEN %START *LSS_(5); *IRSB_IT; *IMYD_1; *ST_%TOS *IAD_(PTIT); *ST_(PTIT) *LSD_(AMIT); *ISB_%TOS; *ST_(AMIT) *LSS_(6); *IRSB_IC; *IMYD_1; *ST_%TOS *IAD_(PTIC); *ST_(PTIC) *LSD_(AMIC); *ISB_%TOS; *ST_(AMIC) PTCALLN=PTCALLN+1 %FINISH %FINISH %REPEAT %FINISH %END %IF CN>0 %THEN %RETURN; ! 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 %THEN STORESEMA=-1 %RETURN; ! AWAIT TRANSFERS %FINISH DEALLOCDD(AMT_DDP,AMT_LEN) DEALLOCAMT %IF MULTIOCP=YES %THEN STORESEMA=-1 %RETURN !----------------------------------------------------------------------- ACT(4): ! ENTERED EVERY 10 SECS %IF MULTIOCP=YES %THEN STORESEMA=-1 %IF SFCFITTED=YES %AND DRUMSIZE#0 %THEN %C I=100*DRUMALLOC//DRUMSIZE %ELSE I=0 %IF SFCFITTED=YES %AND MONLEVEL&1#0 %AND DRUMSIZE#0 %THEN %C 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#"" %THEN %START %IF PROC_STATUS&AMTLOST=0 %AND K1 %THEN HALT OTHER OCP %CYCLE I=1,1,MAXBLOCK %WHILE DDASL(I)#0 %CYCLE J=DDASL(I) DDASL(I)=AMTDD(J) AMTDD(J)=0 %REPEAT %REPEAT FREEMAX=0 I=AMTDDSIZE+1 ALLOC:%WHILE I>1 %CYCLE I=I-1 %IF AMTDD(I)=0 %THEN %START DDX=I %WHILE I>1 %CYCLE I=I-1 %IF AMTDD(I)#0 %THEN DDASLALLOC(I+1,DDX) %AND ->ALLOC %REPEAT DDASLALLOC(1,DDX) %EXIT %FINISH %REPEAT GARB=1 %IF MULTIOCP=YES %AND COM_NOCPS>1 %THEN RESTART OTHER OCP(0) %END %ROUTINE APPENDAMTA(%INTEGER NEWSPACE,REALAD) !*********************************************************************** !* APPEND A NEW EPAGE AT "REALAD" TO THE AMT TABLE. ADD THE LAST * !* NEWSPACE BYTES TO THE TABLE. NEWSPACE=EPAGESIZE FOR ALL EPAGES * !* EXCEPT THE FIRST WHICH HOLDS THE PAGETABLE ALSO. * !*********************************************************************** %INTEGER FIRSTNEW,I,J J=X'80000001'!REALAD %CYCLE I=0,1,EPAGESIZE-1 AMTAPT(I+AMTANEXT)=J+I<<10 %REPEAT AMTANEXT=AMTANEXT+EPAGESIZE FIRSTNEW=AMTASIZE+1 AMTASIZE=AMTASIZE+NEWSPACE//AMTFLEN;! MIGHT WASTE THE ODD RECORD %CYCLE I=FIRSTNEW,1,AMTASIZE-1 AMTA(I)_LINK=I+1 %REPEAT AMTA(AMTASIZE)_LINK=AMTASL AMTASL=FIRSTNEW %END !----------------------------------------------------------------------- %ROUTINE APPENDAMTDD(%INTEGER NEWSPACE,REALAD) !*********************************************************************** !* APPEND A NEW EPAGE TO AMTDD. PARAMETERS AS FOR APPENDAMTA * !*********************************************************************** %INTEGER FIRSTNEW,I,J J=X'80000001'!REALAD %CYCLE I=0,1,EPAGESIZE-1 AMTDDPT(I+AMTDDNEXT)=J+I<<10 %REPEAT AMTDDNEXT=AMTDDNEXT+EPAGESIZE FIRSTNEW=AMTDDSIZE+1 AMTDDSIZE=AMTDDSIZE+NEWSPACE//DDFLEN FREEMAX=0 DDASLALLOC(FIRSTNEW,AMTDDSIZE) %END !----------------------------------------------------------------------- %ROUTINE DDASLALLOC(%INTEGER FROM,TO) !*********************************************************************** !* CHOP UP AMTDD (FROM:TO) INTO AS MANY MAXIMUM SIZED BLOCKS * !* AS POSSIBLE AND A LEFTOVER * !*********************************************************************** %INTEGER LEN %CYCLE LEN=TO-FROM+1 %IF LEN>=MAXBLOCK %THEN %START AMTDD(FROM)=DDASL(MAXBLOCK) DDASL(MAXBLOCK)=FROM FREEMAX=FREEMAX+1 FROM=FROM+MAXBLOCK %FINISH %ELSE %START %IF FROM<=TO %THEN %C 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 %FINISH %ELSE %START J=AMTDD(I)&STXMASK %IF J#STXMASK %THEN STORE(J)_FLAGS=0 %FINISH AMTDD(I)=0 %REPEAT I=DDASL(LEN) AMTDD(DDX)=I DDASL(LEN)=DDX %END !----------------------------------------------------------------------- %END !----------------------------------------------------------------------- %IF MONLEVEL&X'1C'#0 %THEN %START %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",""(15), "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 %THEN %START 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 "%C ."% OF % OF INSTRNS AVERAGE (SECS) (MSECS) TOTAL " %C ."NON-IDLE SUPVSR ") TOTAL=0 %CYCLE I=0,1,LOCSN0+3 S=SERVROUT(I) %IF S#"" %THEN %START PRINT STRING(" ".S.STRSP(16-LENGTH(S)).STRPRINT( %C PERFORM_SERVN(I),9,0)) %IF PERFORM_SERVN(I)=0 %THEN NEWLINE %ELSE %START SERVTIME=COM_ITINT*PERFORM_SERVIT(I) PRINT STRING(STRPRINT(SERVTIME/1000000,6,3). %C STRPRINT((SERVTIME/1000)/PERFORM_SERVN(I),6,3). %C STRPRINT(100*SERVTIME/PERIOD,7,1)."%". %C STRPRINT(100*SERVTIME/(PERIOD-IDLETIME),6,1). %C "%".STRPRINT(100*SERVTIME/(PERIOD-IDLETIME- %C PROCTIME),6,1)."%".STRPRINT(PERFORM_SERVIC(I),11,0)%C .STRPRINT(PERFORM_SERVIC(I)/PERFORM_SERVN(I),8,0)." ") TOTAL=TOTAL+SERVTIME %FINISH %FINISH %REPEAT PRINT STRING(" INTERRUPT/ACTIVATE ETC.=".STRPRINT((PERIOD-TOTAL)/1000000,1,3). %C " SECS (".STRPRINT(100*(PERIOD-TOTAL)/PERIOD,1,1)."%) SEMALOCKOUT=".STRPRINT(SEMATIME/1000000,1,3).%C "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&8#0 %THEN %START 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 %THEN %START 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 %THEN %EXIT; ! 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 %THEN %START %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&8#0 %THEN %START %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 %THEN %START %CYCLE I=0,1,MAXCAT STROBEN(I)=0 STREPN(I)=0 STROUT(I)=0 SEQOUT(I)=0 %REPEAT %FINISH %END %FINISH !----------------------------------------------------------------------- %IF MULTIOCP=YES %THEN %START %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 ISAD=X'42000000'!REMOTE PORT<<20 %IF BASIC PTYPE<=3 %START; ! P2&P3 ISAD=ISAD!X'6014' VAL=X'80' %FINISH %ELSE %START; ! 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 * !* OTHER DACTS DESCRIBED IN COMMENTS * !*********************************************************************** %IF MULTIOCP=YES %THEN %START %INTEGERFNSPEC SMAC PORT(%INTEGER OPEN,PORT) %SWITCH DACT(0:7),CIN,COFF(1:3) %INTEGER DEV,IDENT,I,J,K,MYPORT,HISPORT,STACK,ACT,TOPST,BLKSIZE, %C CONFIG,BLKS,REALAD %LONGINTEGER PSTE %RECORD(STOREF)%NAME ST %OWNINTEGER PAGESONOFF,OCPGOING=0 %STRING(6)DEVNAME,ONOFF %CONSTSTRING(5)%ARRAY DEVS(1:3)="OCP ","SAC ","SMAC "; %IF MONLEVEL&2#0 %AND KMON&1<<17#0 %THEN %C PKMONREC("CONFIG CONTROL",P) DEV=P_P1>>16 IDENT=P_P1&X'FFFF' %IF 1<=DEV<=3 %THEN DEVNAME=DEVS(DEV) %ELSE %START DEVNAME="??? " ->FAIL %FINISH %IF DEV=3 %THEN TOPST=(((PST(STORESEG)>>32&X'3FF80'+128) %C -ADDR(STORE(0))&X'3FFFF')//STOREFSIZE)-1 *LSS_(3); *USH_-26 *AND_3; *ST_MYPORT HISPORT=MYPORT!!1 ACT=P_DEST&15 ->DACT(ACT) DACT(0): ! CONFIGURE OFF ->COFF(DEV) DACT(1): ! CONFIGURE ON ->CIN(DEV) COFF(1): ! CONFIGURE OFF OCP ->FAIL %UNLESS COM_NOCPS=2 %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 BASIC PTYPE<=3 %START I=X'42056011'!IDENT<<20 *LB_I; *LSS_X'80010000' *ST_(0+%B) %FINISH %ELSE %START *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 CIN(1): ! CONFIGURE IN AN OCP ->FAIL %UNLESS COM_NOCPS=1 %AND 2<=IDENT<=3 %AND %C IDENT#COM_OCPPORT0 ->FAIL %UNLESS 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 STACK=2*IDENT+8 %IF 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'80040000'+STACK<<18)#0 %THEN %C COM_NOCPS=1 %AND J=SMACPORT(1,HISPORT) %AND ->FAIL %IF BASIC PTYPE<=3 %START *LSS_1; *ST_(X'6009') %FINISH %ELSE %START *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 ->SUCC 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 %IF SFC FITTED=YES %AND DRUMSIZE>0 %START P_DEST=X'380007' P_SRCE=X'110003' P_P2=IDENT PON(P) %RETURN %FINISH DACT(3): ! REPLY FROM DRUM(ALWAYS OK) 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'110006' P_P2=IDENT PON(P) %RETURN DACT(6): ! REPLY FROM GPC ->SAC USED %UNLESS P_P2=0 %IF COM_NOCPS>1 %AND MYPORT#COM_OCPPORT0 %THEN %C DPON(P,1) %AND %RETURN I=X'8'>>IDENT %IF BASIC PTYPE<=3 %START I=I!I<<4 *LSS_(X'600A'); *OR_I; *ST_(X'600A') %FINISH %ELSE %START I=(I<<12!I<<2)!!(-1) *LSS_(X'4012'); *AND_I; *ST_(X'4012') %FINISH COM_NSACS=1 COM_SACPORT0=IDENT!!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 %C 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') %FINISH %ELSE %START 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 COM_NSACS=2 ->SUCC COFF(3): ! CONFIGURE OFF A SMAC ->FAIL %UNLESS 0FAIL %UNLESS 1<FAIL %UNLESS X'10000'<FAIL %IF SMAC RCONFIG#0; ! ALREADY RECONFIGURING ->FAIL %UNLESS SAFE IS READ(COM_SDR4!IDENT< SEMALOOP(STORESEMA) SSEMAGOT1: %CYCLE I=1,1,TOPST ST==STORE(I) %IF ST_REALAD>>22&15=IDENT %START PAGESONOFF=PAGESONOFF+1; ! IN RIGHT SMAC %IF ST_REALAD<0 %THEN J=J+1;! COUNT FLAWED ONES TO ! REMEMBER 8K PHOTO AREA IN SMAC1 %IF IDENT=1 %AND ST_USERS=255 %AND ST_REALAD&X'3FFFFF' %C FAIL;! SHOULD NOT OCCUR %FINISH %REPEAT SMAC RCONFIG=IDENT SMAC RPAGES=PAGES ONOFF-J ! ! GRAB ANY FREE PAGES FROM FREE LIST AT ONCE ! SMAC RPAGES=SMAC RPAGES-1 %WHILE QUICK EPAGE(1,1<0 STORE SEMA=-1 P_DEST=X'3000D' P_SRCE=X'110004' PON(P); ! KICK SCHEDULE TO FREE STORE P_DEST=X'110004' P_P2=0 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 %IF SMAC RPAGES#0 %%START P_P3=SMAC RPAGES; ! DEBUGGING ONLY DPON(P,1) %RETURN %UNLESS P_P2>15 %AND PAGEFREES=0 %AND DONT SCHED#0;! CONTINUE WAITING %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 %RETURN %UNLESS SMAC RPAGES=0 %FINISH ! ! CLEAR OUT STORE & PUBLIC SEGMENT TABLES ! J=64+16*SMAC RCONFIG PST(I)=0 %FOR I=J,1,J+15 %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 ! 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 COM_SBLKS=J ! ! FINISH OFF INCLUDING CLOSING SAC PORT UNLESS INTERLEAVED ! J=SMAC RCONFIG!!8; ! INTERLEAVED SMAC %IF COM_SMACS&1<SUCC CIN(3): ! CONFIGURE IN A SMAC ->FAIL %UNLESS 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 %EXIT %IF 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' SEMALOOP(STORESEMA) %CYCLE I=COM_SBLKS,1,COM_SBLKS+BLKS-1 REALAD=BLOCKAD(I) J=X'20000'; ! HALF A SEGMENT %IF REALAD&X'20000'#0 %THEN J=X'40000' PST(64+REALAD>>18)=PSTE!(REALAD&X'FFFC0000') ! %C LENGTHENI(J-X'80')<<32 %CYCLE J=0,1,SEGEPSIZE//2-1 K=K+1 %WHILE STORE(K)_REALAD#0 STORE(K)_REALAD=REALAD+EPAGESIZE*1024*J P_P2=K; ! STORE INDEX RETURN EPAGE(P) %REPEAT %REPEAT J=PAGES ONOFF*OVERALLOC PERCENT//100 UNALLOCEPS=UNALLOCEPS+PAGESONOFF+J OVERALLOC=OVERALLOC+J MAX OVERALLOC=MAXOVERALLOC+J COM_SEPGS=COM_SEPGS+PAGESONOFF COM_SBLKS=COM_SBLKS+BLKS COM_SMACS=COM_SMACS!1<SUCC DACT(2): ! FINISH CONFIGURIN OFF HIM %IF OCPGOING=0 %THEN DEVNAME=DEVNAME.TOSTRING(17) OCPGOING=0; ! IF DUE TO FAILURE FLASH MSG COM_NOCPS=1; COM_OCPPORT0=MYPORT COM_OCPPORT1=HISPORT J=SMACPORT(1,HISPORT); ! CLOSE OFF HIS SMAC PORT SUCC: %IF ACT&1=0 %THEN ONOFF="OFF" %ELSE ONOFF="ON" OPMESS(DEVNAME.STRINT(IDENT)." CONFIGURED ".ONOFF) %RETURN FAIL: ! UNKNOWN DEVICE OR OTHERS OPMESS("CANNOT CONFIGURE ".DEVNAME.STRINT(IDENT)) %RETURN %INTEGERFN SMAC PORT(%INTEGER OPEN,PORT) !*********************************************************************** !* OPEN (OPEN=0) %OR CLOSE A SMAC PORT IN ALL ONLINE SMACS * !*********************************************************************** %INTEGER I,J,K,L,VAL,RES K=X'20'>>PORT L=K!!(-1) %IF OPEN=0 %THEN K=0 RES=0 %CYCLE I=0,1,15 %IF 1<1 %THEN HALT OTHER OCP *LSS_X'382E'; *ST_(3); ! No unwanted interrupts %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 %THEN %CONTINUE; ! 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) %ELSE %C %IF J=3 %THEN PP_DEST=9 %AND GPC(PP) %FINISH J=X'40000800'!I<<16 *LB_J; *LSS_2; *ST_(0+%B) %FINISH %REPEAT %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, %C 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 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; ! %BITARRAY (0:MAXAS) %INTEGERARRAY OLDASWIPS(0:MAXRESIDENCES) %CONSTLONGINTEGER LTOPBIT=X'8000000000000000' %CONSTINTEGER TOPBIT=X'80000000' !----------------------------------------------------------------------- ! LOCAL STACKS INFORMATION %BYTEINTEGERARRAY LSTKSSN(1:LSTKN) !----------------------------------------------------------------------- ! CATEGORY INFORMATION %INTEGER EPLIM,EPN,RTLIM,RTN !----------------------------------------------------------------------- %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, %C NEWSTK,STOREX,DEST,SRCE,SUSP,SNOOZES,DA,LASTDA,NONSEQVSIS, %C XSTROBE,SEGLEN,PTEPS,ASDESTROY,PTP,ASP,ASB,OUTN,PTE, %C PROCACTAD1,PROCACTAD2,HIGHSEG,LOCKST,LOCKSTX,LTAD,TSTPTR %IF MONLEVEL&4#0 %THEN %START %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(-3:0) %CONSTINTEGER MAXDIROUT=28 %CONSTLONGINTEGER DGLAEPAGES=8; ! 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+%C LENGTHENI(DIRCSEGL)<<32 ALLOUTP==DIROUTP %IF MONLEVEL&4#0 %START MONVAD=0 %IF PROC_STATUS&4=0 %THEN LPIT==PERFORM_SERVIT(LOCSN0+2) %C %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 ASWIP=0 PROCACTAD1=X'28000004' PROCACTAD2=ADDR(PROC_ACTW0); ! %INTEGERNAME DESCRIPTOR SUSP=0 ASDESTROY=0 ! FILL IN SCTI(3)[ALIGNED] INTEGER(SCTI0+24)=X'38000004' INTEGER(SCTI0+28)=SCTJ30 ! 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-1)_DA=P_P2+MAXBLOCK CBTA(CBTLEN-1)_TAGS=MAXBLOCK-1 CBTA(CBTLEN-1)_LINK=CONTINUATN BLK LST(3)=X'400003FF00000000'!DIRACR<<52!DIRACR<<56! %C (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 %THEN %START; ! 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'01800BFE'; ! ONLY EVENT PENDING & 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 %C 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 %C 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 %C 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 %C RECORD(K+X'100')<-ISTDUM ! SET INSTRUCTION COUNTER IST ENTRY *JLK_ ; *LSS_%TOS ; *ST_I ISTDUM_PC=I RECORD(J+X'160')<-ISTDUM %IF MULTIOCP=YES %THEN %C 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 %C 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'01800BFE' *STSF_I LSSNP1_SF=I LSSNP1_IT=MAXIT LSSNP1_IC=MAXIT LSSNP1_CTB=0 %FINISH !----------------------------------------------------------------------- ! SET UP DIRECTOR CONTEXT NEWSTK=LSTKSSN(1)<<18 SSNP1==RECORD(NEWSTK!X'40000') SSNP1=0 SSNP1_LNB=NEWSTK SSNP1_PSR=X'00040001'!DIRACR<<20; ! PROG ERRORS UNMASKED SSNP1_PC=X'00080010'; ! TO M-C CODE DIRLOADER SSNP1_SSR=X'01800000'; ! ALL INTS ALLOWED SSNP1_SF=NEWSTK!X'14'; ! 5 WORDS ON FROM LNB SSNP1_IT=0 SSNP1_IC=MAXIT SSNP1_B=DIROUTPAD SSNP1_DR0=X'B1000000'; ! DESCRIPTOR 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) !----------------------------------------------------------------------- ! 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'01800FFF'; ! 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 %THEN %START *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 %C 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 PROC_EPN=0 HIGHSEG=2 RETIME: ! START NEW TIMESLICE SSNP1==RECORD(PROC_STACK!X'40000');! PROCESS CONTEXT %IF SSNP1_IT&X'FF800000'=0 %THEN %START %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 %THEN %START %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'FFFFFFF5'; *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 !----------------------------------------------------------------------- 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). %C " TERMINATED") %AND NEWSTK=PROC_STACK %AND ->TERMINATE %IF I=X'FFFE' %THEN %START *OUT_99; ! CRASH WITH MASKED OUT INT %FINISH %UNLESS I=1 %THEN ->SIGINT INTMESS<-P_INTMESS %IF LENGTH(INTMESS)=1 %THEN %START %IF P_P2>=0 %AND IOSTAT_IAD#P_P2 %THEN IOSTAT_IAD=P_P2 SIGINT: SIGOUTP<-P SIGOUTP_TYPE=3 SIGOUTP_SSN=CURSSN SIGOUTP_SSNAD=PROC_STACK SIGOUTP_SUSP=SUSP; ! PRESERVE SUSPEND STATUS SUSP=0 NEWSTK=LSTKSSN(2)<<18 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 %C %OR SSNP1_PSR&3=0 %THEN PRINT STRING(" ACTIVATE CONTEXT INVALID") %AND ->TERMINATE ->ACTIVATE %FINISH %ELSE %START %IF LENGTH(INTMESS)>1 %THEN IOSTAT_INTMESS=INTMESS %IF P_P2>=0 %AND IOSTAT_IAD#P_P2 %THEN %START IOSTAT_IAD=P_P2 %IF SUSP<0 %THEN SUSP=0 %FINISH RESUSP: ! **** 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 %THEN %START 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 %THEN %START %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 *LSS_%TOS; ! PARAMETER *ST_VSPARM %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 %THEN %START 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 %THEN %START *INCT_(STORESEMA) *JCC_8, SEMALOOP(STORESEMA) SSEMAGOT: %FINISH %IF FREE EPAGES>0 %THEN STOREX=QUICK EPAGE(0,-1) %AND %C STORESEMA=-1 %AND ->ACT9 POUT_SRCE=ME!9 POUT_P2=0; ! CLEAR TO ZERO GET EPN=GET EPN+1 %IF MULTIOCP=YES %THEN STORESEMA=-1 %IF PAGEFREES<=1 %AND GETEPN>=MPLEVEL+1-COM_NOCPS %THEN %C 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 EPN=EPN+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 %THEN %START;! BLOCK NOT ACTIVE %IF TSTPTR&127=127 %THEN %START;! 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 ASFREE=ASFREE&(\ASB); ! REMOVE BIT %FINISH POUT_DEST=X'80001'; ! GET AMTX POUT_SRCE=0 POUT_P1=PROCESS POUT_P2=CBT_DA POUT_P3=CBT_AMTX<<16!(CBT_TAGS&X'80')<<24!CBT_TAGS ! NEWBIT<<31 ! LENGTH (COMPATIBLY) %IF MONLEVEL&4#0 %THEN %START *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH ACTIVE MEM(POUT) %IF MONLEVEL&4#0 %THEN %START *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 %C POUT_P2=VSPARM; ! NOT USED.FOR KMON ONLY %IF MONLEVEL&4#0 %THEN %START *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH PAGETURN(POUT) %IF MONLEVEL&4#0 %THEN %START *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 CBT_LINK&ADVISORY SEQ#0 %OR %C (VSSEG#PROC_STACK>>18 %AND AS(TSTPTR)<>(64-VSEPAGE)&3=3) %THEN %C PAGEOUT(VSSEG,VSEPAGE-2,CBT) %ELSE NONSEQVSIS=NONSEQVSIS+1 %IF POUT_DEST#0 %THEN PTE=X'80000001'!POUT_P2 %AND ->ACT10 PROC_STATUS=PROC_STATUS!2; ! DEMAND PAGE PRIORITY ->RETURN !----------------------------------------------------------------------- ACTIVITY(10): ! EPAGE HERE ! P_P1=RUBBISH IDENT ! P_P2=STORE(EPAGE)_REALAD ! VSSEG,VSEPAGE&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 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 ? 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 %THEN %START PROC_RUNQ=CATTAB(PROC_CATEGORY)_RQTS2 %IF MONLEVEL&1#0 %THEN %C UPDISP(PROCESS,11,"R".TOSTRING(PROC_RUNQ+'0')) %FINISH %ELSE %START %IF RTN=RTLIM %THEN %START POUT_DEST=X'3000B'; ! MORE TIME ON THE FLY ? POUT_SRCE=0 POUT_P1=PROCESS POUT_P2=EPN %IF MONLEVEL&4#0 %THEN %START %IF MONVAD>0 %THEN GARNER(7,2<<24!PROC_CATEGORY<<16!EPN) *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH SCHEDULE(POUT) %IF MONLEVEL&4#0 %THEN %START *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 %THEN %START 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 %FINISH %ELSE %START 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 RUNQ1#0 %OR (PREEMPTED!RUNQ2#0 %AND PROC_RUNQ=2) %START POUT_DEST=ME!2 PON(POUT) ->RETURN %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 EPLIM0 %THEN GARNER(7,3<<24!PROC_CATEGORY<<16!EPN) *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH SCHEDULE(POUT) %IF MONLEVEL&4#0 %THEN %START *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 %THEN %START EPLIM=POUT_P1 RTLIM=POUT_P2 RTN=0 STROBE(0) %IF POUT_P3#0; ! NEWCAT_STROBEI#0 ->ACTIVATE %FINISH %FINISH %IF XSTROBE<0 %THEN %START; ! 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 PON(POUT) ->RETURN !----------------------------------------------------------------------- ACTIVITY(7): ! MORE ALLOCATION AVAILABLE !----------------------------------------------------------------------- PROGERRI:*JLK_%TOS ! PROGRAM ERROR INTERRUPTS ENTER HERE *LSS_%TOS *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 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 SIGOUTP_P1=PEPARM SIGOUTP_P2=PROC_STACK SIGOUTP_TYPE=2 SIGOUTP_SSN=CURSSN SIGOUTP_SSNAD=PROC_STACK SIGOUTP_SUSP=0 NEWSTK=LSTKSSN(2)<<18 %IF PROC_STACK=NEWSTK %THEN %START PRINT STRING("PROGRAM ERROR ON SIGNAL STACK CLASS="%C .STRINT(PEPARM&255)." SUBCLASS=".STRINT(PEPARM>>8&255)." ") ->TERMINATE %FINISH ->SIGACT !----------------------------------------------------------------------- OUTI:*JLK_%TOS ! LOCAL OUTS ENTER HERE *LSS_%TOS *ST_J *LSS_%TOS *ST_OUTN %IF 0<=OUTN<=MAXDIROUT %THEN %START %IF PROC_STACK=LSTKSSN(2)<<18 %AND 1< ILLEGAL OUT ! ALLOWS OUT 0,1,3,6,8,10,14,15 ! 16,19,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 %C 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) 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 %IF TSTPTR#127 %THEN ASOUT(TSTPTR) ASDESTROY=0 LST(VSSEG)=LST(VSSEG)&X'FFFFFFFF00000000' %IF TSTPTR=127 %OR ALLOUTP_P2#0 %OR PROCESS<=3 %THEN ->REACT ! ! 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 TSTPTR#127 %AND DCLEARS+PAGEFREES>100 %AND LASTDA#0 %C %AND CHECKDA(LASTDA)>0 %THEN WAIT(16,1) %AND ->RETURN LASTDA=DA ->REACT !----------------------------------------------------------------------- DIROUT(4): ! NOT USED ->FREACT !----------------------------------------------------------------------- DIROUT(5): ! PON FOR DIRECTOR SRCE=PROCESS+LOCSN1 DIRPONS: ! OTHER PONS JOIN HERE DEST=ALLOUTP_DEST>>16 %IF DEST=X'FFFF' %THEN %START; ! RELAY MESSAGE %IF FIND PROCESS=0 %THEN ->ACTIVATE;! NOT LOGGED ON %FINISH %ELSE %START %UNLESS 0<=DESTFREACT %FINISH %IF DEST#0 %THEN %START 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 MULTIOCP=YES %THEN ->ONBRUNQA %ELSE ->ONFRUNQA ! IN SINGLES KERNEL SERVICES ! WILL ALWAYS COMPLETE BEFORE ! REENTRY. NOT SO IN DUALS HENCE ! DIFFERENCES ESPECIALLY FOR ! ROUTINE UPDATE OUTPUT !----------------------------------------------------------------------- ACTIVITY(12): ! RE-ENTRY AFTER DIRECTOR PON PROC_STATUS=PROC_STATUS&(\2) %IF SRCE>LOCSN3 %THEN %START %IF SERV3_P<<2#0 %THEN ->ASYNCH %FINISH %ELSE %START 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 %THEN %START ->DEPART %IF PROC_STATUS&AMTLOST#0 %IF NONSEQVSIS>1 %OR XSTROBE<0 %THEN STROBE(1) I=EPN*COM_USERS>>1 ->DEPART %UNLESS I0 %THEN GARNER(5,EPN) SUSP=SRCE; ->RETURN %FINISH %FINISH ACTIVITY(8):DEPART: ! SUSPED BUT MUST NOW GO WORKSET(1) %IF MONLEVEL&4#0 %AND MONVAD>0 %THEN %C GARNER(7,1<<24!PROC_CATEGORY<<16!EPN) 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' %THEN %START %IF FIND PROCESS=0 %THEN ->ACTIVATE %FINISH %ELSE %START %UNLESS 0<=DESTFREACT %FINISH %IF DEST#0 %THEN %START; ! 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) ->ONFRUNQ %FINISH ! DEST=0 TOFF & CONTINUE %IF SRCE>LOCSN3 %THEN %START %IF SERV3_P<<2#0 %THEN ->ASYNCH ALLOUTP_DEST=0 %FINISH %ELSE %START SERV==SERVA(SRCE) %IF SERV_P<<2#0 %THEN SUPPOFF(SERV,ALLOUTP) %C %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 %THEN %START *INCT_SCHEDSEMA *JCC_8, SEMALOOP(SCHEDSEMA) SSEMAGOT1: %FINISH MPLEVEL=MPLEVEL-1; ! DECREASE MPLEVEL&CHECK DEADLOCKS %IF PAGEFREES<=2 %AND 0=MPLEVEL-1 %THEN %C P_DEST=X'20000' %AND PON(P) %IF MULTIOCP=YES %THEN SCHEDSEMA=-1 ->RETURN; ! WAIT IN STORE FOR REPLY !----------------------------------------------------------------------- ACTIVITY(13): ! REPLY TO PON & WAIT IN STORE %IF MULTIOCP=YES %THEN %START *INCT_SCHEDSEMA *JCC_8, SEMALOOP(SCHEDSEMA) SSEMAGOT2: %FINISH MPLEVEL=MPLEVEL+1 PROC_RUNQ=J %IF MULTIOCP=YES %THEN SCHEDSEMA=-1 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 %C 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 %C %ELSE ALLOUTP==DIROUTP ->RESUSP !----------------------------------------------------------------------- DIROUT(15): ! SYSTEM CALL ERROR ! (AFTER STACK SWITCH) ! SUB-IDENT. IN OLD XNB PEPARM=INTEGER(PROC_STACK!X'40020')<<6!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 %THEN %EXIT K=CHECKDA(K) %IF K#0 %THEN %START %IF K<0 %AND J>0 %THEN %C OPMESS("? BLK ACTIVTY ".STRHEX(INTEGER(DIROUTPAD+4*I)))%C %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 %C %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 MONLIM=MONVAD+INTEGER(MONVAD+8) MONVAD=0 %AND ->FREACT %UNLESS %C CHECKRES(0,INTEGER(MONVAD+8),MONVAD)=0 MONPTAD=INTEGER(LOCKST&X'0FFFFFF0'+VIRTAD+8*(MONVAD>>18)+4)%C &X'0FFFFFF0'+VIRTAD ->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&4#0 %START *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH COMMS CONTROL(ALLOUTP) %IF MONLEVEL&4#0 %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 %C %THEN ->FREACT %IF LOCKST=0 %THEN %START; ! NO SEG TABLE AROUND ->FREACT %UNLESS ALLOUTP_P1>0 %IF MULTIOCP=YES %THEN %START *INCT_(STORESEMA) *JCC_8, SEMALOOP(STORESEMA) SSEMAGOT3: %FINISH %IF FREE EPAGES>0 %THEN %START STOREX=QUICK EPAGE(0,-1) %IF MULTIOCP=YES %THEN STORESEMA=-1 ->ACTF %FINISH POUT_SRCE=ME!X'F' POUT_P2=0; ! CLEAR TO ZERO GET EPN=GET EPN+1 %IF MULTIOCP=YES %THEN STORESEMA=-1 %IF PAGEFREES<=1 %AND GETEPN>=MPLEVEL+1-COM_NOCPS %THEN %C 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 %FINISH %ELSE 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' %C !(LTAD-VIRTAD) %FINISH %ELSE %START; ! UNLOCK AREA %IF LONGINTEGER(K+8*VSSEG)=0 %THEN ->FREACT LTAD=(INTEGER(K+8*VSSEG+4)&X'0FFFFFF0'+VIRTAD) INTEGER(LTAD)=INTEGER(K+4) INTEGER(K+4)=LTAD-K LONGINTEGER(K+8*VSSEG)=0 LOCKST=LOCKST-1<<28 %IF LOCKST>>28=0 %START POUT_DEST=X'60000' POUT_P2=LOCKSTX P_SRCE=ME!15 %IF MONLEVEL&4#0 %THEN %START *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH RETURN EPAGE(POUT) %IF MONLEVEL&4#0 %THEN %START *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 %FINISH %ELSE %START POUT_DEST=X'40002'; ! PAGE OUT TO UNLOCK POUT_SRCE=0 POUT_P2=8+4; ! WRITTEN TO+UPDATE DRUM %FINISH POUT_P1=CBT_AMTX<<16!EPX %IF MONLEVEL&4#0 %THEN %START *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH PAGETURN(POUT) %IF MONLEVEL&4#0 %THEN %START *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 %C 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&4#0 %THEN %START *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH ACTIVE MEM(POUT) %IF MONLEVEL&4#0 %THEN %START *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 %THEN %RESULT=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 %THEN %START; ! PREVIOUS SEGMENT %IF CBT_LINK&CONTINUATN BLK=0 %THEN %RETURN 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 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 %C I=I!4; ! TO DRUM IF THERE IS ONE P_P2=I %IF MONLEVEL&4#0 %THEN %START %IF MONVAD>0 %THEN %C GARNER(3+I>>3,VSSEG<<18!VSEPAGE<<12) *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH PAGETURN(P) %IF MONLEVEL&4#0 %THEN %START *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 EPN=EPN-1 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 ASDESTROY=0 %AND %C 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) 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 %THEN %START %IF MONVAD>0 %THEN %C GARNER(1+POFL>>3,VSSEG<<18!VSEPAGE<<12) *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH PAGETURN(POUT) %IF MONLEVEL&4#0 %THEN %START *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 %REPEAT PROC_EPN=EPN NOP: CBTP=SST(VSSEG) CBT==CBTA(CBTP) %CYCLE %IF CBT_TAGS&X'20'#0 %THEN %START POUT_DEST=X'80002'; ! RETURN AMTX POUT_SRCE=0 POUT_P1=PROCESS POUT_P2=CBT_AMTX POUT_P3=ASDESTROY; ! DESTROY FLAG %IF MONLEVEL&4#0 %THEN %START *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH ACTIVE MEM(POUT) %IF MONLEVEL&4#0 %THEN %START *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) ! ! 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, %C PTEAD,I %IF MONLEVEL&16#0 %THEN %START %INTEGER CAT %FINISH %LONGINTEGER EPMASK ASMASK=ASWAP; ! ALL SLOTS WITH ACTIVE PAGES ASP=-1 %IF MONLEVEL&16#0 %THEN %START 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 %THEN %CONTINUE 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 %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 %THEN %START %IF MONVAD>0 %THEN %C GARNER(3+POFL>>3,VSSEG<<18!VSEPAGE<<12) *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH PAGETURN(POUT) %IF MONLEVEL&4#0 %THEN %START *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 AS(ASP)=AS(ASP)&(\(LTOPBIT>>VSEPAGE)) %FINISH %REPEAT %IF AS(ASP)=0 %THEN %START ASB=TOPBIT>>ASP ASWAP=ASWAP&(\ASB) ASWIP=ASWIP!ASB %FINISH %REPEAT 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) 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 %THEN %START %IF MONVAD>0 %THEN %C GARNER(1+POFL>>3,VSSEG<<18!VSEPAGE<<12) *LSS_(6); *ST_IC; *LSS_(5); *ST_IT %FINISH PAGETURN(POUT) %IF MONLEVEL&4#0 %THEN %START *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 %THEN EPN=EPN-1 %REPEAT AS(ASP)=0 %REPEAT 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 %CYCLE I=MAXRESIDENCES-1,-1,0 J=J&OLD ASWIPS(I) %IF I 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' %C +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 %THEN %START *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) %THEN %RESULT=I %REPEAT MONITOR("CURRENT STACK ?") %END !----------------------------------------------------------------------- %ROUTINE WAIT(%INTEGER DACT,N) POUT_DEST=X'A0002' POUT_SRCE=0 POUT_P1=ME!DACT POUT_P2=N PON(POUT) %END !----------------------------------------------------------------------- %END !----------------------------------------------------------------------- %END !*********************************************************************** !* THESE THREE ROUTINES ARE SYTEMCALLED DIRECTLY FROM USER * !*********************************************************************** %EXTERNALINTEGERFN REQUEST INPUT(%INTEGER OUTPUT POSN,TRIGGER POSN) %UNLESS IOSTAT_OUTBUFLEN>0 %AND 0<=OUTPUT POSN0 %AND 0<=TRIGGER POSN0 %AND 0<=OUTPUT POSN