! ! To make S series supervisor requires:- ! 1) Change SSERIES=NO to SSERIES=YES in ctoptions file ! ! ! THESE CONST INTEGERS DEFINE SIZES AND LAYOUT OF IMPORTANT TABLES ! THEY HAVE TO BE HERE TO BE GLOBAL TO ALL ROUTINES INCLUDING IO ONES ! CONSTINTEGER LSTLEN=192; ! LOCAL SEGMENT TABLE LENGTH CONSTINTEGER CBTLEN=299; ! LENGTH OF CBT TABLE CONSTLONGINTEGER LCACR=1; ! ACR OF LOCAL CONTROLLER CONSTINTEGER DIRCSEG=10; ! SEG NO OF DIRECTOR COMMS SEG CONSTINTEGER DIRCSEGOFFSET=0; ! FOR ALIGNMENT IF NEEDED CONSTINTEGER DIRCSEGAD=DIRCSEG<<18; ! VIRTUAL ADDRESS OF DIR COM SEG CONSTINTEGER DIRCSEGL=8*CBTLEN+255+2*LSTLEN; ! SIZE OF SAME ! MADE UP OF 2049 FOR CBT ! 2*LSTLEN FOR SST ! 48+64 FOR 2 BITS OF SYTEMCALL TABLE ! 32+48 FOR DIROUTP&SIGOUT CONSTINTEGER LSTACKLEN=3; ! LOCAL CONT. STACK ELEN CONSTINTEGER LSTACKLENP=2; ! PAGED PART CONSTINTEGER LSTKN=3; ! NO OF LOCAL STACKS CONSTLONGINTEGER DIRACR=2; ! DIRECTOR ACR LEVEL CONSTLONGINTEGER NONSLAVED=X'2000000000000000' CONSTINTEGER MAXIT=X'FFFFFF' ! THESE CONST INTEGERS LAYOUT THE DIRECTOR COMMS SEGMENT(LOCAL 10) CONSTINTEGER SCTIENTRIES=6; ! VALID I VALUES FOR SCT CONSTINTEGER SCTI0=DIRCSEGAD+DIRCSEGOFFSET;! SYSTEMCALL INDEX TABLE CONSTINTEGER SCTILEN=SCTIENTRIES*8; ! OF SCTIENTRIES DOUBLE WORDS CONSTINTEGER SCTJ30=SCTI0+SCTILEN; ! 3RD BRANCH OF SC TABLE CONSTINTEGER SCTJ3LEN=4*16; ! 4ENTRIES FOR 3 LC ROUTINES CONSTINTEGER DIROUTPAD=SCTJ30+SCTJ3LEN;! ADDRESS OR DIROUTP CONSTINTEGER DIROUTPLEN=32; ! ONE 32 BYTE RECORD CONSTINTEGER SIGOUTPAD=DIROUTPAD+DIROUTPLEN;! ADDR SIGOUTP CONSTINTEGER SIGOUTPLEN=48; ! ONE 48 BYTE RECORD CONSTINTEGER CBTAD=SIGOUTPAD+SIGOUTPLEN;! CLAIMED BLOCK TABLE AD CONSTINTEGER SSTAD=CBTAD+8*CBTLEN; ! 2DRY SEG TABLE OF LSTLEN BYTES CONSTINTEGER LSTVAD=0; ! VIRTUAL ADDRESS OF LOCAL SEG TABLE !----------------------------------------------------------------------- RECORDFORMAT IOSTATF(INTEGER IAD,STRING (15) INTMESS, C INTEGER INBUFLEN,OUTBUFLEN,INSTREAM,OUTSTREAM) RECORDFORMAT PARMF(INTEGER DEST,SRCE,(INTEGER P1,P2,P3,P4,P5,P6C 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 CALLS ! MADE VIA THE SYSTEM CALL TABLE WILL BE FOR INTERNAL ACCESS AND ! THIS MAY BE DISASTEROUS ! EXTERNALINTEGERFNSPEC REQUEST INPUT(INTEGER OUTPUT POSN,TRIGGER POSN) EXTERNALINTEGERFNSPEC REQUEST OUTPUT(INTEGER OUTPUT POSN,TRIGGER POSN) EXTERNALINTEGERFNSPEC CHANGE CONTEXT LONGINTEGERFNSPEC RTDR(INTEGERFN A) EXTERNALROUTINE SUP29 !----------------------------------------------------------------------- OWNSTRING (3) SUPID="29G" ! MAIN CHANGES FOR 26I !--------------------- ! 1) CHANGES FOR BETTER ACCESSING OF SEQUENTIAL FILES ! TOGETHER WITH REDUCTION IN STROBING ! 2) CHANGES TO PREPAGING LC STACK TO AVOID USING PPCELLS ! 3) PENALISING PROCESS WITH LOTS OF P4 TO P4 TRANSITIONS ! MAIN CHANGES FOR 26J ! -------------------- ! 1) CHANGE TO IMP80 ! MAIN CHANGES FOR 27A ! 1) STORE LIST NOW CONSTRUCTED BY CHOPSUPE ! ! MAIN CHANGES FOR 27B ! 1) INDIVIDUAL TIMEOUTS ON SNOOZING ! ! ! MAIN CHANGES FOR 27C ! 1) CORRECTIONS AND EXTENSIONS TO CODE FOR SPLITTING A DUAL ! SERVICE TO A SINGLE SERVICE AND A DEVLOPMENT M-C ! ! MAIN CHANGES FOR 27D ! 1) CHANGE TO SCHEDULE FOR SMOOTHER TRANSITION FROM SNNOZING ! TO NON-SNOOZING AS LOAD INCREASE PAST OPTIMUM ! ! MAIN CHANGES FOR 27E ! 1) CHANGE TO COLLECTION OF TIMING INFORMATION TO ALLOW ACCESS ! FROM A PRIVILEGED PROCESS ! 2) ON A PAGE FAULT IF A SEGMENT APPEARS TO BE BEING ACCESSED ! SEQUENTIALLY A LOWER NUMBERED PAGE IS REMOVED FROM THE ! WORKING SET. ! ! MAIN CHANGES FOR 27F ! 1) SETTING NONSLAVED BITS ON CONFIGURING IN AN OPC SINCE THE ! IPL MIGHT HAVE BEEN DONE ON A SINGLE! ! MAIN CHANGES FOR 27G ! 1) CHANGES TO SNOOZING TO OMIT READ ONLY PAGES FROM SNOOZ SET ! WHEN STORE IS BUSY PRIOR TO ABANDONING SNOOZING ALLTOGETHER ! MAIN CHANGES FOR 27H ! 1) REMOVING CHANGE 1 OF 27G AFTER DEVASTATING ERTE FIGURES ! 2) IN PROCESS VS MONITORING VIA OUT20 ! MAIN CHANGES FOR 27I ! 1) DIRECT CALLS OF COMMS CONTROLLER FROM REQUEST OUTPUT ! MAIN CHANGES FOR 27J ! 1) DEDICATED FLAG (RECONFIGURE=YES/NO) FOR CONDITIONAL COMPILATION ! OF RECONFIGURE CODE. ! Main changes for 28A ! 1) Fully "S" series compatible. ! 2) Report to OPER on illegal system call ! MAIN CHANGES FOR 28B ! 1) USES THE MULTIPLE CONNECTS BIT IN DRUM WSET COMPUTATION ! 2) REVISION TO SCHEDULING OF P4 JOBS ! Main changes for 28C ! 1) Uses the new GPC/DCU driver 'GDC' ! ! MAIN CHANGES FOR 28D ! 1) CORRECTION TO CLEAR CODE TO STOP FILES BEING RECONNECTED ! BEFORE ALL THE CLEARS HAVE BEEN COMPLETED AND TO PREVENT ! CLEARS OVERWRITING VALID DATA. ! 2) INCORPORATION OF CONDITIONAL "DAP" CODE ! Main changes for 28E ! 1) Changes to multi OCP code to handle dual "S" series processors ! 2) Change to insist on day of week in "DT" command ! 3) Addition of FEDOWN command ! ! Main changes for 29a ! 1) Chanegs to Dap Driver for better interactive access ! MAIN CHANGES FOR 29B ! 1) "DIRECT" STACK MOVED UP 100 EPAGES TO ALLOW MORE FIXED SITES ! MAIN CHANGES FOR 29C ! 1) DAP DRIVER ADAPTED FOR MULTIPLE DAPS ! ! MAIN CHANGES FOR 29D ! 1) DPA DRIVER TIMES OUT DUD DAPS AND GEN RESSES THEM ! ! Main changes for 29F ! 1) Clears store to remove parities when configuring on a SMAC ! 2) Periodically checks that 'other' OCP is still awake ! ! Main changes for 29G ! 1) Dap now restarts at once after check for file syncronising ! 2) L-C Stacks page 0 into proper smac not dap after uncured problems ! with OCP claiming SSN+1 not resident when its in Dap store. ! CONSTSTRING (3) CHOPID="22B"; ! EARLIEST COMPATABLE CHOPSUPE !----------------------------------------------------------------------- !* !* Communications record format - extant from CHOPSUPE 22B onwards * !* RECORDFORMAT CDRF(BYTEINTEGER IPDAPNO,DAPBLKS,DAPUSER,DAPSTATE, C INTEGER DAP1,DAPINT) RECORDFORMAT COMF(INTEGER OCPTYPE,SLIPL,SBLKS,SEPGS,NDISCS,DLVNADDR, C (INTEGER GPCTABSIZE,GPCA OR INTEGER DCUTABSIZE,DCUA), C INTEGER SFCTABSIZE,SFCA,SFCK,DIRSITE, C DCODEDA,SUPLVN,TOJDAY,DATE0,DATE1,DATE2, C TIME0,TIME1,TIME2,EPAGESIZE,USERS,CATTAD,SERVAAD, C BYTEINTEGER NSACS,RESV1, C (BYTEINTEGER SACPORT1,SACPORT0 OR BYTEINTEGER C OCP1 SCU PORT,OCP0 SCU PORT), BYTEINTEGER C NOCPS,SYSTYPE,OCPPORT1,OCPPORT0,INTEGER ITINT, C (INTEGER CONTYPEA,GPCCONFA,FPCCONFA,SFCCONFA OR C INTEGER DCU2HWNA,DCUCONFA,MIBA,SP0), C INTEGER BLKADDR,RATION, C (INTEGER SMACS OR INTEGER SCUS), C INTEGER 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,RECORD (CDRF)ARRAY CDR(1:2), C INTEGER 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 (S1) ! 2 = 2960 (P2) or 2956 (S2) ! 3 = 2970 (P3) or 2966 (S3) ! 4 = 2980 (P4) ! 5 = 2972 or non-interleaved 2976 (P4/1) ! 6 = Interleaved 2976 (P4/1) ! ! SLIPL bit 0 is set to 1 to force an AUTO IPL from RESTART. ! bits 1-15 are the SLOAD lvn & site >>4. ! (equivalent to the handkey settings for AUTO IPL). ! bits 16-31 are thehe port/trunk/stream(or DCU/stream) of the ! device used at IPL time. ! SBLKS The no of 128k blocks of main store present ! SEPGS The no of extended pages for paging(ie not including ! any pages occupied by resident code & data). ! NDISCS Then number of EDS drives avaliable ! DLVNADDR The address of an array which maps disc lvns to ! their ddt slots. ! GPCTABSIZE The size in bytes of the GPC (or DCU) table ! GPCA The address of the GPC (or DCU) table ! SFCTABSIZE The size of the SFC(ie DRUM) table ! SFCA The address of the SFC table ! SFCK The number of (useable) 1K page frames of Drum store ! available for paging.(0 = No drum configuration) ! DIRSITE The Director site address(eg X200) no longer reqd? ! DCODEDA The Disc Address of the Director (expressed as ! SUPLVN<<24!DIRSITE) ! SUPLVN The logical volume no of the disc from which the ! Sytem was "SLOADED". Various System components (eg ! DIRECT, VOLUMS will page from here ! ! TOJDAY Todays (Julien) day number. ! DATE0} These three integers define the current date(updated at ! DATE1} at 2400) as a character string such that ! DATE2} the length byte is in the bottom of DATE0 ! ! TIME0} These three integers define the clock time as a string ! TIME1} in the same format as for DATE. The time is updated ! TIME2} about every 2 seconds ! ! EPAGESIZE The number of 1K pages combined together to make up ! the logical "Extended Page" used in Emas.Currently=4 ! USERS The number of user processes (foreground+background) ! currently in existence.Includes DIRECT,VOLUMS&SPOOLR ! CATTAD Address of maxcat followed by category table. ! SERVAAD The address of the service array SERVA. ! NSACS The number of sacs found at grope time ! SACPORT1} Holds the Port no of the Store Access Controller(s) ! SACPORT0} found at grope time. SACPORT0 was used to IPL system. ! NOCPS The number of OCPS found at grope time. ! SYSTYPE System infrastructure: ! 0 = SMAC based ! 1 = SCU based (SCU1) ! 2 = SCU based (SCU2) ! OCPPORT1} Hold the Port no of the OCPs found at grope time. ! OCPPORT0} OCPPORT0 was used to IPL the system. ! ITINT The Interval Timer interval in microsecs. Varies ! between different members of the range ! CONTYPEA The address of a 31 byte area containing the codes ! of the controllers in port-trunk order. Codes are:- ! 0 = Not relevant to EMAS ! 1 = SFC1 ! 2 = FPC2 ! 3 = GPC1 ! ! GPCCONFA} These three variables each point to a word array ! FPCCONFA} containing controller data. The first word in each ! SFCCONFA} case says how many controllers on the system. The ! remainder have Port&Trunk in top byte and Public ! segment no of comms segment in bottom byte. For GPCS ! the Public Seg no is apparently omitted! ! BLKADDR The address of first element of a word array bounds ! (1:SBLKS) containing the real address of each 128K ! block of main store. Real addresses are in the form ! RSN/SMAC NO/Address in SMAC ! RATION Information maintained by DIRECT concerning access ! rationing. Bytes from left indicate scarcity, ! pre-empt point, zero and interactive users ! respectively ! SMACS Bits 0-15 are a map of SMACS in use by the system. ! 2**16 bit set if SMAC0 in use etc. ! Bits 16-31 are a map of SMACS found at grope time. ! 2**0 bit set if SMAC0 found etc. ! TRANS The address of a 768 byte area containing 3 translate ! tables. The first is ISO to EBCDIC, the second the ! exact converse & the third is ISO to ISO with ! lower to upper case conversion. ! KMON A 64 bit bitmask controlling monitoring of Kernel ! services. Bit 2**n means monitor service n. Bits can ! be set by Operator command KMON. ! DITADDR Disc index table address. The address of first ! element of an array(0:NDISCS-1) containing the address ! of the disc device entries. ! SMACPOS The no of places that the Smac no must be left ! shifted to be in the right position to access ! a Smac image store location. Incredibly this varies ! between the 2980 and others!! ! SUPVSN The Supervisor id no as a three char string eg 22A ! PSTVA The virtual address of the Public Segment table which ! is itself a Public segment. All other information ! about PST can be found by looking at its own PST entry ! SECSFRMN The no of Seconds since midnight. Updated as for TIME ! SECSTOCD The number of seconds to System closedown if positive ! If zero or negative no close down time has yet been ! notified. Updated as for TIME ! SYNC1DEST} These are the service nos N2,N3 & N4 for process ! SYNC2DEST} parameter passing described in Supervisor Note 1 ! ASYNCDEST} ! MAXPROCS The maximum number of paged processes that the ! Supervisor is configured to run. Also the size ! of the Process array. ! INSPERSECS The number of instructions the OCP executes in 1 ! second divided by 1000(Approx average for EMAS) ! ELAPHEAD The head of a linked list of param cells holding ! service with an elapsed interval interrupt request ! outstanding ! COMMSRECA The address of an area containing details of the ! Communication streams.(private to COMMS Control) ! STOREAAD The address of first element of the store record array ! bounds (0:SEPGS-1) ! PROCAAD The address of first element of the process record ! array bounds(0:MAXPROCS) ! SFCCTAB} The addresses of two private tables provided by grope ! DRUMTAD} for use by the routine DRUM. They give details of ! the SFCS and DRUMS found on the system ! TSLICE Time slice in microsecs. Supervisor has to allow for ! differences in interval timer speeds accross the range ! FEPS Bits 0-15 are a map of FEPs found at grope time. ! 2**16 bit set if FE0 found etc. ! Bits 16-31 are a map of currently available FEPs. ! 2**0 bit set if FE0 available etc. ! MAXCBT Maximum cbt entry ! PERFORMAD Address of record holding timing information and counts ! for performance analysis. ! IPDAPNO PORT & SMAC number for the DAP ! DAPBLKS The number of 128K blocks in DAP ! DAPUSER The PROCESS currently holding the DAP ! DAPSTATE The state of the DAP ! DAP1 DAP control fields ! DAPBMASK Bit map of currently allocated DAP blocks ! SP1->SP3 Spare locations ! LSTL} ! LSTB} ! PSTL} ! PSTB} These are the image store addresses for the following ! HKEYS} control registers:- ! HOOT} Local Segment Table Limit & Base ! SIM } Public Segment Table Limit & Base ! CLKX} Handkeys,Hooter System Interrupt Mask Register ! CLKY} and the clock X,Y & Z Registers ! CLKZ} ! HBIT A bit pattern that when ORed into Control Register ! "HOOT" operates the Hooter.(0=Hooterless machine) ! SLAVEOFF A bit pattern (top 16 bits) and Image store address ! in bottom 16 bits. ORing the top 16 bits(after ! shifting) into the image store will stop all slaving of ! operands but not instructions ! INHSSR A bit pattern and image location as for SLAVEOFF. ! ORing the bits into the location will switch off ! reporting of successful system retry ! SDR1} ! SDR2} The image store addresses of SMAC internal registers ! SDR3} needed by the Engineers after Smac errors have ! SDR4} occurred ! SESR} ! HOFFBIT A bit pattern that when ORed into a Smac Engineers ! status register will stop reporting of error ! from that Smac ! ! BLOCKZBIT A bit pattern indicating the position of ! the block zero bit in the SMAC config register. ! ! BLKSHIFT Indicates which way to shift the BLOCKZBIT mask ! to correspond with subsequent store blocks. ! ! BLKSIZE Store block size. ! CONSTRECORD (COMF)NAME COM=X'80000000'+48<<18 CONSTINTEGER VIRTAD=X'81000000'; ! CAN NOT BE USED IF PAGE FLAWED CONSTINTEGER PUBSEG=X'80000000',SEG64=X'01000000' COM_MAXPROCS=MAXPROCS CONSTINTEGER EPAGESHIFT=12; ! 4*1024==1<<12 CONSTINTEGER SEGEPSIZE=256//EPAGESIZE !----------------------------------------------------------------------- ! MISC. ROUTINE SPECS EXTERNALROUTINESPEC SLAVESONOFF(INTEGER ONOFF) EXTERNALSTRING (15)FNSPEC STRINT(INTEGER N) EXTERNALSTRING (8)FNSPEC STRHEX(INTEGER N) EXTERNALSTRING (63)FNSPEC STRSP(INTEGER N) EXTERNALROUTINESPEC PKMONREC(STRING (20)TEXT,RECORD (PARMF)NAME P) EXTERNALROUTINESPEC MONITOR(STRING (63) S) EXTERNALROUTINESPEC OPMESS(STRING (63) S) EXTERNALROUTINESPEC DISPLAY TEXT(INTEGER SCREEN,LINE,CHAR, 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 CHECK OTHER OCP EXTERNALROUTINESPEC HALT OTHER OCP EXTERNALROUTINESPEC RESTART OTHER OCP(INTEGER MODE) EXTERNALROUTINESPEC CLOCK TO THIS OCP IF SSERIES=YES START EXTERNALROUTINESPEC DCU1 RECOVERY(INTEGER PARM) FINISH FINISH IF MONLEVEL&4#0 START LONGINTEGERNAME IDLEIT,NOWORKIT,LCIT,FLPIT,BLPIT,PTIT,DRUMIT, 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 MAXP4PAGES,P4PAGES,SXPAGES, NPQ,OLDLNB,IDLE,DONT SCHED,SMAC RCONFIG,SMACRPAGES, C MPLEVEL,PAGEFREES,DCLEARS,GETEPN,PREEMPTED, C MAX OVERALLOC,SNOOZTIME,SAC MASK LONGINTEGER L,STKPSTE STRING (3) STRPROC !----------------------------------------------------------------------- ! CONFIGURATION DECLARATIONS BYTEINTEGERARRAYNAME CONTYPE BYTEINTEGERARRAYFORMAT CONTYPEF(0:31) CONTYPE==ARRAY(COM_CONTYPEA,CONTYPEF) INTEGERARRAYNAME BLOCKAD INTEGERARRAYFORMAT BLOCKADF(0:127); ! ALLOW UP TO 16 MEGABYTES BLOCKAD==ARRAY(COM_BLKADDR,BLOCKADF) !----------------------------------------------------------------------- RECORDFORMAT SSNP1F(INTEGER LNB,PSR,PC,SSR,SF,IT,IC,CTB,XNB,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=PSTVA; ! PST SEG 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=25 CONSTINTEGER STOREFSIZE=12; ! SIZE OF ELEMENT OF STORE ARRAY CONSTINTEGERNAME STORESEMA=STORE0AD+8;! USE STORE(0)_REALAD AS SEMA INTEGER SPSTOREX; ! FOR KEEPING EMERGENCY SPARE PAGE !----------------------------------------------------------------------- ! ACTIVE MEMORY TABLE DECLARATIONS CONSTINTEGER MIN RESIDENCES=3,MAXRESIDENCES=15;! FOR AMT TIMEOUTS OWNINTEGER RESIDENCES=MAXRESIDENCES; ! ADJUSTED DOWN AS DRUM FILLS CONSTINTEGER AMTASEG=21 CONSTINTEGER MAXAMTAK=MAXPROCS//2//EPAGESIZE*EPAGESIZE RECORDFORMAT AMTF(INTEGER DA,HALFINTEGER DDP,USERS,LINK, 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&32#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 PP CELL(INTEGER CELL) EXTERNALROUTINESPEC FASTPON(INTEGER PPCELL) IF MULTIOCP=YES THEN START EXTERNALROUTINESPEC SEMALOOP(INTEGERNAME SEMA,INTEGER PARM) 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) EXTERNALROUTINESPEC GDC(RECORD (PARMF)NAME P) EXTERNALROUTINESPEC DISC(RECORD (PARMF)NAME P) EXTERNALROUTINESPEC PDISC(RECORD (PARMF)NAME P) EXTERNALROUTINESPEC BMOVE(RECORD (PARMF)NAME P) EXTERNALROUTINESPEC TAPE(RECORD (PARMF)NAME P) EXTERNALROUTINESPEC OPER(RECORD (PARMF)NAME P) EXTERNALROUTINESPEC PRINTER(RECORD (PARMF)NAME P) EXTERNALROUTINESPEC LP ADAPTOR(RECORD (PARMF)NAME P) IF CRFITTED=YES START EXTERNALROUTINESPEC CR ADAPTOR(RECORD (PARMF)NAME P) FINISH EXTERNALINTEGERFNSPEC SAFE IS READ(INTEGER ISAD,INTEGERNAME VAL) EXTERNALINTEGERFNSPEC SAFE IS WRITE(INTEGER ISAD,VAL) IF CPFITTED=YES THEN START EXTERNALROUTINESPEC CP ADAPTOR(RECORD (PARMF)NAME P) FINISH IF DAP FITTED=YES THEN START CONSTINTEGER MAXLDAP=2 ROUTINESPEC DAP DRIVER(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'3C'#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) ! 2**10 HAS PIECE OF DAP ! REMAINDER UNUSED ! DUMP PROGRAM NEED TO HAVE ! DETAILS OF ANY CHANGES ! CONSTINTEGER HADTONFLY=32,HADPONFLY=64,SNOOZED=128 CONSTINTEGER LCSTFAIL=256,AMTLOST=16,STATEX=512 CONSTINTEGER FIRST UPROC=6 CONSTINTEGER OPERSPACE=41*(6+MAXPROCS//3) INTEGERARRAY PROC PICT(0:2+OPERSPACE>>2);! SPACE FOR PROCESS PICTURE PROC PICT(0)=OPERSPACE; ! FIRST WORD=LENGTH OF REM !----------------------------------------------------------------------- ! LOCAL CONTROLLER DECS ETC. ROUTINESPEC LOCAL CONTROL ROUTINESPEC GLOBAL CONTROL OWNLONGINTEGERARRAYFORMAT LSTF(0:LSTLEN-1) OWNINTEGER TIMESLICE=X'4000'; ! 131072 MICROSECS OWNINTEGER OUT18CHARGE=X'800'; ! CHARGE FOR OUT116 =8 MILLESECS OWNINTEGER OUT18INS; ! CHARGE *INS RATE OWNINTEGER ALLOW PERI INTS=X'01803FFE';! CHANGED IN SCHEDULE ACT0 EXTERNALINTEGERFNSPEC SYSTEMCALL !----------------------------------------------------------------------- I=SYSTEM CALL; ! TO INITIALISE "COM" FILE *STLN_OLDLNB ! ! CREATE LOCAL CONTROLLER CONTEXT ! LSSNP1I=0 LSSNP1I_LNB=LSTLEN*8+LSTKN*X'80'+(DIRCSEGL+1)+X'50' LSSNP1I_PSR=X'00140001' *JLK_<LCCALL> *LSS_TOS *ST_I LSSNP1I_PC=I; ! TO CALL OF L-C AFTER ACTIVATE LSSNP1I_SSR=X'01803BFE' LSSNP1I_SF=LSTLEN*8+LSTKN*X'80'+(DIRCSEGL+1)+X'80' ! SF AT 12 WORDS AFTER LNB LSSNP1I_IT=MAXIT LSSNP1I_IC=MAXIT *LSS_(LNB +5); ! PRESERVE DISPLAY PTR *ST_I LSSNP1I_CTB=I COM_DCODEDA=COM_SUPLVN<<24!COM_DIRSITE ! ! SET UP CLOCK REGS ! I=COM_CLKZ *LB_I *LSS_13; ! INTERRUPT EVERY 2 SECS(APPROX) *ST_(0+B ); ! Z-REG IF COM_TSLICE>0 THEN TIMESLICE=COM_TSLICE//COM_ITINT OUT18CHARGE=TIMESLICE>>3; ! ONE EIGHTH OF TSLICE OUT18INS=OUT18CHARGE*COM_INSPERSEC*COM_ITINT//1000 ! ! FIND END OF KERNEL STACK ETC. ! PST(44)=0; PST(45)=0; ! CLEAR CHOPSUPE CODE GLA PST(46)=0; PST(47)=0; ! & STACK SEGMENTS FROM PST PST(13)=PST(5)-128; ! SSN FOR OCP PORT 2 PST(15)=PST(5)+128; ! SSN FOR OCP PORT 3 FSTASL==STORE(0)_FLINK BSTASL==STORE(0)_BLINK ! SET KERNEL STACK SEGMENT LIMIT ! INCLUDING PROTEM 8 K FOR EACH OCP ! STACK. THESE WILL BE REMOVED ! ONCE THE OCPS ARE ACTIVATED I=PST(4)&X'0FFFFFF8'; ! REALAD OF STACK K=PST(4)>>32&X'3FF80'+128+I; ! REALAD OF MAX TOS *STSF_J L=(J&X'3FFFF'+X'7F'+X'2000')>>7 IF MULTIOCP=YES THEN L=L+X'2000'>>7 PST(4)=PST(4)&X'FFFC007FFFFFFFFF'!(L-1)<<39 STKPSTE=PST(4)-X'200000000000' IF MULTIOCP=YES THEN STKPSTE=STKPSTE-X'200000000000' J=EPAGESIZE<<10; ! ADD UNUSED KERNEL STACK TO FREE LIST K=K//J-1 J=(I+L<<7+J-1)//J STORESEMA=-1 SPSTOREX=0 GETEPN=0 PREEMPTED=0; ! NO PROCESS PRE-EMPTED DONT SCHED=0 SMAC RCONFIG=0 SMAC RPAGES=0 IF SSERIES=NO START ; ! mask for configured in SACs SAC MASK=1<<COM_SACPORT0 IF COM_NSACS>1 THEN SAC MASK=SAC MASK!(1<<COM_SACPORT1) FINISH 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 P4PAGES=0 SXPAGES=0 MAXP4PAGES=P4PERCENT*COM_SEPGS//100 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))<CHOPID THEN C OPMESS("WRONG CHOPSUPE") STRING(ADDR(COM_SUPVSN))=SUPID IF MULTIOCP=YES AND COM_NOCPS>1 START P_DEST=X'110001'; P_P1=1<<16!COM_OCPPORT1 COM_NOCPS=1 PON(P); ! CONFIGURE IN 2ND OCP LATER FINISH ELSE COM_NOCPS=1 END ! ! NOW ACTIVATE THIS OCP INTO GLOBAL CONTROLLER. ALSO REMOTE ACTIVATE ! OTHER OCP IF PRESENT. STACKS ARE PUBLIC 12 FOR PORT 2 AND 14 FOR PORT 3 ! IF SSERIES=YES THEN I=2*COM_OCPPORT0+12 ELSE C I=2*COM_OCPPORT0+8; ! PST no. for local activate K=I!!2; ! AND FOR REMOTE ACTIVATE GSSNP1=LSSNP1I *JLK_<GCCALL> *LSS_TOS ; *ST_J GSSNP1_PC=J GSSNP1_LNB=X'80000004'+I<<18 GSSNP1_SF=GSSNP1_LNB+X'20' GSSNP1_SSR=X'01803FFE' RECORD(X'80000000'+(I+1)<<18)<-GSSNP1; ! context from record to SSN+1 *STSF_J PST(I)=PST(4)&X'1FF000008FFFFF80'+X'1F8000000000'+ 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) *LSD_(CTB +3); *ST_(LNB +3); ! COPY ACROSS PLT DESCR GLOBAL CONTROL; ! DOES NOT RETURN !----------------------------------------------------------------------- LCCALL:*JLK_TOS *STCT_(LNB +5); ! DISPLAY PTR TO NEW STACK ! SO THAT THE LXN IN CALL SEQUENCE ! LINKS LOCAL TO GLOBAL CONTEXTS *STB_(LNB +0); ! B HAS PROCESS NO IN IT PUTIN ! BY SCHEDULE AT CREATE ! AND IS PASSED ON BY THIS FRIG *LSD_(CTB +3); *ST_(LNB +3); ! COPY ACROSS PLT DESCR LOCAL CONTROL; ! INITIAL CALL(DOES NOT RETURN!) ROUTINE GLOBAL CONTROL !%ROUTINESPEC UNQUEUE(%INTEGERNAME QUEUE,UNQUED SERVICE) INTEGER I,J,K,PORT,SEIP,SELN,SESTK,KSERVICE,LSERVICE,TSERVICE, 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 IF MULTI OCP=YES START INTEGERNAME MY ALARM,HIS ALARM CONSTINTEGER MAX ALARM=1024 ! control words to catch other OCP going to sleep FINISH INTEGERNAME CURPROC; ! CURRENT PROCESS KEPT IN IST ! (LAST WRD) FOR DUMPS ETC SWITCH CONROUT(0:3) SWITCH SERVROUT(0:LOCSN0); ! KERNEL SERVICES RECORD (PROCF)NAME PROC; ! STATUS BITS SIGNIFY AS FOLLOWS RECORD (SERVF)NAME KSERV,LSERV,LSERVQ RECORD (ISTF)NAME ISTP RECORD (CDRF)NAME LDAP INTEGERNAME RUNQ RECORD (PARMF) P ! ! FIND WHICH OCP THIS ACTIVATION IS USING AND SET RELEVANT IST ! *LSS_(3); *USH_-26 *AND_3; *ST_ MY OCP PORT IF MULTI OCP=YES THEN HIS OCP PORT=MY OCP PORT!!1 PST(4)=STKPSTE; ! SHORTEN OLD STACK *LSS_OLDLNB; *ST_(LNB +0); ! FOR %MONITOR ISTAD=X'80000000'+MY OCP PORT<<18 ISTP==RECORD(ISTAD); ! IST BASE *STLN_I; ! USED TO FRIG %MONITOR LATER ISTP_LNB=I ISTP_PSR=X'00140001'; ! ACR=1, PRIV=1, PM=0, ACS=1 ISTP_PC=0 ISTP_SSR=X'01803FFE'; ! ONLY SYSERR *STSF_I ISTP_SF=I ISTP_IT=MAXIT ISTP_IC=MAXIT ISTP_CTB=0 RECORD(ISTAD+X'20')<-ISTP; ! EXTERNAL INTS RECORD(ISTAD+X'40')<-ISTP; ! M-P INTS RECORD(ISTAD+X'60')<-ISTP; ! PERIPHERAL INTS RECORD(ISTAD+X'120')<-ISTP; ! EXTRACODE(!) INTS RECORD(ISTAD+X'140')<-ISTP; ! EVEBT PENDING INTS RECORD(ISTAD+X'180')<-ISTP; ! Primitive ints. RECORD(ISTAD+X'1A0')<-ISTP; ! Unit ints. LSSNP1P==RECORD(X'40000') ! ! MASK SYSERR& UNMASK OUT ON SYSERR. INTERRUPT ! ISTP_SSR=X'01803EFF' ISTP_SF=ISTP_SF+X'1000'; ! SET SYSTEM ERROR SF TO DISTANT PLACE ! ! INSERT PCS ! *LXN_ISTAD *JLK_<IST1I>; *LSS_TOS ; *ST_(XNB +2) *JLK_<IST2I>; *LSS_TOS ; *ST_(XNB +10) *JLK_<IST3I>; *LSS_TOS ; *ST_(XNB +18) *JLK_<IST4I>; *LSS_TOS ; *ST_(XNB +26) *JLK_<IST10I>; *LSS_TOS ; *ST_(XNB +74) *JLK_<IST11I>; *LSS_TOS ; *ST_(XNB +82) *JLK_<IST13I>; *LSS_TOS ; *ST_(XNB +98) *JLK_<IST14I>; *LSS_TOS ; *ST_(XNB +106) IF MULTI OCP=YES START MY ALARM==INTEGER(ISTAD+4*94); ! uses IC field for IC int HIS ALARM==INTEGER(ISTAD!!1<<18+4*94) FINISH CURPROC==INTEGER(ISTAD+4*95); ! onto CTB field for IC int CURPROC=0 KSERVICE=0 KSERV==SERVA(0) LSERV==KSERV; ! INITIALISE POINTERS. HERE AFTER ! ADDRESS FIELD ONLY UPDATE ! IN ASSEMBLER SEQUENCES IF MONLEVEL&4#0 START IT CORRN=1+1024*IC CORRN//(COM_INSPERSEC*COM_ITINT) KIT==INTEGER(ISTP_SF&X'FFFC0000'+X'40014') FINISH IF MULTIOCP=YES AND COM_NOCPS>1 THEN START ! OPEN PATHS FOR MP INT ETC ! SET PORT DEPENDENT PHOTO(P4S) IF SSERIES=NO START IF BASIC PTYPE<=3 START *LSS_1; *ST_(X'6009'); ! BROADCAST SE *LSS_(X'600A') *AND_X'CC'; *ST_(X'600A'); ! PERMIT MP INTS & ACTIVATES *ST_IS DIAG 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 FINISH IF MY OCP PORT#COM_OCPPORT0 START ;! IM NOT IPL PROCESSOR IF SSERIES=YES START J=COM_OCP0 SCU PORT *LSS_J; *ST_(X'600F') *LB_X'602B'; *LSS_0; *ST_(0+B ); ! unset selective masks *LB_X'6011'; *LSS_(0+B ); *AND_X'FFFD'; *OR_1; *ST_(0+B ); ! miniphotos only J=X'400C0000'!COM_OCP0 SCU PORT<<22 ! set up UTBR I=J!X'6004'; *LB_I; *LSS_(0+B ); *LB_X'6004'; *ST_(0+B ) I=J!X'6005'; *LB_I; *LSS_(0+B ); *LB_X'6005'; *ST_(0+B ) ! set up MIB UNLESS COM_MIBA=0 START I=COM_MIBA+MY OCP PORT<<12 *LB_X'601A'; *LSS_I; *ST_(0+B ) FINISH ! set up cross reporting of errors I=COM_OCP0 SCU PORT<<22 *LB_X'601D'; *LSS_I; *ST_(0+B ) I=J!X'601D'; J=COM_OCP1 SCU PORT<<22 *LB_I; *LSS_J; *ST_(0+B ) FINISH ELSE IF BASIC PTYPE<=3 START J=X'80'>>COM_SACPORT0 IF COM_NSACS>1 THEN J=J!X'80'>>COM_SACPORT1 J=J!!(-1) *LSS_(X'600A'); *AND_J; *ST_(X'600A') ! CLOSE OFF SAC INTS TO THIS OCP IF BASIC PTYPE=2 START *LSS_X'00011001'; *ST_(X'6011') ! INHIBIT PHOTO ON SOFT SYSTEM ERROR FINISH J=COM_OCPPORT0 *LSS_J; *ST_(X'600F');! OPEN ROUTE FOR RRTC *ST_IS DIAG 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'01803FFE' *ST_(3) IF MULTIOCP=YES THEN START *INCT_(MAINQSEMA) *JCC_8,<MQGOT1> SEMALOOP(MAINQSEMA,0) 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_<LSERVE>; ! PREMPTED LOWPRIO FOR HIGHPRIO FINISH KACT: ! ACTIVATE DIRECT KERNEL->USER IF MULTIOCP=YES START ; *TDEC_(MAINQSEMA); FINISH 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,<LSERVE> 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,<LSERVE> ! ! NO PROCESS NEEDS OCP. ENTER AND TIME THE IDLE LOOP ! WHICH IS DIFFERENT FOR MULTI OCPS WHERE OTHER OCP CAN GENERATE WORK ! IF MULTIOCP=YES START ; *TDEC_(MAINQSEMA); FINISH IF MONLEVEL&4#0 THEN START IF MPLEVEL+NPQ<COM_NOCPS THEN NOWORKN=NOWORKN+1 ELSE C IDLEN=IDLEN+1 IDLE=1 FINISH *LSS_X'01800820'; ! ALL EXCEPT TIMER INTERRUPTS *ST_(3) IF MULTIOCP=NO THEN START IDLE0: *IDLE_0 ->IDLE0; ! IN CASE "EKS" SET FINISH ELSE START ; ! IDLE IN DUALS IF SSERIES=NO AND MY OCP PORT#COM_OCPPORT0 START ! ! for S series DCU2 interrupts are reported to the ! activating OCP & DCU1 ints. to the IPL (or S/W nominated) OCP ! so trying to grab outstanding ints. will not work! ! PORT=COM_SACPORT0 *LSS_X'01803FFE'; *ST_(3) J=X'44000000'!PORT<<20 *LB_J; *LSS_(0+B ); *ST_I *JAF_4,<PROCESS INT> IF COM_NSACS>1 START PORT=COM_SACPORT1 J=X'44000000'!PORT<<20 *LB_J; *LSS_(0+B ); *ST_I *JAF_4,<PROCESS INT> 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_<IL0> IF MONLEVEL&4#0 START *LSS_(5) *IRSB_MAXIT *IAD_IT CORRN; ! CORRECT FOR THESE INSTRNS *ST_I IF MPLEVEL+NPQ<COM_NOCPS THEN NOWORKIT=NOWORKIT+I C ELSE IDLEIT=IDLEIT+I IDLE=0 FINISH ->KSERVE FINISH FINISH ! ! MAIN QUEUE SERVICING SECTION ! IF KSERVICE=0 THEN START ! UNQUEUE(KERNELQ,KSERVICE) ! KSERV==SERVA(KSERVICE) *LD_KERNELQ; *JLK_<JLUNQ> *STB_KSERVICE *STXN_KSERV+4; ! COPY MAPPING FROM JLK SUBROUTINE FINISH I=KSERV_P&X'BFFFFFFF'; ! REMOVE EXECUTED BIT IF I<=0 THEN KSERV_P=I AND KSERVICE=0 AND ->KSKIP IF KSERVICE>LOCSN1 START ; ! SUSPEND REPLY I=(KSERVICE-LOCSN0)&(MAXPROCS-1)+LOCSN1 SERVA(I)_P=SERVA(I)_P!X'80000000' I=I+(LOCSN2-LOCSN1) SERVA(I)_P=SERVA(I)_P!X'80000000' I=I+(LOCSN3-LOCSN2) SERVA(I)_P=SERVA(I)_P!X'80000000' IF MULTIOCP=YES START ; *TDEC_(MAINQSEMA); FINISH P_DEST=X'30007'; ! RESCHEDULE LOCAL CONTROLLER P_SRCE=0 P_P1=I-LOCSN3 SCHEDULE(P) TSERVICE=3 ->KTIMES FINISH IF MULTIOCP=YES START ; *TDEC_(MAINQSEMA); FINISH SUPPOFF(KSERV,P) ->SERVROUT(KSERVICE) !----------------------------------------------------------------------- ! SERVICE ROUTINE CALLS SERVROUT(1): SNOOZTIME=P_P1; ->KEXIT SERVROUT(2): DEADLOCK; ->KEXIT SERVROUT(3): SERVROUT(15): SCHEDULE(P); ->KEXIT SERVROUT(4): PAGETURN(P); ->KEXIT SERVROUT(5): GET EPAGE(P); ->KEXIT SERVROUT(6): RETURN EPAGE(P); ->KEXIT SERVROUT(7): SEMAPHORE(P); ->KEXIT SERVROUT(8): SERVROUT(14): ACTIVE MEM(P); ->KEXIT SERVROUT(9): ! ONLY FOR MONITORING IF MONLEVEL&X'3C'#0 THEN TIMEOUT; ->KEXIT SERVROUT(10): ELAPSEDINT(P); ->KEXIT SERVROUT(11): UPDATE TIME; ->KEXIT SERVROUT(12): DPONPUTONQ(P); ->KEXIT SERVROUT(13): TURNONER(P); ->KEXIT SERVROUT(16): OVERALLOC CONTROL; ->KEXIT SERVROUT(17): CONFIG CONTROL(P); ->KEXIT SERVROUT(18): SHUTDOWN(P); ->KEXIT SERVROUT(19): IF MULTI OCP=YES AND COM_NOCPS>1 THEN CHECK OTHER OCP AND ->KEXIT ->INVALID SERVROUT(20):SERVROUT(21): SERVROUT(22):SERVROUT(23):SERVROUT(24):SERVROUT(25):SERVROUT(26): SERVROUT(27):SERVROUT(28):SERVROUT(29):SERVROUT(30): ->INVALID SERVROUT(31): IF DAP FITTED=YES THEN DAP DRIVER(P) AND ->KEXIT ->INVALID SERVROUT(32): DISC(P) ->KEXIT SERVROUT(33): PDISC(P); ->KEXIT SERVROUT(34):SERVROUT(35): ->INVALID SERVROUT(36):SERVROUT(37): BMOVE(P); ->KEXIT SERVROUT(38):SERVROUT(39): ->INVALID SERVROUT(40): IF SFC FITTED=YES THEN DRUM(P) AND ->KEXIT ELSE ->INVALID SERVROUT(41): IF CSU FITTED=YES THEN CSU(P) AND ->KEXIT ELSE ->INVALID SERVROUT(42):SERVROUT(43):SERVROUT(44):SERVROUT(45):SERVROUT(46): SERVROUT(47):->INVALID SERVROUT(48): GDC(P); ->KEXIT SERVROUT(49): TAPE(P); ->KEXIT SERVROUT(50): OPER(P); ->KEXIT SERVROUT(51): LP ADAPTOR(P); ->KEXIT SERVROUT(52): IF CRFITTED=YES THEN CR ADAPTOR(P) AND ->KEXIT ELSE ->INVALID SERVROUT(53): IF CPFITTED=YES THEN CP ADAPTOR(P) AND ->KEXIT ELSE ->INVALID SERVROUT(54): PRINTER(P); ->KEXIT SERVROUT(55): COMMS CONTROL(P); ->KEXIT SERVROUT(56): IF MONLEVEL&256#0 THEN COMBINE(P) AND ->KEXIT ELSE -> INVALID SERVROUT(57): MK1FEADAPTOR(P); ->KEXIT SERVROUT(58):SERVROUT(59):SERVROUT(60):->INVALID SERVROUT(61): BMREP(P); ->KEXIT SERVROUT(62): COMREP(P); ->KEXIT SERVROUT(63): ! DELAYED RELAY I=P_DEST&X'FFFF'; ! THE DELAY P_DEST=P_P6 DPON(P,I) ->KEXIT SERVROUT(64):SERVROUT(0): ->INVALID !----------------------------------------------------------------------- KEXIT: IF MONLEVEL&4#0 THEN TSERVICE=KSERVICE KTIMES: ! RECORD SERVICE ROUTINE TIMES IF MONLEVEL&4#0 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) LSERV_P=LSERV_P&X'BFFFFFFF'; ! REMOVE EXECUTING BIT IF MULTI OCP=YES START ; *TDEC_(MAINQSEMA); FINISH ! AND DROP THRO FOR MSG INVALID: ! INVALID SERVICE CALLED PKMONREC("INVALID POFF:",P) ->KSERVE !----------------------------------------------------------------------- LSERVE: ! LOCAL CONTROLLER SERVICES *STD_RUNQ; ! COMPLETE MAPPING OF RUNQ ! UNQUEUE(RUNQ,LSERVICE) ! LSERV==SERVA(LSERVICE) *JLK_<JLUNQ>; *STB_LSERVICE *STXN_LSERV+4; ! COPY MAPPING FROM JLK SUBROUTINE ! THIS IS USED ON L-C EXIT ! ! L-C IS ONLY INHIBITIED BEFORE PROCESS START AND AFTER STOPPING ! SO THE LOGICALLY NECESSARY TEST FOR INHIBITION CAN BE OMITTED ! UNLESS CODEING ELSEWHERE IS CHANGED. CODE LEFT AS COMMENT AS ! A REMINDER ! ! I=LSERV_P&X'BFFFFFFF'; ! WITHOUT "EXECUTING" BIT ! %IF I<=0 %THEN LSERV_P=I %AND ->KSKIP;! INHIBITED ! CURPROC=LSERVICE-LOCSN0 *SBB_LOCSN0; *STB_(CURPROC) PROC==PROCA(CURPROC) IF PROC_ACTIVE#255 THEN ->LINVALID IF MULTI OCP=YES START *TDEC_(MAINQSEMA) IF COM_NOCPS>1 START ; ! other OCP sleep check HIS ALARM=HIS ALARM+1 IF HIS ALARM>MAX ALARM THEN CHECK OTHER OCP AND HIS ALARM=0 MY ALARM=0 FINISH FINISH ! ! TO ACTIVATE TO LOCAL CONTROLLER USE THE ACTIVATE WORDS IN THE PROCESS ! LIST BUT SUBSTITUTE LC STACK NO(0) FOR PROCESS STACK NO ! *LXN_PROC+4 *LSD_(XNB +3) *SLSD_0; ! LC STACK NO NOT PARAMETERISED ! *ST_TOS IF MONLEVEL&4#0 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 *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 IF COM_NOCPS>1 THEN MY ALARM=0 *INCT_(MAINQSEMA) *JCC_8,<MQGOT2> SEMALOOP(MAINQSEMA,0) MQGOT2: FINISH LSERV_P=LSERV_P&X'BFFFFFFF'; ! REMOVE "EXECUTING" BIT ! ! IF THE PROCESS IS NOT SUSPENDED THERE WILL BE MORE PARAMETERS FOR IT ! AND IT MUST BE REQUEUED. NOTE THAT THE PROCESS MAY HAVE CHANGED ! ITS RUNQ BY TRANSITIONS MADE ON THE FLY! ! IF LSERV_P>0 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 START ; *TDEC_(MAINQSEMA); FINISH ->KSERVE !----------------------------------------------------------------------- ! INTERRUPT ENTRY POINTS IST1I: *JLK_TOS ; ! ENTRY IS LINK PC I.E. NEXT INSTR ! SYSTEM ERROR INTS ENTER HERE *LSS_TOS ; *ST_SESTK *LSS_TOS ; *ST_SEIP *LSS_(LNB +8); *ST_SELN; ! OLD LINE NUMBER SYSERR(SESTK,SEIP); ! DOES NOT RETURN ->KSERVE !----------------------------------------------------------------------- IST2I:*JLK_TOS ! EXTERNAL INTS (CLOCK+DAP) ENTER HERE *LSS_TOS ; *ST_I; ! OLD STACK *LSS_TOS ; *ST_J; ! INTERRUPT PARAMETER IF MONLEVEL&4#0 AND IDLE#0 THEN START IF MPLEVEL+NPQ<COM_NOCPS THEN C NOWORKIT=NOWORK IT+(MAXIT-KIT) ELSE C IDLEIT=IDLEIT+(MAXIT-KIT) IDLE=0 FINISH P_P1=I P_P2=J PORT=J>>20&15 P_SRCE=0 IF DAP FITTED=YES AND 4<=PORT<=5 START ;! FROM DAP FOR I=1,1,MAXLDAP CYCLE LDAP==COM_CDR(I) IF LDAP_IPDAPNO>>4=PORT START J=LDAP_DAP1+7 *LB_J; *LSS_(0+B ); *ST_J; ! READ AND CLEAR INT IF J#0 START ; ! WAS AN INTERRUPT P_P3=J; ! DAP INT STATUS REG P_P4=MY OCP PORT P_DEST=X'1F0003'!I<<8 PON(P) FINISH FINISH REPEAT ->KSERVE FINISH IF SSERIES=NO AND BASIC PTYPE=4 AND COM_OCPTYPE=4 START ! 2980 CLOCK IS IN SAC I=COM_CLKX&X'FFF00000'!X'100'; ! SAC EXTERNAL INT REG *LB_I; ! MUST BE READ&CLEARED *LSS_(0+B ); ! OR INT WILL OCCUR AGAIN *ST_J P_P3=J FINISH IF BASIC PTYPE=4 AND COM_CLKX>>20&15#PORT THEN C OPMESS("?? CLOCK INT PORT ".STRINT(PORT)) P_DEST=X'A0000' IF MULTIOCP=YES THEN PON(P) AND ->KSERVE ELSE START ELAPSEDINT(P) IF MONLEVEL&4#0 THEN TSERVICE=10 ->KTIMES FINISH !----------------------------------------------------------------------- IST3I:*JLK_TOS ; ! multi-processor MULT: ! or pseudo via PON 19 IF MULTIOCP=YES 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 SSERIES=NO START IF BASIC PTYPE<=3 START *LSS_(X'6303'); ! CLEAR & DISCARD *LSS_(X'600A'); *OR_X'33' *ST_(X'600A') *LSS_0; *ST_(X'6009'); ! DONT BROADCAST SE INTS 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 FINISH ! ! If the remaining OCP is not the IPL OCP then clock control must be ! established in this OCP. ALSO ALLOW SAC INTS ! IF COM_OCP PORT0#MY OCP PORT START IF SSERIES=NO START ; ! OPEN SAC INTERRUPT PATHS I=X'8'>>COM_SACPORT0 IF COM_NSACS>1 THEN I=I!(X'8'>>COM_SACPORT1) IF BASIC PTYPE<=3 START J=(I!I<<4)!!(-1) *LSS_(X'600A'); *AND_J; *ST_(X'600A') FINISH ELSE START J=I<<12!I<<2 *LSS_(X'4012'); *OR_J; *ST_(X'4012') FINISH FINISH CLOCK TO THIS OCP ! ! ALLOW DAP INTERUPTS IF RELEVANT ! IF DAP FITTED=YES THEN START J=0 FOR I=1,1,MAXLDAP CYCLE K=COM_CDR(I)_IPDAPNO IF K#0 THEN J=J!(X'80000000'>>(K>>4)) REPEAT IF J>0 START ; ! A DAP CONFIGURED IN IF BASIC PTYPE<=3 START ;! DAP ON 2970 *LSS_(X'600A') *AND_X'F3FFFFFF' *ST_(X'600A') FINISH ELSE START ; ! DAP ON P4 *LSS_(X'4012') *OR_X'0C000000' *ST_(X'4012') FINISH FINISH FINISH FINISH ! ! FREE UP ANY BUSY KERNEL SERVICE. THESE MUST BE DUE TO HIM ! SINCE MPINT IS MASKED DURING KERNEL ! CYCLE I=1,1,LOCSN0 IF SERVA(I)_P&X'40000000'#0 THEN 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<COM_NOCPS THEN C NOWORKIT=NOWORKIT+(MAXIT-KIT) ELSE C IDLEIT=IDLEIT+(MAXIT-KIT) IDLE=0 FINISH IF SSERIES=YES THEN START P_SRCE=0 P_DEST=X'300003' P_P1=I GDC(P) IF MONLEVEL&4#0 START TSERVICE=58 ->KTIMES FINISH ELSE ->KSERVE FINISH ELSE START ; ! FOR P SERIES PORT=I>>20&3 *LSS_1 *USH_PORT *AND_SACMASK *JAT_4,<KSERVE>; ! IGNORE OTHERWISE ! *JAF_4,<SACOK>; ! SAC configured in ! OPMESS("Surprise int. - SAC ".STRINT(PORT).TOSTRING(17)) ! ->KSERVE SACOK: I=X'44000000'!PORT<<20 ;! IMAGE STORE ADDR FOR TRUNK FLAGS *LB_I *LSS_(0+B ) *JAT_4,<KSERVE>; ! 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' IF MULTI OCP=YES AND I#0 AND COM_NOCPS>1 THEN PON(P) C ELSE DISC(P); ! PON if more ints. & multi ocp IF MONLEVEL&4#0 THEN TSERVICE=34 ->CONTINUE CONROUT(3): P_DEST=X'300003' P_SRCE=M'INT' IF MULTI OCP=YES AND I#0 AND COM_NOCPS>1 THEN PON(P) C ELSE GDC(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' !----------------------------------------------------------------------- ! Primitive IST13I:*JLK_TOS ; *IDLE_X'FB' !----------------------------------------------------------------------- ! Unit IST14I: *JLK_TOS IF SSERIES=YES START ; ! unit interrupts S series only *LSS_TOS ; *LSS_TOS *ST_I IF MONLEVEL&4#0 AND IDLE#0 THEN START IF MPLEVEL+NPQ<COM_NOCPS THEN C NOWORKIT=NOWORKIT+(MAXIT-KIT) ELSE C IDLEIT=IDLEIT+(MAXIT-KIT) IDLE=0 FINISH K=UT VA+(I&X'FFFF')*64; ! unit table entry J=BYTEINTEGER(COM_DCU2HWNA+INTEGER(K+8)>>24) IF J=0 START OPMESS("Unit int.?? ".STRHEX(I)) ->KSERVE FINISH J=J<<24!(INTEGER(K+8)>>8&255) ! h/w no./00/00/strm K=I>>16&15; ! int. sub-class IF K=0 THEN J=J!X'00208000' ELSE C { normal term } IF K=1 THEN J=J!X'00208400' ELSE C { abterm } IF K=4 THEN J=J!X'00204000' C { attention } ELSE J=J!X'00201000' { control term } P_DEST=X'300003' P_P1=J P_P2=I GDC(P) IF MONLEVEL&4#0 START TSERVICE=58 ->KTIMES FINISH ELSE ->KSERVE FINISH ELSE START ; ! P series *IDLE_X'FC'; ! should not occur FINISH !----------------------------------------------------------------------- JLUNQ: ! JUMP&LINK VERSION OF ROUTINE UNQUEUE ! DR DESCRIBES QUEUE *LB_(DR ); *MYB_8; *ADB_SERVA+4 *LCT_B ; ! CTB TO SERVQ *LB_(CTB +1); *STB_TOS *MYB_8; *ADB_SERVA+4 *LXN_B ; ! XNB TO SERV *LSS_(XNB +0); *OR_X'40000000'; *ST_(XNB +0) *LB_TOS ; *CPB_(DR ); *JCC_7,<JLUNQA> *LSS_0; *ST_(DR ); *J_<JLUNQB> JLUNQA: *LSS_(XNB +1); *ST_(CTB +1) JLUNQB: *LSS_0; *ST_(XNB +1) *J_TOS ; ! SERVICE NO IN B !%ROUTINE UNQUEUE(%INTEGERNAME QUEUE,UNQUED SERVICE) !!*********************************************************************** !!* UNQUEUES A SERVICE FROM MAIN OR RUN QUEUES AND MARKS IT * !!* AS BEING EXECUTED * !!*********************************************************************** !%INTEGER SERVICE; ! LOCAL COPY OF UNQUED SERVICE !%RECORD(SERVF)%NAME SERVQ; ! MAPPED ON TO SERVICE AT BACK OF Q !%RECORD(SERVF)%NAME SERV; ! FOR UNQUED SERVICE ! SERVQ==SERVA(QUEUE); ! BACK OF Q. L POINTS TO FRNT ! SERVICE=SERVQ_L; ! SERVICE TO UNQUEUE ! SERV==SERVA(SERVICE) ! SERV_P=SERV_P!X'40000000'; ! MARK AS UNDER EXECUTION ! %IF SERVICE=QUEUE %THEN QUEUE=0 %ELSE SERVQ_L=SERV_L ! SERV_L=0 ! UNQUED SERVICE=SERVICE !%END END ; ! OF GLOBAL CONTROLLER ROUTINE SCHEDULE(RECORD (PARMF)NAME P) !*********************************************************************** !* ACTIVITY 0 : INITIALISE * !* ACTIVITY 1 : CREATE FOREGROUND PROCESS * !* ACTIVITY 2 : REPLY FROM CREATE PROCESS * !* ACTIVITY 3 : OUT OF EPAGES FROM LOCAL CONTROLLER * !* ACTIVITY 4 : OUT OF TIME SLICES FROM LOCAL CONTROLLER * !* ACTIVITY 5 : SUSPEND PROCESS * !* ACTIVITY 6 : TRY AND LOAD FURTHER PROCESS * !* ACTIVITY 7 : UNSUSPEND PROCESS * !* ACTIVITY 8 : DESTROY PROCESS * !* ACTIVITY 9 : REPLY FROM PAGE-IN OF LOCAL CONTROLLER STACK * !* ACTIVITY 10: MORE EPAGES ON THE FLY ? * !* ACTIVITY 11: MORE TIME ON THE FLY ? * !* ACTIVITY 12: SNOOZING HAS TIMED OUT * !* ACTIVITY 13: RESCHEDULE ALL RESIDENT TO FREE SMAC * !* ACTIVITY 14: DEADLOCK RECOVERY * !* ACTIVITY 15: UPDATE OPER DIPLAY * !* ACTIVITY 16: CREATE BACKGROUND JOB * !* ACTIVITY 17: START OR RESTART DIRECT * !* ACTIVITY 18: SUSPEND ON FLY? * !*********************************************************************** ROUTINESPEC PARE EPAGES ROUTINESPEC ONPQ CONSTINTEGER PRATMAX=255,PRIQS=5 CONSTBYTEINTEGERARRAY PRAT(0:PRATMAX)= C 1,1,2,1,3,1,1,2,1,1,2,1,1,4,1,2,1,1,2,1,1,1,2,1,1,3,1,1,2,1,1,2, 1,1,2,1,3,1,1,2,1,1,2,1,1,5,1,2,1,1,2,1,1,1,2,1,1,3,1,1,2,1,1,2, 1,1,2,1,3,1,1,2,1,1,2,1,1,4,1,2,1,1,2,1,1,1,2,1,1,3,1,1,2,1,1,2, 1,1,2,1,3,1,1,2,1,1,2,1,1,5,1,2,1,1,2,1,1,1,2,1,1,3,1,1,2,1,1,2, 1,1,2,1,3,1,1,2,1,1,2,1,1,4,1,2,1,1,2,1,1,1,2,1,1,3,1,1,2,1,1,2, 1,1,2,1,3,1,1,2,1,1,2,1,1,5,1,2,1,1,2,1,1,1,2,1,1,3,1,1,2,1,1,2, 1,1,2,1,3,1,1,2,1,1,2,1,1,4,1,2,1,1,2,1,1,1,2,1,1,3,1,1,2,1,1,2, 1,1,2,1,3,1,1,2,1,1,2,1,1,5,1,2,1,1,2,1,1,1,2,1,1,3,1,1,2,1,1,2; OWNINTEGER PRATP=0,SCHTICKS=0 !----------------------------------------------------------------------- ! PRIORITY QUEUE ARRAY ETC. OWNBYTEINTEGERARRAY PQ(1:MAXPROCS)=0(MAXPROCS) OWNBYTEINTEGERARRAY PQH(1:PRIQS)=0(PRIQS);! NUMBER OF PRIORITIES=PRIQS OWNBYTEINTEGERARRAY PQN(1:PRIQS)=0(PRIQS) IF MONLEVEL&1#0 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:20) IF MONLEVEL&2#0 AND KMON&1<<3#0 THEN C PKMONREC("SCHEDULE:",P) ACT=P_DEST&X'FFFF' PROCESS=P_P1 IF 0<PROCESS<=MAXPROCS THEN START PROC==PROCA(PROCESS) OLDCATSLOT=PROC_CATEGORY OLDCAT==CATTAB(OLDCATSLOT) FINISH IF MULTIOCP=YES THEN START *INCT_SCHEDSEMA *JCC_8,<SSEMAGOT> SEMALOOP(SCHEDSEMA,0) 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 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 TOTAL 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 user="OCP ".strint(com_ocpport0) if multi ocp=yes and com_nocps>1 then charno(user,4)='s' display text(0,4,13,user) P_DEST=X'80000' ACTIVE MEM(P) IF SNOOZING=YES OR MONLEVEL&1#0 START P_DEST=X'A0001'; ! REGULAR CLOCK TICK P_SRCE=0 P_P1=X'F000F'; ! ON SCHED ALT SERVICE NO P_P2=5; ! AT 5 SEC INTERVALS PON(P); ! FOR VIDEO & BOOTING FINISH ALLOW PERI INTS=X'01800824'; ! PERMITS INTS BETWEEN KERNEL ! SERVICES NOW INITIALISATION ! IS COMPLETED(XCEPT IT,IC&MP INTS) ! ! START "DIRECT" PROCESS TAKING CARE ITS INCARNATION IS 0 ! AND THAT ALL ITS TEMP SPACE IS IN X40 EPAGES(1 SEGMENT) ! ACTIVITY(17): ! FOR DIRECTOR RESTARTS P_DEST=X'30001' P_SRCE=0; ! NO REPLY WANTED P_P1=M'DIR'!6<<24 P_P2=M'ECT'<<8; ! ENSURE INCAR=0 P_P3=COM_SUPLVN<<24!X'500'; ! LSTACKDA(NEEDS 3 EPAGES ONLY) P_P4=0; ! USE DEFAULT DIRVSN P_P5=P_P3+LSTACKLEN; ! DSTACKDA(1SEG IN CBT BUT USES LESS) P_P6=P_P3+(X'40'-8); ! DGLADA (ALLOW LAST 8 PAGES) PON(P) IF MULTIOCP=YES START ; *TDEC_SCHEDSEMA; FINISH RETURN !----------------------------------------------------------------------- ACTIVITY(16): ! CREATE BATCH JOB ACTIVITY(1): ! CREATE FORGROUND PROCESS ! P_P1/P2 : STRING(USER NAME) ! P_P3 : L-C STACK DISC ADDRESS ! P_P4 : DIRCODE DISC ADDRESS ! (<=0 FOR DEFAULT) ! P_P5 : DIR STACK DISC ADDRESS ! P_P6 : DIR GLA DISC ADDRESS SRCE=P_SRCE USER=P_USER INCAR=P_INCAR IF COM_USERS>=MAXPROCS-1 THEN P_P1=1 AND ->STARTREP;! SYSTEM FULL PROCESS=0 IF USER="DIRECT" THEN PROCESS=1 IF USER="SPOOLR" THEN PROCESS=3 IF USER="VOLUMS" THEN PROCESS=2 IF USER="MAILER" THEN PROCESS=4 IF USER="FTRANS" THEN PROCESS=5 IF PROCESS>0 START PROC==PROCA(PROCESS) IF PROC_USER#"" THEN P_P1=3 AND ->STARTREP 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 PROC_ACTIVE=0; ! SUSPENDED PROC_CATEGORY=0 IF MONLEVEL&1#0 THEN SUSPN=SUSPN+1 IF MULTIOCP=YES START ; *TDEC_SCHEDSEMA; FINISH IF ACT=16 START FOR I=1,1,6 CYCLE J=BYTEINTEGER(ADDR(USER)+I) IF 'A'<=J<='Z' THEN J=J!32 BYTEINTEGER(ADDR(USER)+I)=J REPEAT FINISH UPDISP(PROCESS,4,USER) CLEAR PARMS(PROCESS+LOCSN0) CLEAR PARMS(PROCESS+LOCSN1) UNLESS PROCESS<FIRST UPROC 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 START ; *TDEC_SCHEDSEMA; FINISH 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 IF RECONFIGURE=YES AND SMAC RCONFIG#0 THEN ->WAYOUT IF OLDCAT_PRIORITY<=3 AND PROC_STATUS&HADPONFLY=0 C AND XEPS<FREE EPAGES+PAGE FREES THEN ->GIVE 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 I<K CYCLE J=J+PQN(I) I=I+1 REPEAT IF J#0 THEN ->WAYOUT; ! NO: MORE URGENT WORK GIVE PAGES: ! WITHOUT BOUNCING PROC_STATUS=PROC_STATUS!HADPONFLY;! SO HE WONT DO IT AGAIN UNALLOCEPS=UNALLOCEPS-XEPS PROC_CATEGORY=NEWCATSLOT P_P1=NEWCAT_EPLIM PROC_EPA=NEWCAT_EPLIM CONT: P_P2=NEWCAT_RTLIM P_P3=NEWCAT_STROBEI; ! SO L-C CAN DECIDE TO STROBE IF OLDCAT_PRIORITY>=4 THEN P4PAGES=P4PAGES-OLDCAT_EPLIM IF NEWCAT_PRIORITY>=4 THEN P4PAGES=P4PAGES+NEWCAT_EPLIM IF NEWCAT_PRIORITY=4=OLDCAT_PRIORITY AND PROC_P4TOP4<255 C AND PROCESS>=FIRST UPROC THEN PROC_P4TOP4=PROC_P4TOP4+1 IF MONLEVEL&32#0 THEN C FLYCAT(NEWCATSLOT,OLDCATSLOT)<-FLYCAT(NEWCATSLOT,OLDCATSLOT)+1 WAYOUT: IF MULTIOCP=YES START ; *TDEC_SCHEDSEMA; FINISH RETURN !----------------------------------------------------------------------- ACTIVITY(4): ! OUT OF TIME NEWCATSLOT=OLDCAT_MORET PARE EPAGES ->STOUT !----------------------------------------------------------------------- ACTIVITY(11): ! MORE TIME ON THE FLY? ! BE KIND TO VOLUMS&SPOOLR P_P1=0 IF OLDCAT_PRIORITY>=4 AND P4PAGES>=MAXP4PAGES AND SXPAGES> C (SHAREDEPS+UNALLOCEPS) AND PROCESS>=FIRST UPROC THEN ->WAYOUT IF RECONFIGURE=YES AND SMAC RCONFIG#0 THEN ->WAYOUT NEWCATSLOT=OLDCAT_MORET NEWCAT==CATTAB(NEWCATSLOT) IF PROC_STATUS&HADTONFLY=0 AND 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 PROCESS<FIRST UPROC AND PQN(4)>0 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+UNALLOCEPS<MAX EPAGES %AND OLDCAT_PRIORITY>1 %C ! %THEN ->WAYOUT; ! NO ! IF RECONFIGURE=YES AND SMAC RCONFIG#0 THEN ->WAYOUT I=(PQN(1)+PQN(2))*MAXEPAGES>>1;! PAGES NEEDED TO CLERAR QS ! ! THE NEXT CONDITION IS CRUCIAL FOR SATISFACTORY SNOOZING ! CAN NOT AFFORD IN GENERAL TO ALLOW ANYONE TO SNOOZE WHEN THERE ARE ! NOT ENOUGH FREE PAGES TO CLEAR QUEUEING INTEGERACTIVE PROCESSES ! HOWEVER IN LARGE STORE NO DRUM CONFIGURATIONS QUEUEING MAY BE ! DUE TO LARGE NUMBER OF PAGE FREES BUILDING UP. IN THESE CIRCUMSTANCES ! IT IS BETTER TO LET THIS CHAP SNOOZE TILL THING QUIETEN DOWN. ! THE BIGGER THE STORE THE TRUEUER THIS IS SO DO NOT SCALE PAGE FREES ! FOR BIGGER CORE SIZES ! IF I>FREE EPAGES+PAGE FREES AND (PAGE FREES<MAX EPAGES>>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&32#0 THEN FLYCAT(NEWCATSLOT,OLDCATSLOT) <- C FLYCAT(NEWCATSLOT,OLDCATSLOT)+1 MPLEVEL=MPLEVEL-1 IF OLDCAT_PRIORITY>=4 THEN P4PAGES=P4PAGES-OLDCAT_EPLIM;! PEDANTIC ! P_DEST=X'A0002'; P_SRCE=X'30012';! KICK ELAPSED INT P_P1=X'3000C'!PROCESS<<8 P_P2=SNOOZTIME; P_P3=PROCESS PON(P) P_P1=0; ! YES MAY SUSPEND ON FLY FINISH IF NPQ#0 THEN P_DEST=X'30006' AND PON(P) ->WAYOUT !---------------------------------------------------------------------- ACTIVITY(5): ! SUSPEND IF MONLEVEL&1#0 THEN SUSPN=SUSPN+1 I=8!(1<<((P_SRCE-LOCSN0)//MAXPROCS)) PUNINH(PROCESS,I) PSTATE="S " IF PROC_STATUS&AMT LOST=0 AND SMAC RCONFIG=0 AND C (PROCESS<FIRST UPROC OR OLDCAT_PRIORITY*COM_USERS<=COM_SEPGS)C THEN PROC_STATUS=PROC_STATUS!STATEX AND PSTATE="X " IF MONLEVEL&1#0 THEN UPDISP(PROCESS,11,PSTATE) PROC_ACTIVE=0 IF PROC_STATUS&8#0 START ; ! DELLOCATE AMT ONLY PROC_STATUS=PROC_STATUS!!8 PROC_ACTIVE=3; ! GUESS.2-5 POSSIBLE DEPENDING ! ON CURRENT DRUN LOADING FINISH NEWCATSLOT=OLDCAT_SUSP PARE EPAGES IF NEWCAT_PRIORITY<4 AND PROC_STATUS&(STATEX!4)=STATEX THEN C SXPAGES=SXPAGES+PROC_EPN ->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 PROC_RUNQ=OLDCAT_RQTS1 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) IF MONLEVEL&4#0 THEN PERFORM_SNOOZN=PERFORM_SNOOZN+LSTACKLENP ->WAYOUT FINISH PROC_ACTIVE=255 IF OLDCAT_PRIORITY<4 AND PROC_STATUS&(STATEX+4)=STATEX THEN C SXPAGES=SXPAGES-PROC_EPN ONPQ ->LOAD !----------------------------------------------------------------------- ACTIVITY(8): ! DESTROY PROCESS MPLEVEL=MPLEVEL-1 DESTROY: UPDISP(PROCESS,4," ") COM_USERS=COM_USERS-1 PINH(PROCESS,X'F'); ! ALL PROCESS SERVICES IF OLDCAT_PRIORITY>=4 THEN P4PAGES=P4PAGES-OLDCAT_EPLIM P_DEST=X'40002'; ! PAGE-TURN OUT P_SRCE=X'30008' P_P2=0; ! REGARD AS NOT WRITTEN TO CYCLE I=0,1,LSTACKLEN-1 P_P1=PROC_LAMTX<<16!I PON(P) REPEAT P_DEST=X'80002'; ! RETURN AMTX FOR L-CNTRLR STACK P_P1=0; ! ID NOT USED P_P2=PROC_LAMTX P_P3=1; ! DESTROY FLAG PON(P) PROC=0 ->DEALL !----------------------------------------------------------------------- STOUT: ! PAGE-OUT LOCAL CONTROLLER STACK IF NEWCAT_PRIORITY=4=OLDCAT_PRIORITY AND PROC_P4TOP4<255 C AND PROCESS>=FIRST UPROC THEN PROC_P4TOP4=PROC_P4TOP4+1 IF MONLEVEL&32#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>=40 START ;! TOO MANY WRITEOUT PRATP=(PRATP+1)&PRATMAX; ! PASS OVER BIG JOB IF MULTIOCP=YES START ; *TDEC_SCHEDSEMA; FINISH P_DEST=X'A0002' P_P1=X'30006'; P_P2=1 PON(P); ! WAIT 1 SEC RETURN FINISH PROCESS=PQ(PQH(PTY)) PROC==PROCA(PROCESS) OLDCATSLOT=PROC_CATEGORY OLDCAT==CATTAB(OLDCATSLOT) ! ! THE IDEA OF THE NEXT FEW LINES IS TO RESTRICT P4 JOBS TO 1 OR TO ! P4PAGES OF STORE EXCEPT WHEN THERE ARE SO FEW FOREGROUND USERS ! ASLLEEP THAT THEY WILL NOT BE INCONVENINECED. ! IF PTY>=4 THEN START IF P4PAGES>0 AND P4PAGES+OLDCAT_EPLIM>MAXP4PAGES AND C SXPAGES>(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 ->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 MULTIOCP=YES START ; *TDEC_SCHEDSEMA; FINISH ! PAGE IN LOCAL CONTROLLER STACK P_SRCE=X'30009' IF PROC_STATUS&STATEX#0 THEN I=LSTACKLENP ELSE I=0 PQ(PROCESS)=LSTACKLEN-I; ! TO COUNT PAGE-TURN REPLIES CYCLE I=I,1,LSTACKLEN-1 IF I=0 THEN P_DEST=X'40009' ELSE P_DEST=X'40001';! PAGETURN/PAGE-IN ! BUT PAGE 0 TO SYSTEM SMAC NOT DAP 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 P_DEST=(PROCESS+LOCSN0)<<16!8 P_SRCE=X'3000C' PON(P) FINISH IF MULTIOCP=YES START ; *TDEC_SCHEDSEMA; FINISH RETURN !----------------------------------------------------------------------- ACTIVITY(13): ! RESCHEDULE ALL RESIDENT TO FREE SMAC CYCLE I=1,1,MAXPROCS PROC==PROCA(I) IF PROC_USER#"" 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*(300-PROC_P4TOP4)//300 PON(P) FINISH IF MULTIOCP=YES START ; *TDEC_SCHEDSEMA; FINISH RETURN !----------------------------------------------------------------------- ACTIVITY(15): ! UPDATE OPER INFO(EVERY 5 SECS) SCHTICKS=SCHTICKS+1 IF SCHTICKS&3=0 START ; ! @EVERY 20 SECS I=1; J=0 UNTIL J=COM_USERS OR I>MAXPROCS CYCLE PROC==PROCA(I) IF PROC_USER#"" THEN START IF I>=FIRST UPROC AND PROC_ACTIVE=3*MINSINACTIVE C AND PROC_STATUS&X'404'=0 START ;! NOT BATCH OR DAP P_DEST=(I+LOCSN3)<<16+1 P_P1=-1; P_P2=-1 P_P3=X'01570000'; ! SEND INT W PON(P) FINISH PROC_ACTIVE=PROC_ACTIVE+1 UNLESS PROC_ACTIVE>200 J=J+1 FINISH I=I+1 REPEAT FINISH IF MULTIOCP=YES START ; *TDEC_SCHEDSEMA; FINISH IF MONLEVEL&1#0 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(COM_USERS)." ") 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 !----------------------------------------------------------------------- ACTIVITY(19): ! SET BITS IN P_P2 INTO STATUS ! OF PROCESS IN P_P1 PROC_STATUS=PROC_STATUS!P_P2 ->WAYOUT ACTIVITY(20): ! CONVERSE OF 19 PROC_STATUS=PROC_STATUS&(¬P_P2) ->WAYOUT ROUTINE PARE EPAGES !*********************************************************************** !* CHAIN BACK DOWN CATEGORY TABLE TO FIND THE BEST FIT * !* AFTER ALLOWING SOME LEEWAY * !*********************************************************************** CONSTINTEGER LEEWAY=2 CYCLE NEWCAT==CATTAB(NEWCATSLOT) IF NEWCAT_LESSP=0 OR 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 * !* ACTIVITY 9 : AS ACT 1 BUT PLACE IN SYSTEM SMAC IF POSSIBLE * !* STORE FLAGS SIGNIFY AS FOLLOWS : * !* BIT 7 : DISC TRANSFER IN PROGRESS(1)/NOT IN PROGRESS(0) * !* BIT 6 : DISC INPUT(0)/OUTPUT(1) * !* BIT 5 : DRUM TRANSFER IN PROGRESS(1)/NOT IN PROGRESS(0) * !* BIT 4 : DRUM INPUT(0)/OUTPUT(1) * !* BIT 3 : WRITTEN TO MARKER * !* BIT 2 : TYPE (0:DISC ONLY, 1:DISC & DRUM) * !* BIT 1 : MAKE NEW IE DONT PAGE OUT & SUPPLY ZEROPAGE ON REREAD * !* BIT 0 : RECAPTURABLE(IF ON FREE LIST ON PAGING OUT) * !*********************************************************************** CONSTINTEGER ZEROPAGEAD=X'804C0000' INTEGER AEX,AMTX,EPX,DDX,DTX,FLAGS,STOREX,SRCE,CALL,ID,I,B,F,PAGEMASK IF MONLEVEL&12=12 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:9) 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,<SSEMAGOT> SEMALOOP(STORESEMA,0) SSEMAGOT: FINISH I=AMTDDDDX ! %IF SFCFITTED=NO %OR I&DTXBIT=0 %START;! NO DRUM PAGE ALLOCATED ! STOREX=I&STXMASK ! DTX=-1 ! %FINISH %ELSE %START ! DTX=I&STXMASK ! STOREX=DRUMT(DTX) ! %FINISH IF SFC FITTED=YES THEN START *LSS_I; *AND_DTXBIT; *JAT_4,<MCL1> *LB_I; *SBB_DTXBIT; *STB_DTX *ADB_B ; *LSS_(DRUMT+B ) *ST_STOREX; *J_<MCL2> MCL1: FINISH *LSS_I *AND_STXMASK; *ST_STOREX *LSS_-1; *ST_DTX MCL2: ->ACTIVITY(P_DEST-X'40000') !----------------------------------------------------------------------- ACTIVITY(9): ! PAGE INTO SYTEM SMACS PAGEMASK=COM_SMACS>>16 ->ACT1 ACTIVITY(1): ! PAGE-IN (ALLOWS PAGETURN TO BE CALLED) PAGEMASK=-1 ACT1: IF MONLEVEL&4#0 THEN PERFORM_PTURNN=PERFORM_PTURNN+1 AMT_USERS=AMT_USERS+1 CALL=P_SRCE SRCE=CALL&X'7FFFFFFF' ID=P_P2 IF STOREX=STXMASK THEN ->FETCH PAGE HERE: ! EPAGE ALLOCATED ST==STORE(STOREX) ! ->NOTRECAP %UNLESS ST_FLAGS=1 %AND ST_USERS=0;! RECAPTURE ! ST_FLAGS=0 ! ST_USERS=1 ! ST_LINK=0 ! F=ST_FLINK ! B=ST_BLINK ! ST_BLINK=AMTX ! ST_FLINK=EPX *LCT_ST+4; *LSS_(CTB +0) *USH_-16; *ICP_X'0100'; ! FLAGS=1 & USERS=0 *JCC_7,<NOTRECAP> *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_<PUSHPIT> MUST WAIT: ! FOR FREE PAGE OR TRANSFER IF MULTIOCP=YES START ; *TDEC_(STORESEMA); FINISH P_DEST=0; ! IF CALLED MEANS PAGE COMING RETURN FINISH PAGEIN REPLY: ! INTACT COPY IN STORE IF ! RECAPTURED OR PAGING OUT:REPLY ! PAGE IMMEDIATELY AVAILABLE P_P1=ID; ! IDENTIFIER P_P2=ST_REALAD&X'0FFFFFFF'; ! MAY BE FLAWED(BIT SET IN TOP) P_P3=0; ! SUCCESS IF MONLEVEL&256#0 START P_P5=ST_USERS P_P6=ST_FLAGS FINISH IF MULTIOCP=YES START ; *TDEC_(STORESEMA); FINISH IF CALL>0 THEN P_DEST=SRCE AND P_SRCE=X'40001' AND PON(P) RETURN FETCH PAGE: ! ALLOCATE EPAGE IF AMTDDDDX&NEWEPBIT#0 THEN I=0 ELSE I=1;! CLEAR IF NEW IF FREE EPAGES>0 THEN STOREX=QUICK EPAGE(I,PAGEMASK) AND ->ACT3 P_SRCE=X'40003' P_P1=AEX P_P2=I; ! =0 FOR ZEROED P_P5=SRCE P_P6=ID IF LOCSN0<SRCE>>16<=LOCSN1 THEN GET EPN=GET EPN+1 IF MULTIOCP=YES START ; *TDEC_(STORESEMA); FINISH IF PAGEFREES<=1 AND GETEPN>=MPLEVEL+1-COM_NOCPS THEN 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 START ; *TDEC_(STORESEMA); FINISH 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_<PUSHPIT> ST_FLAGS=X'20'; ! DRUM->STORE TRANSIT FLAGS=X'20'; ! DRUM TRANSFER TO BE STARTED IF MULTIOCP=YES START ; *TDEC_(STORESEMA); FINISH TDRUM_DEST=X'280001' TDRUM_SRCE=X'80040006' TDRUM_P1=AEX TDRUM_P2=DTX TDRUM_P3=STOREX P_DEST=0; ! IN CASE CALLED ->TRANSFER NEEDED FINISH ! NO DRUMS OR PAGE IS ON DISC *JLK_<PUSHPIT> DRUMRF: ! DRUM READ FAILURES REJOIN HERE AMTDDDDX=STOREX ST_FLAGS=X'80'; ! DISC->STORE TRANSIT FLAGS=X'80'; ! DISC TRANSFER NEEDED IF MULTIOCP=YES START ; *TDEC_(STORESEMA); FINISH TDISC_DEST=X'210005'; ! DIRECT REPLIES TO LC TDISC_SRCE=X'80040099' TDISC_P1=AEX TDISC_P2=AMT_DA+EPX ;! DISC ADDRESS TDISC_P3=STOREX P_DEST=0 ->TRANSFER NEEDED !----------------------------------------------------------------------- ACTIVITY(6): ! FAILURE REPLY FROM DRUM/READ IF SFCFITTED=YES 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) IF ST_USERS=0 OR AMT_USERS=0 START OPMESS("? PAGEOUT ".STRHEX(AEX)) OPMESS("SRCE ".STRHEX(P_SRCE)) OPMESS("INFORM PDS") IF MULTIOCP=YES START ; *TDEC_(STORESEMA); FINISH RETURN FINISH AMT_USERS=AMT_USERS-1 ST_FLAGS=ST_FLAGS!P_P2; ! INSERT WRITTEN ETC. MARKERS ST_USERS=ST_USERS-1 IF ST_USERS>0 THEN START SHAREDEPS=SHAREDEPS-1 IF MULTIOCP=YES START ; *TDEC_(STORESEMA); FINISH RETURN FINISH PAGEFREES=PAGEFREES+1; ! PAGE ABOUT TO BECOME FREE IF ST_FLAGS&X'A0'#0 THEN ->MUST WAIT ! PREVIOUS WRITEOUTS STILL GOING PAGEOUT: ! ACTUALLY PAGE IT OUT FLAGS=0; ! NO TRANSFER SET UP YET ! ! FIRST UPDATE DISC COPY IF PAGE HAS BEEN UPDATED. THEN CONSIDER ! WHETHER TO UPDATE OR GENERATE A DRUM COPY ! IF ST_FLAGS&X'0A'=8 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 START ; *TDEC_(STORESEMA); FINISH TRANSFER NEEDED: ! TO COMPLETE PAGETURN IF FLAGS&X'80'#0 THEN START ; ! DISC TRANSFER TO START IF MONLEVEL&12=12 THEN START *LSS_(6); *ST_IC; *LSS_(5); *ST_IT FINISH PDISC(TDISC) IF MONLEVEL&12=12 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&12=12 START *LSS_(6); *ST_IC; *LSS_(5); *ST_IT FINISH DRUM(TDRUM) IF MONLEVEL&12=12 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 START ; *TDEC_(STORESEMA); FINISH FLAGS=X'80'; ! DISC WRITE INITIATED TDISC_DEST=X'210002'; ! WRITEOUT TDISC_SRCE=X'80040008'; ! REPLY TO ACT 8 TDISC_P1=AEX TDISC_P2=AMT_DA+EPX TDISC_P3=ZEROPAGEAD ->TRANSFER NEEDED !---------------------------------------------------------------------- ACTIVITY(5): ! REPLY FROM DISC/WRITE ST==STORE(STOREX) ! ! THERE ARE THREE POSSIBLE COURSES OF ACTION ON DISC FAILURE ! 1) FRIG THE USER COUNT SO IT STAYS IN CORE ! 2) TRY AGAIN (UNHELPFUL SINCE 42*8 TRIES ALREADY MADE) ! 3) DO NOTHING AND RELY ON NEXT READ FAILING ! FOR THE MOMENT FOLLOW COURSE 3 ! ST_FLAGS=ST_FLAGS&X'3F'; ! NO DISC TRANSFER IF P_P2=4 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&12=12 THEN START *LSS_(6); *ST_IC; *LSS_(5); *ST_IT FINISH RETURN EPAGE(P) IF MONLEVEL&12=12 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&12=12 THEN START *LSS_(6); *ST_IC; *LSS_(5); *ST_IT FINISH ACTIVE MEM(P) IF MONLEVEL&12=12 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 START ; *TDEC_(STORESEMA); FINISH 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 AMTDDDDX=AMTDDDDX&(¬NEWEPBIT); ! CLEAR NEW MARKER AMT_OUTS=AMT_OUTS-1 ->RAMTX !---------------------------------------------------------------------- PUSHPIT: ! AWAIT TRANSFER USING THE PIT LIST I=NEWPPCELL PP==PARM(I) PP_DEST=SRCE PP_SRCE=X'40003' PP_P1=ID PP_P2=ST_REALAD&X'0FFFFFFF'; ! MAY BE FLAWED PP_P3=0; ! SUCCESS FLAG PP_P6=DTX; ! TELL IF DRUM OR DISC IN DUMP PP_LINK=ST_LINK ST_LINK=I *J_TOS END !---------------------------------------------------------------------- IF SFCFITTED = YES 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 SSERIES=YES OR RECONFIGURE=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 IF SMAC RCONFIG#0 AND FSTASL#STOREX#BSTASL START STORE(ST_FLINK)_BLINK=0 STORE(ST_BLINK)_FLINK=0 STORE(BSTASL)_FLINK=FSTASL STORE(FSTASL)_BLINK=BSTASL BSTASL=ST_BLINK FSTASL=ST_FLINK FINISH ELSE START STORE(ST_FLINK)_BLINK=ST_BLINK STORE(ST_BLINK)_FLINK=ST_FLINK FINISH EXIT FINISH STOREX=ST_FLINK IF STOREX=0 THEN RESULT =-1 ST==STORE(STOREX) REPEAT FINISH ST_USERS=1 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,<SEMACL> SEMALOOP(STORESEMA,0) SEMACL: FINISH IF FREEEPAGES=0 THEN START ; ! SHOULD ONLY OCCUR IN MULTIOCPS IF MULTIOCP=YES START ; *TDEC_(STORESEMA); FINISH PON(P); ! SERVICE NOW INHIBITED RETURN FINISH IF MONLEVEL&2#0 AND KMON&1<<5#0 THEN 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<PS>>16<=LOCSN1 THEN GETEPN=GETEPN-1 IF MULTIOCP=YES START ; *TDEC_(STORESEMA); FINISH PON(P) END !----------------------------------------------------------------------- INTEGERFN NEW EPAGE !*********************************************************************** !* HANDS OUT A NEW EPAGE TO EXTEND A VITAL RESIDENT TABLE * !*********************************************************************** INTEGER I IF MULTIOCP=YES THEN START *INCT_(STORESEMA) *JCC_7,<USE SPARE>; ! CAN NOT LOOP HERE FINISH IF FREE EPAGES>0 THEN START I=QUICK EPAGE(0,COM_SMACS>>16);! ZEROED & IN SYSTEM SMAC IF I<0 THEN ->USE SPARE IF MULTI OCP=YES START ; *TDEC_(STORESEMA); FINISH STORE(I)_USERS=255 RESULT =STORE(I)_REALAD&X'0FFFFFFF';! MAY BE FLAWED FINISH USE SPARE: ! try emergency spare page IF MULTIOCP=YES START ; *TDEC_(STORESEMA); FINISH IF SPSTOREX>0 START I=STORE(SPSTOREX)_REALAD; ! CANNOT BE FLAWED(SEE RETURNEPAGE) SPSTOREX=0 RESULT =I FINISH RESULT =-1 END !----------------------------------------------------------------------- ROUTINE RETURN EPAGE(RECORD (PARMF)NAME P) !*********************************************************************** !* PUT AN EPAGE BACK ON THE FREE LIST. FLAWED PAGES ARE ABANDONED * !* IF THE PAGE IS MARKED AS 'RECAPTURABLE' IT GOES TO THE BACK OF * !* OF THE FREELIST OTHERWISE IT GOES ON THE FRONT. THIS GIVES THE * !* MAXIMUM CHANCES OF RECAPTURING ANYTHING USEFUL * !*********************************************************************** CONSTINTEGER CLEARTB=X'58000000'+1024*EPAGESIZE RECORD (STOREF)NAME ST INTEGER I,STOREX,STAD,ACT ACT=P_DEST&1 IF MULTIOCP=YES AND ACT=0 THEN START *INCT_(STORESEMA) *JCC_8,<SEMACL> SEMALOOP(STORESEMA,0) SEMACL: FINISH IF MONLEVEL&2#0 AND KMON&1<<6#0 THEN C PKMONREC("RETURNEPAGE:",P) STOREX=P_P2 ST==STORE(STOREX) ST_USERS=0 ! IF PAGE IS IN SMAC BEING ! RECONFIGURED THEN DISCARD IF RECONFIGURE=YES AND 0#SMAC RCONFIG=ST_REALAD>>22&15 START SMAC RPAGES=SMAC RPAGES-1 *JLK_<STOP RECAPTURE> ->RETURN FINISH IF ST_REALAD<=0 THEN START IF STOREX=0 THEN MONITOR("PAGE 0 RETURNED???") OPMESS("PAGE ".STRINT(STOREX)." ABANDONED") *JLK_<STOP RECAPTURE> ->RETURN FINISH ! ! REPLENSISH THE SPARE PAGE FROM THE ALLOWED SYSTEM SMACE ONLY ! IF SPSTOREX=0 AND (SSERIES=YES OR RECONFIGURE=NO OR C COM_SMACS&X'10000'<<(ST_REALAD>>22&15)#0) START *JLK_<STOP RECAPTURE> 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 START ; *TDEC_(STORESEMA); FINISH 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,<SEMAGOT> SEMALOOP(STORESEMA,0) SEMAGOT: FINISH UNLESS PAGEFREES<=1 AND GETEPN>=MPLEVEL+1-COM_NOCPS START IF MULTIOCP=YES START ; *TDEC_(STORESEMA); FINISH RETURN ; ! NOT A TRUE DEADLOCK FINISH N=GETEPN GETEPN=GETEPN-1; ! ASSUMES WE WILL CURE DEADLOCK IF MULTIOCP=YES START ; *TDEC_(STORESEMA); FINISH CYCLE I=1,1,4*N; ! ALLOW FOR PLENTY OF OTHER RQS SUPPOFF(SERVA(5),P); ! TAKE A GET PAGE REQUEST IF (P_SRCE=X'40003' AND LOCSN0<P_P5>>16<=LOCSN1) OR C LOCSN0<P_SRCE>>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<MAX OVERALLOC THEN OVERALLOC=OVERALLOC+K AND C UNALLOCEPS=UNALLOCEPS+K END !----------------------------------------------------------------------- ROUTINE ACTIVE MEM(RECORD (PARMF)NAME P) !*********************************************************************** !* CONTROLS THE ALLOCATION OF ACTIVE MEMORY * !* ACTIVITY 0 INITIALISE * !* ACTIVITY 1 GET AMT FOR SPECIFIED DISC ADDRESSS * !* ACTIVITY 2 RETURN AMT FOR DITTO * !* ACTIVITY 3 COMPLETE RETURN OF AMT AFTER TRANSFER COMPLETED * !* ACTIVITY 4 ORGANISE TIMEOUT OF ACTIVE MEM * !* ACTIVITY 5 CHECK IF DISC ADDRESS IS STILL ACTIVE * !*********************************************************************** ROUTINESPEC COLLECT DD GARBAGE ROUTINESPEC APPENDAMTA(INTEGER NEWSPACE,REALAD) ROUTINESPEC APPENDAMTDD(INTEGER NEWSPACE,REALAD) ROUTINESPEC DDASLALLOC(INTEGER FROM,TO) ROUTINESPEC DEALLOCAMT ROUTINESPEC DEALLOCDD(INTEGER DDX,LEN) INTEGER HASH,DDX,GARB,AMTX,SRCE,ID,DA,LEN,MASK,REALAD,FREEMAX,I,J,K,CN INTEGER DACT IF MONLEVEL&12=12 THEN START INTEGER IT,IC FINISH LONGINTEGER LIM RECORD (PROCF)NAME PROC RECORD (PARMF) Q OWNHALFINTEGERARRAY AMTHASH(0:511)=0(512) RECORD (AMTF)NAME AMT OWNINTEGERARRAYNAME AMTAPT OWNINTEGER AMTASIZE,AMTASL,AMTANEXT=0 OWNINTEGER AMTDDSIZE,AMTDDNEXT=0 OWNINTEGERARRAYNAME AMTDDPT OWNINTEGERARRAY DDASL(1:MAXBLOCK)=0(MAXBLOCK) SWITCH ACT(0:6) IF MONLEVEL&2#0 AND KMON&1<<8#0 THEN C PKMONREC("ACTIVEMEM:",P) SRCE=P_SRCE ID=P_P1 IF MULTIOCP=YES THEN START *INCT_(STORESEMA) *JCC_8,<ASEMAGOT> SEMALOOP(STORESEMA,0) ASEMAGOT: FINISH DACT=P_DEST&X'F' ->ACT(DACT) !----------------------------------------------------------------------- ACT(0): ! INITIALISE IF MULTIOCP=YES START ; *TDEC_(STORESEMA); FINISH REALAD=NEW EPAGE LIM=MAXAMTAK-1 PST(AMTASEG)=X'4110038080000001'!LIM<<42!REALAD IF MULTIOCP=YES THEN PST(AMTASEG)=PST(AMTASEG)!NONSLAVED ! ! SET UP PUBLIC SEGMENT 'AMTASEG' FOR AMTA RECORD ARRAY WITH ! PAGE TABLE FOR IT AT BEGINNING OF FIRST EPAGE OF ITSELF ! AMTAPT==ARRAY((REALAD+SEG64)!PUBSEG,PTF) APPENDAMTA(EPAGESIZE<<10-MAXAMTAK<<2,REALAD) REALAD=NEW EPAGE LIM=MAXAMTDDK-1 ! ! PUBLIC SEGMENT 'AMTDDSEG' FOR AMTDD ARRAY WITH ! PAGE TABLE FOR IT AT BEGINNING OF FIRST EPAGE OF ITSELF ! PST(AMTDDSEG)=X'4110038080000001'!LIM<<42!REALAD IF MULTIOCP=YES THEN PST(AMTDDSEG)=PST(AMTDDSEG)!NONSLAVED AMTDDPT==ARRAY((REALAD+SEG64)!PUBSEG,PTF) APPENDAMTDD(EPAGESIZE<<10-MAXAMTDDK<<2,REALAD) IF SFCFITTED=YES 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_LEN<LEN THEN AMTX=0 AND ->RETURN;! 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 IF AMT_USERS=0 AND AMT_OUTS>0 START CYCLE I=AMT_DDP,1,AMT_DDP+LEN-1 IF AMTDD(I)&NEWEPBIT#0 THEN AMTX=-4 AND ->RETURN REPEAT FINISH AMT_USERS=AMT_USERS+1; ! USERS ->RETURN FINISH AMTX=AMT_LINK REPEAT IF AMTASL=0 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 AMTDDNEXT<MAXAMTDDK START REALAD=NEW EPAGE IF REALAD>0 THEN APPENDAMTDD(EPAGESIZE<<10,REALAD) FINISH REPEAT SETAMT: ! PUSHDOWN NEW AMT CELL AMTX=AMTASL AMT==AMTA(AMTX) AMTASL=AMT_LINK AMT_DA=DA AMT_DDP=DDX AMT_USERS=1 AMT_LEN=LEN AMT_OUTS=0 AMT_LINK=AMTHASH(HASH) AMTHASH(HASH)=AMTX CYCLE I=DDX,1,DDX+LEN-1 AMTDD(I)=MASK>>31<<15!STXMASK REPEAT RETURN: P_P1=ID P_P2=AMTX IF MULTIOCP=YES START ; *TDEC_(STORESEMA); FINISH IF SRCE>0 THEN P_DEST=SRCE AND P_SRCE=X'80001' AND PON(P) RETURN !----------------------------------------------------------------------- ACT(2): ! RETURN AMTX IN P_P2 ! P_P3=0 FILE KEPT #0 DESTROY BEGIN INTEGERARRAY CLEARS(0:MAXBLOCK) AMTX=P_P2 AMT==AMTA(AMTX) IF AMT_DA=X'FF000000' OR AMT_DA=0 THEN OPMESS("RETURNED AMT??") CN=0; ! NO CLEARS AS YET IF P_P3=0 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 CLEARS(CN)=AMTX<<16!(I-AMT_DDP) CN=CN+1 AMT_OUTS=AMT_OUTS+1 FINISH REPEAT FINISH AMT_USERS=AMT_USERS-1 ! ! NOW IF THERE WERE ANY CLEARS SET THEM OFF. THIS IS DONE LATER ! SO THAT THE STORE SEMA CAN BE FREE ON DUALS. IMPORTANT AS IT MAY ! BE NECESSARY TO EXTEND THE PARM ASL IF VERY LARGE NO OF CLEARS ! ARE REQUIRED ! P_P6=CN; ! SO L-C CAN ACCOUNT FOR CLEARS IF CN>0 START DCLEARS=DCLEARS+CN IF MULTIOCP=YES START ; *TDEC_(STORESEMA); FINISH Q_DEST=X'40004'; ! ZERO PAGE Q_SRCE=X'80080002' CYCLE I=0,1,CN-1 Q_P1=CLEARS(I) PON(Q); ! PON to limit call depth & so REPEAT ; ! avoid possible LC stack o'flow FINISH END IF CN>0 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 START ; *TDEC_(STORESEMA); FINISH RETURN ; ! AWAIT TRANSFERS FINISH DEALLOCDD(AMT_DDP,AMT_LEN) DEALLOCAMT IF MULTIOCP=YES START ; *TDEC_(STORESEMA); FINISH RETURN !----------------------------------------------------------------------- ACT(4): ! ENTERED EVERY 10 SECS IF MULTIOCP=YES START ; *TDEC_(STORESEMA); FINISH IF SFCFITTED=YES AND DRUMSIZE#0 THEN 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 K<PROC_ACTIVE<=200 START P_DEST=(I+LOCSN3)<<16; ! ASYNCH ACT 0 P_P1=2; ! RELEASE ACTIVE MEMORY PON(P) EXIT FINISH J=J+1 FINISH I=I+1 REPEAT RETURN !----------------------------------------------------------------------- ACT(5): ! CHECK DISC ADDRESS ACTIVE ACT(6): ! TRAP ! VALIDATE BULKMOVE DA=P_P1 *LSS_DA; *IMDV_509; *LSS_TOS ; *AND_511; *ST_HASH AMTX=AMTHASH(HASH) P_DEST=0 WHILE AMTX#0 CYCLE AMT==AMTA(AMTX) IF AMT_DA=DA THEN START IF AMT_OUTS#0 OR (MULTIOCP=YES AND AMT_USERS=0) C THEN P_DEST=1 AND EXIT ! HAVE BEATEN PONNED DEALOCATE ! IN MULTIOCP CASE P_DEST=-1; ! REPORT BACK TO DIRECTOR EXIT FINISH AMTX=AMT_LINK REPEAT IF MULTIOCP=YES START ; *TDEC_(STORESEMA); FINISH ! %IF DACT=6 %AND P_DEST#0 %START; ! TRAP SPRING ! OPMESS("ACTIVE BM--CALL PDS") ! OPMESS("DA=".STRHEX(DA)) ! I=(P_SRCE>>16-LOCSN0)&(MAXPROCS-1) ! OPMESS("USER=".PROCA(I)_USER) ! %FINISH RETURN !----------------------------------------------------------------------- ROUTINE COLLECT DD GARBAGE !*********************************************************************** !* GARBAGE COLLECT AMTDD TO COUNTERACT FRAGMENTATION * !* IN DUALS HALT OTHER OCP OR SEMA WILL TIMEOUT ! * !*********************************************************************** INTEGER I ! CLEAR ALL FREE HOLES TO ZERO IF MULTIOCP=YES AND COM_NOCPS>1 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'3C'#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",""(14), "DAP DRIVER", "DISC","DISC TRANSFERS","DISC INTERRUPT","","MOVE REQUESTS", "MOVE TRANSFERS",""(2), "DRUM TRANSFERS","CSU","DRUM INTERRUPT",""(5),"GPC REQUESTS","TAPE", "OPER","LP ADAPTOR","CR ADAPTOR","CP ADAPTOR","PRINTER", "COMMS CONTROL","COMBINE","FEP ADAPTOR","GPC INTERRUPT", ""(2),"BMREP","COMREP",""(2),"LOCAL CONTROL","FOREGRND USERS", "BACKGRND USERS" INTEGER I,J,K LONGREAL PERIOD, TOTAL, IDLETIME, PROCTIME, SERVTIME STRING (15) S STRING (31)FNSPEC STRPRINT(LONGREAL X,INTEGER A,B) IF MULTIOCP=YES THEN RESERVE LOG IF MONLEVEL&4#0 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) J=PERFORM_SERVN(I) IF S#"" AND J>0 THEN START PRINT STRING(" ".S.STRSP(16-LENGTH(S)).STRPRINT(J,9,0)) SERVTIME=COM_ITINT*PERFORM_SERVIT(I) PRINT STRING(STRPRINT(SERVTIME/1000000,6,3). C STRPRINT((SERVTIME/1000)/J,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)/J,8,0)." ") TOTAL=TOTAL+SERVTIME 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&32#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&32#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 DAP FITTED=YES THEN START ROUTINE DAP DRIVER(RECORD (PARMF)NAME P) !*********************************************************************** !* THIS ROUTINE(SERVICE 31 X1F) HANDLES THE DAP * !* ACT=0 INITIALISE * !* ACT=1 ALLOCATE (SOME OF) THE DAP * !* ACT=2 DEALLOCTE (SOME OF) THE DAP * !* ACT=3 DAP INTERRUPT * !* ACT=4 START THE DAP * !* ACT=5 STOP THE DAP * !* ACT=6 CLOSE DOWN THE DAP FOR RECONFIGN * !* ACT=7 CLOCK TICK TO RETURN IDLE DAP TO STORE * !* ACT=8 SET TIMEOUT TO P_P1 * !* ACT=9 FROM LOCAL CNTRLR WHEN PROCESS DIES WITH DAP * !* ACT=10 RETURN PROCESS LIST NOS OF DAP USERS * !*********************************************************************** ROUTINESPEC DREPLY(INTEGER LDAPNO,FAIL) ROUTINESPEC DSTATUS INTEGER I,J,DACT,PROCNO,FAIL,PT0,PT1,LDAPNO,INIT,STEP,FINAL INTEGER STATUS,STATUS2,STATUS3,ADVIOL,IT,IC,ILOG1,ILOG2,DLOG1,DLOG2,DPC RECORD (PROCF)NAME PROC RECORD (CDRF)NAME LDAP RECORD (PARMXF)NAME PCELL INTEGERNAME LINK OWNINTEGER TOUT=180; ! AFTER 3 MINS REVERTS TO STORE OWNINTEGER HWTOUT=60; ! AFTER 60 SECS INT IS CLASSED AS MISSING STRING (5)DAPID CONSTINTEGER MAXDACT=12 CONSTINTEGER SWOP DAP=X'80' SWITCH ACT(0:MAXDACT) OWNINTEGER CLOSING=0,PENDING=0,RESTART BITS=0 DACT=P_DEST&15 LDAPNO=P_DEST>>8&15 IF 1<=LDAPNO<=MAXLDAP THEN LDAP==COM_CDR(LDAPNO) IF 1<<DACT&B'100011111101'#0 AND (LDAPNO<=0 OR LDAPNO>MAXLDAP) C THEN ->REQERR IF MONLEVEL&2#0 AND C KMON>>31&1#0 THEN PKMONREC("DAP DRIVER:",P) PROCNO=(P_SRCE>>16-LOCSN0)&(MAXPROCS-1) PROC==PROCA(PROCNO) IF 0<=DACT<=MAXDACT THEN ->ACT(DACT) REQERR: ! ERROR IN REQUEST OPMESS("INVALID DAP REQUEST") PKMONREC("DAP ERR:",P) DSTATUS RETURN ACT(0): ! INITIALISE(NO PARAMS) *LSS_(3); *USH_-26 *AND_3; *ST_I IF I#COM_OCP PORT 0 THEN DPON(P,1) AND RETURN CLOSING=CLOSING&(¬(1<<LDAPNO)) LDAP_DAPUSER=0 LDAP_DAPSTATE=1 J=LDAP_DAP1+3 *LB_J; *LSS_(0+B ); *AND_15; ! INTERUPTING PORT *ST_J LDAP_IPDAPNO=LDAP_IPDAPNO&15!J<<4 J=X'80000000'>>J; ! INT PORT MASK BIT IF BASIC PTYPE<=3 START ; ! DAP ON 2970 *LSS_(X'600A') *SLSS_J; *NEQ_-1; *AND_TOS *ST_(X'600A') FINISH ELSE START ; ! DAP ON P4 *LSS_(X'4012') *OR_J *ST_(X'4012') FINISH J=LDAP_DAP1+5 *LB_J; *LSS_10; *ST_(0+B ); ! DIAG ALLOW AND STOP DAP *ADB_X'EA'; *LSS_2; *ST_(0+B ); ! CLEAR FAILS AND GEN RES DSTATUS IF PENDING=0 ->DSCHED ACT(1): ! ALLOCATE P_P1 BLOCKS OF DAP ! ! REPLIES ARE P_P1=1 NO DAP AVAILABLE ! P_P1=2 NOT ENOUGH CONTIGUOUS BLOCKS ! P_P1=3 DAP IS CLOSING DOWN ! P_P1=4 USER ALREADY HAS DAP ! P_P1=0 DAP ALLOCATED WHEREUPON: ! P_P2=LDAP<<16!PHYSICAL DAP NO ! P_P3=FIRST BLOCK ALLOCATED ! P_P4=NO OF BLOCKS ALLOCATED ! INIT=1; STEP=1; FINAL=MAXLDAP IF 2<=COM_CDR(1)_DAPSTATE<=3 THEN START STEP=-1; INIT=MAXLDAP; FINAL=1 FINISH CYCLE LDAPNO=INIT,STEP,FINAL; ! TRY FROM ALL DAPS ! TESTING BUSY ONES LAST LDAP==COM_CDR(LDAPNO) FAIL=0 IF LDAP_IPDAPNO=0 OR LDAP_DAPSTATE=0 THEN FAIL=1 IF P_P1<=0 OR P_P1>LDAP_DAPBLKS THEN FAIL=2 IF CLOSING&1<<LDAPNO#0 THEN FAIL=3 EXIT IF FAIL=0 REPEAT IF FAIL#0 THEN DREPLY(0,FAIL) AND RETURN FOR I=1,1,MAXLDAP CYCLE IF COM_CDR(I)_DAPUSER=PROCNO THEN DREPLY(I,4) AND RETURN REPEAT IF LDAP_DAPSTATE=17 THEN DPON(P,2) AND RETURN ! MUST WAIT IF DAP RECONFIGURING P_P4=PROCNO; ! REMEMBER FOR DACT10 STRING(ADDR(P_P5))=PROC_USER; ! REMEMBER OWNER I=NEWPPCELL PCELL==PARM(I) PCELL<-P LINK==PENDING LINK==PARM(LINK)_LINK WHILE LINK#0;! TO LAST LINK IN CHAIN OF PENDING TRANSFERS PCELL_LINK=0 LINK=I IF LDAP_DAPSTATE>15 START ; ! DAP AS STORE GET IT BACK P_DEST=X'110001' P_SRCE=X'1F0001' P_P1=4<<16!LDAP_IPDAPNO&15 PON(P) RETURN FINISH DSCHED: ! TRY TO SCHEDULE ALL DAPS FOR LDAPNO=1,1,MAXLDAP CYCLE LDAP==COM_CDR(LDAPNO) CONTINUE UNLESS LDAP_DAPSTATE=1;! DAP AVAILABLE TO BE SCHEDULED LINK==PENDING WHILE LINK>0 CYCLE ; ! DAP JOBS ON QUEUE I=LINK P<-PARM(I) IF P_P1>LDAP_DAPBLKS THEN LINK==PARM(I)_LINK AND CONTINUE PROCNO=(P_SRCE>>16-LOCSN0)&(MAXPROCS-1) PROC==PROCA(PROCNO) LINK=PARM(I)_LINK RETURN PP CELL(I) IF PROC_USER#STRING(ADDR(P_P5)) THEN CONTINUE ;! CLAIMER HAS GONE AWAY LDAP_DAPSTATE=2 EXIT REPEAT IF LDAP_DAPSTATE=2 START ; ! DAP SCHEDULED UPDISP(PROCNO,10,TOSTRING((LDAP_IPDAPNO>>4)*2+52));!< OR > PROC_STATUS=PROC_STATUS!2****10 LDAP_DAPUSER=PROCNO P_P4=P_P1 P_P2=LDAP_IPDAPNO&15!LDAPNO<<16 P_P3=0 DREPLY(LDAPNO,0) FINISH IF LDAP_DAPSTATE=1 START ; ! DAP IS IDLE P_DEST=X'000A0002' P_P1=X'1F0007'!LDAPNO<<8 P_P2=TOUT P_SRCE=X'1F0001' PON(P); ! TIMEOUT BACK TO STORE FINISH REPEAT ; ! FOR ALL DAPS RETURN ACT(2): ! DEALLOCATE P_P3 BLKS OF DAP UNLESS P_P1&X'FFFF'=LDAP_IPDAPNO&15 AND LDAP_DAPUSER=PROCNO C THEN DREPLY(LDAPNO,1) AND RETURN DREPLY(LDAPNO,0) RESET: ! ENTER AFTER PROC FAILS(ACT10) UPDISP(PROCNO,10," ") LDAP_DAPUSER=0 LDAP_DAPSTATE=1 PROC_STATUS=PROC_STATUS&(¬(2****10)) J=LDAP_DAP1+X'EF'; ! gen res DAP in case *LB_J; *LSS_2; *ST_(0+B ); ! ended in disorder IF CLOSING&(1<<LDAPNO)#0 START ; ! DAP IS NOW FREE P_DEST=X'110000' P_SRCE=X'1F0002'!LDAPNO<<8 P_P1=4<<16!LDAP_IPDAPNO&15; ! CONFIGURE OFF THIS DAP PON(P) CLOSING=CLOSING&(¬(1<<LDAPNO)) RETURN FINISH ->DSCHED ACT(11): ! FORM ELAPSED INT: INT LONG OVERDUE IF LDAP_DAPSTATE=3 START ; ! DAP IS RUNNING DAPID="DAP".TOSTRING(LDAP_IPDAPNO>>4+48) OPMESS(DAPID." TIMES OUT".TOSTRING(17)) P_DEST=LDAP_DAPINT P_SRCE=X'1F000B' PON(P) LDAP_DAPINT=0 LDAP_DAPSTATE=2 J=LDAP_DAP1+5 *LB_J; *LSS_10; *ST_(0+B ); ! STOP DAP AND DIAG ALLOW *ADB_X'EA'; *LSS_2; *ST_(0+B );! AND GEN RES IT FINISH ELSE OPMESS("SPURIOUS DAP TIMEOUT") RETURN ACT(3): ! DAP INTERRUPT ! P_P3 HAS INT STAT IF LDAP_DAPSTATE=3 START ; ! DAP IS RUNNING IF CLOSING&(1<<LDAPNO)=0 AND P_P3=X'22' START ! JUST ROUTINE TIMESLICE ! RESTART AT ONCE J=LDAP_DAP1+X'3B'; ! IT REG *LSS_X'FFFFF'; *LB_J; *ST_(0+B );! RESET IT *SBB_X'36'; *LSS_0; *ST_(0+B );! AND RESTART IT ->SET TOUT FINISH J=LDAP_DAP1+9 *LB_J; *LSS_(0+B ); *ST_STATUS *ADB_2; *LSS_(0+B ); *ST_ADVIOL *ADB_X'2E'; *LSS_(0+B ); *ST_IC *ADB_2; *LSS_(0+B ); *ST_IT *ADB_2; *LSS_(0+B ); *ST_DPC *ADB_2; *LSS_(0+B ); *ST_DLOG1 *ADB_2; *LSS_(0+B ); *ST_DLOG2 *ADB_2; *LSS_(0+B ); *ST_ILOG1 *ADB_2; *LSS_(0+B ); *ST_ILOG2 *ADB_8; *LSS_(0+B ); *ST_STATUS3 *ADB_2; *LSS_(0+B ); *ST_STATUS2 IF P_P3&8#0 START ; ! HARDWARE DAPID="DAP".TOSTRING(LDAP_IPDAPNO>>4+48)." " OPMESS(DAPID."H-W ERROR".TOSTRING(17)) PRINTSTRING(DAPID."H-W FAILURE INSTAT=".STRHEX(P_P3)) PRINTSTRING(" STATUS 1&2&3=".STRHEX(STATUS)." ".STRHEX(STATUS2)." ".STRHEX(STATUS3)) FOR I=0,1,3 CYCLE J=LDAP_DAP1+X'50'+4*I *LB_J; *LSS_(0+B ); *ST_PT0 *ADB_1; *LSS_(0+B ); *ST_PT1 PRINTSTRING(" PTYP"); WRITE(I,1) PRINTSTRING(" ".STRHEX(PT0).STRHEX(PT1)) REPEAT NEWLINE FINISH IF ILOG1=X'F7F00000' AND 1<<LDAPNO&RESTART BITS#0 START ! STOP IS FOR I-O SYNC BUT DIR HAS TOLD ! US VIA ACT12 THAT I-O HAS COMPLETED RESTART BITS=RESTART BITS&(¬(1<<LDAPNO)) J=LDAP_DAP1+5 *LB_J; *LSS_0; *ST_(0+B ) ->SET TOUT FINISH P_DEST=LDAP_DAPINT; P_SRCE=X'1F0003' LDAP_DAPINT=0 P_P1=P_P3<<24!ADVIOL&X'00FFFF00'!STATUS IF PENDING#0 THEN P_P1=P_P1!SWOP DAP P_P2=DPC P_P3=DLOG1<<15!DLOG2&X'7FFF'; P_P4=IC P_P5=ILOG1 P_P6=ILOG2 PON(P) IF MONLEVEL&2#0 AND KMON>>31&1#0 THEN C PKMONREC("DAP INT :",P) LDAP_DAPSTATE=2 P_DEST=X'A0001' P_SRCE=X'1F0003' P_P1=X'1F000B'!LDAPNO<<8 P_P2=-1; ! CANCELL ELAPSED INT REQUEST PON(P); ! REMOVE TIMEOUT ON INT FINISH ELSE START OPMESS("SURPRISE DAP INTERRUPT") PKMONREC("SPUR DAPINT:",P) FINISH RETURN ACT(4): ! START THE DAP ! P_P1=DATUM,P_P2=LIMIT ! P_P3=COB(ASE),P_P4=COL(IMIT) ! P_P5=DAPPC,P_P6=DAPIC DREPLY(LDAPNO,1) AND RETURN UNLESS C PROCNO=LDAP_DAPUSER AND LDAP_DAPSTATE=2 DREPLY(LDAPNO,2) AND RETURN IF CLOSING&(1<<LDAPNO)#0 LDAP_DAPINT=P_SRCE LDAP_DAPSTATE=3; ! DAP IS RUNNING J=LDAP_DAP1+X'31'; ! TO IS DATUM *LB_J; *LCT_P+4; ! CTB TO RECORD P *LSS_(CTB +2); *ST_(0+B ); ! DATUM=P_P1 *ADB_2; *LSS_(CTB +4); *ST_(0+B );! COB=P_P3 *ADB_2; *LSS_(CTB +5); *ST_(0+B );! COL=P_P4 *ADB_2; *LSS_(CTB +3); *ST_(0+B );! LIMIT=P_P2 *ADB_2; *LSS_(CTB +7); *ST_(0+B );! DAPIC=P_P6 *ADB_2; *LSS_X'FFFFF' *ST_(0+B ); ! DAPIT=X'FFFFF' *ADB_2; *LSS_(CTB +6); *ST_(0+B );! DAPPC=P_P5 *SBB_X'38'; *LSS_0; *ST_(0+B ); ! START IT RUNNING SET TOUT: ! TIME OUT MISSING INTS P_DEST=X'A0002' P_SRCE=X'1F0004' P_P1=X'1F000B'!LDAPNO<<8 P_P2=HWTOUT P_P3=-1 PON(P); ! SET TIMEOUT ON INT RETURN ACT(5): ! (CONDITIONALLY) ABORT THE DAP IF LDAP_DAPSTATE=3 AND PROCNO=LDAP_DAPUSER START ;! EXECUTING FOR THIS USER I=LDAP_DAP1+5 *LB_I; *LSS_2; *ST_(0+B ); ! ORDERLY STOP RETURN ; ! UNTIL INT FROM STOPPING FINISH ! ! DAP GOING FOR SOMEONE ELSE. CHECK PENDING QUEUE ! LINK==PENDING WHILE LINK>0 CYCLE PCELL==PARM(LINK) IF PROCNO=(PCELL_SRCE>>16-LOCSN0)&(MAXPROCS-1) START ;! FOUND RIGHT USER PCELL_DEST=PCELL_SRCE PCELL_SRCE=X'1F0005' PCELL_P1=-1 J=LINK; LINK=PCELL_LINK FASTPON(J) RETURN FINISH LINK==PCELL_LINK REPEAT RETURN ; ! ALREADY STOPPED ACT(6): ! CLOSE THE DAP CLOSING=CLOSING!1<<LDAPNO RETURN ACT(7): ! TIMEOUT IF SMAC RCONFIG#0 THEN DPON(P,5) AND RETURN IF LDAP_DAPSTATE=1 AND COM_SEPGS<30*COM_USERS START ;! STILL IDLE ! AND SHORT OF REAL STORE P_DEST=X'110000' P_P1=4<<16!LDAP_IPDAPNO&15 LDAP_DAPSTATE=17; ! ON WAY BACK TO STORE PON(P) FINISH ->DSCHED; ! SET FURTHER TIMEOUT IN CASE ! NO OF USERS INCREASES ACT(8): ! SET TIMEOUT HWTOUT=P_P2 IF P_P2>10 TOUT=P_P1 IF P_P1>1 RETURN ACT(9): ! PROCESS DIES WITH DAP ! ALLOW RESET BY HAIRY PON FOR LDAPNO=1,1,MAXLDAP CYCLE LDAP==COM_CDR(LDAPNO) IF PROCNO=LDAP_DAPUSER THEN ->RESET REPEAT RETURN ACT(10): ! RETURN CURRENT DAP USER LIST FAIL=0 FOR I=1,1,MAXLDAP CYCLE LDAP==COM_CDR(I) IF LDAP_DAPUSER>0 THEN BYTEINTEGER(ADDR(P_P2)+FAIL)= C LDAP_DAPUSER AND FAIL=FAIL+1 REPEAT LINK==PENDING WHILE LINK>0 CYCLE PCELL==PARM(LINK) BYTEINTEGER(ADDR(P_P2)+FAIL)=PCELL_P4 FAIL=FAIL+1 LINK==PCELL_LINK REPEAT DREPLY(0,FAIL) RETURN ACT(12): ! FROM DIR ASYNCH IO COMPLETE IF LDAP_DAPSTATE=3 THEN RESTART BITS=RESTART BITS!(1<<LDAPNO) RETURN ROUTINE DREPLY(INTEGER LDAPNO,FAIL) !************************************************************************ !* REPLIES TO THE CURRENT REQUEST AS FROM LOGIGAL DAP "LDAPNO" * !************************************************************************ IF P_SRCE>0 START ; ! IF REPLY WANTED P_P1=FAIL P_P6=PROC_STATUS *LSS_(3); *ST_I P_P5=I P_DEST=P_SRCE P_SRCE=X'1F0000'!DACT!LDAPNO<<8 PON(P) IF MONLEVEL&2#0 AND C KMON>>31&1#0 THEN PKMONREC("DAP REPLY :",P) FINISH END ROUTINE DSTATUS INTEGER I STRING (40)S FOR I=1,1,MAXLDAP CYCLE LDAP==COM_CDR(I) S="LDAP".STRINT(I) IF LDAP_IPDAPNO=0 THEN S=S." NONE" ELSE C S=S." DAC".STRINT(LDAP_IPDAPNO&15)." BLKS ".STRINT(LDAP_DAPBLKS).C " USER".STRINT(LDAP_DAPUSER)." STATE".STRINT(LDAP_DAPSTATE) OPMESS(S) REPEAT END 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 IF SSERIES=YES START IF REMOTE PORT=COM_OCPPORT1 THEN REMOTE PORT=COM_OCP1 SCU PORT C ELSE REMOTE PORT=COM_OCP0 SCU PORT ISAD=X'40000000'!REMOTE PORT<<22 FINISH ELSE ISAD=X'42000000'!REMOTE PORT<<20 IF SSERIES=YES OR 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 * !* DEV=4 FOR DAP * !* OTHER DACTS DESCRIBED IN COMMENTS * !*********************************************************************** IF RECONFIGURE=YES OR DAP FITTED=YES THEN START INTEGERFNSPEC SMAC PORT(INTEGER OPEN,PORT) INTEGERFNSPEC MAPDAP SWITCH DACT(0:7),CIN,COFF(1:4) INTEGER DEV,IDENT,I,J,K,MYPORT,HISPORT,STACK,ACT,TOPST,BLKSIZE, C CONFIG,BLKS,REALAD,LDAPNO LONGINTEGER PSTE RECORD (STOREF)NAME ST RECORD (CDRF)NAME LDAP OWNINTEGER PAGESONOFF,OCPGOING=-1,TRIES=0 STRING (9)DEVNAME,ONOFF CONSTSTRING (5)ARRAY DEVS(1:4)="OCP ","SAC ","SMAC ","DAP "; IF MONLEVEL&2#0 AND KMON&1<<17#0 THEN C PKMONREC("CONFIG CONTROL",P) DEV=P_P1>>16 IDENT=P_P1&X'FFFF' IF 1<=DEV<=4 THEN DEVNAME=DEVS(DEV) ELSE DEVNAME="??? " AND ->FAIL IF DEV=3 OR DEV=4 THEN TOPST=(((PST(STORESEG)>>32&X'3FF80'+128) C -ADDR(STORE(0))&X'3FFFF')//STOREFSIZE)-1 *LSS_(3); *USH_-26 *AND_3; *ST_MYPORT HISPORT=MYPORT!!1 ACT=P_DEST&15 IF DEV=4 AND MAPDAP=0 THEN ->FAIL;! DOES MAPPING OF LDAP ->DACT(ACT) DACT(0): ! CONFIGURE OFF ->COFF(DEV) DACT(1): ! CONFIGURE ON ->CIN(DEV) COFF(1): ! CONFIGURE OFF OCP IF MULTI OCP=YES START ->FAIL UNLESS COM_NOCPS=2 AND ((SSERIES=YES AND 0<=IDENT<=1) OR C (SSERIES=NO AND 2<=IDENT<=3)) IF MYPORT #IDENT START ; ! CAN ONLY CONFIGURE OFF MYSELF P_P6=P_DEST; P_DEST=X'3F0001' PON(P); ! TRY AGAIN IN 1 SEC RETURN FINISH ! OCPGOING=MYPORT J=X'8000017C'+MY PORT<<18 I=INTEGER(J); INTEGER(J)=0; ! PROC I WAS RUNNING IF I#0 START I=I+LOCSN0 SERVA(I)_P=SERVA(I)_P&X'BFFFFFFF';! CLEAR EXECUTING BIT UNINHIBIT(I) P_DEST=I<<16!2; PON(P); ! SEND HIM A CONTINUE FINISH IF SSERIES=YES START IF MYPORT=COM_OCPPORT0 START HALT OTHER OCP DCU1 RECOVERY(0); ! DCU1s to other OCP RESTART OTHER OCP(0) I=COM_OCP1 SCU PORT J=I FINISH ELSE I=COM_OCP0 SCU PORT AND J=I I=X'4004601D'!I<<22 J=J<<22 *LB_I; *LSS_J; *ST_(0+B ); ! send mpint to other OCP & ! reset cross reporting FINISH ELSE IF BASIC PTYPE<=3 START I=X'42056011'!HISPORT<<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 FINISH ELSE ->FAIL CIN(1): ! CONFIGURE IN AN OCP IF MULTI OCP=YES START ->FAIL UNLESS COM_NOCPS=1 AND IDENT#COM_OCPPORT0 AND C ((SSERIES=YES AND 0<=IDENT<=1) OR (SSERIES=NO AND 2<=IDENT<=3)) ->FAIL IF SSERIES=NO AND SMAC PORT(0,IDENT)#0; ! open relevant port ! ! MARK COMMS,GLA,BASE STACK&STORE ARRAY SEGS AS NONSLAVED. THESE ARE ! SET SLAVED BY CHOPSUPE UNLESS 2 OCPS ARE PRESENT AL IPL ! PST(4)=PST(4)!NONSLAVED PST(9)=PST(9)!NONSLAVED PST(STORESEG)=PST(STORESEG)!NONSLAVED PST(48)=PST(48)!NONSLAVED IF SSERIES=YES THEN STACK=2*IDENT+12 ELSE STACK=2*IDENT+8 IF SSERIES=NO AND BASIC PTYPE<=3 START *LSS_(X'600A'); *AND_X'CC'; *ST_(X'600A');! ALLOW ACTIVATES FINISH COM_OCPPORT1=IDENT COM_NOCPS=2 IF REMOTE ACTIVATE(IDENT,X'80000000'+(STACK+1)<<18)#0 START COM_NOCPS=1 IF SSERIES=NO THEN J=SMACPORT(1,HISPORT) ->FAIL FINISH IF SSERIES=NO START IF BASIC PTYPE<=3 START *LSS_1; *ST_(X'6009') 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 FINISH ->SUCC FINISH ELSE ->FAIL IF SSERIES=NO START COFF(2): ! CONFIGURE OFF A SAC ->FAIL UNLESS COM_NSACS=2 AND 0<=IDENT<=1 IF BASIC PTYPE=4=COM_OCPTYPE AND COM_CLKX>>20&15=IDENT START ! PROBLEMS WITH CLOCK IN SAC IF COM_NOCPS>1 THEN OPMESS("STILL DUAL OCPS") AND ->FAIL K=IDENT!!1; ! REMAINING SAC I=(IDENT-K)<<20 J=COM_CLKX; *LB_J *LSS_(0+B ); *SBB_I *ST_(0+B ); ! TRANSFER CLOCK REG TO OTHER SAC *STB_J; COM_CLKX=J; ! AND UPDATE ADDRESS J=COM_CLKY; *LB_J *LSS_(0+B ); *SBB_I *ST_(0+B ); ! TRANSFER CLOCK REG TO OTHER SAC *STB_J; COM_CLKY=J; ! AND UPDATE ADDRESS J=COM_CLKZ; *LB_J *LSS_(0+B ); *SBB_I *ST_(0+B ); ! TRANSFER CLOCK REG TO OTHER SAC *STB_J; COM_CLKZ=J; ! AND UPDATE ADDRESS J=X'80000000'>>K; ! EXTERNAL INT BIT *LSS_(X'4012'); *AND_X'0FFFFFFF' *OR_J; *ST_(X'4012') *LSS_(X'4013'); *AND_X'000FFFFF' *SLSS_K; *USH_20; *OR_TOS *ST_(X'4013'); ! FOR RRTC INSTRUCTION FINISH P_DEST=X'200007' P_SRCE=X'110005' P_P2=IDENT PON(P) RETURN DACT(5): ! REPLY FROM DISC ->SAC USED IF P_P2#0 P_DEST=X'300007' P_SRCE=X'110003' P_P2=IDENT PON(P) RETURN DACT(3): ! REPLY FROM GPC ->SAC USED UNLESS P_P2=0 IF SFC FITTED=YES AND DRUMSIZE>0 START P_DEST=X'280007' P_SRCE=X'110006' P_P2=IDENT PON(P) RETURN FINISH DACT(6): ! REPLY FROM DRUM(ALWAYS OK) IF COM_NOCPS>1 AND MYPORT#COM_OCPPORT0 THEN 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 SAC MASK=SAC MASK&(¬(1<<IDENT)) ACT=0; ! ENSURE RIGHT MESSAGE ->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 SAC MASK=SAC MASK!(1<<IDENT) COM_NSACS=2 ->SUCC CIN(4): ! CONFIGURE IN A DAP IF DAP FITTED=YES START ->FAIL UNLESS (IDENT=LDAP_IPDAPNO&15 AND LDAP_DAPSTATE&15=0 ) OR C LDAP_IPDAPNO=0 IF SMAC RCONFIG#0 START IF SMAC RCONFIG=IDENT THEN ->FAIL;! THIS ONE AGAIN DPON(P,5); ! WAIT 5 SECS & RETRY RETURN FINISH IF MYPORT#COM_OCPPORT0 THEN DPON(P,1) AND RETURN K=COM_SDR4!IDENT<<COM_SMACPOS ->FAIL UNLESS SAFE IS READ(K,CONFIG)=0 ->FAIL UNLESS CONFIG&X'02000000'#0 FINISH COFF(3): ! CONFIGURE OFF A SMAC ->FAIL UNLESS 0<IDENT<=15; ! SMAC 0 NOT CONFIGURABLE ->FAIL UNLESS 1<<IDENT&COM_SMACS#0;! UNLESS SMAC IN CONFIGRNT IF DAP FITTED=YES AND DEV=3 START ; ! CHECK FOR SMAC THAT IS ACTIVE DAP FOR I=1,1,MAXLDAP CYCLE LDAP==COM_CDR(I) ->FAIL IF LDAP_IPDAPNO&15=IDENT AND LDAP_DAPSTATE>0 REPEAT FINISH ->FAIL IF (COM_OCPTYPE=4 OR COM_OCPTYPE=6) AND C 1<<(IDENT!!8)&COM_SMACS#0; ! & not interleavable ! full check very difficult! ->FAIL UNLESS X'10000'<<IDENT&COM_SMACS=0;! BUT NOT USED BY SYSTEM IF SMAC RCONFIG#0 START ; ! ALREADY RECONFIGURING IF SMAC RCONFIG=IDENT AND TRIES>150 THEN C SMAC RPAGES=0 AND RETURN ;! 2ND REQUEST=FORCE IT OFF ->FAIL FINISH ->FAIL UNLESS SAFE IS READ(COM_SDR4!IDENT<<COM_SMACPOS,J)=0 ! CHECK CAN ACCESS SMAC IS PAGESONOFF=0; J=0; ! WORK OUT NO OF PAGES TRIES=0; ! COUNT IF ATTEMPTS TO CONFIGURE IF MULTI OCP=YES THEN SEMALOOP(STORESEMA,1) 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 AND ST_USERS=0 THEN J=J+1 ! forget abandoned flawed pages ! REMEMBER 8K PHOTO AREA IN SMAC1 IF IDENT=1 AND ST_USERS=255 AND ST_REALAD&X'3FFFFF' C <X'7FFF' THEN ST_USERS=0 AND J=J+1 IF ST_USERS=255 THEN ->FAIL;! SHOULD NOT OCCUR FINISH REPEAT SMAC RCONFIG=IDENT SMAC RPAGES=PAGES ONOFF-J IF MULTIOCP=YES START ; *TDEC_(STORESEMA); FINISH ; ! cannot hold thru 2 loops ! ! GRAB ANY FREE PAGES FROM FREE LIST AT ONCE ! IF MULTI OCP=YES THEN SEMALOOP(STORESEMA,1) SMAC RPAGES=SMAC RPAGES-1 WHILE QUICK EPAGE(1,1<<IDENT)>0 IF MULTI OCP=YES START ; *TDEC_(STORESEMA); FINISH P_DEST=X'3000D' P_SRCE=X'110004' PON(P); ! KICK SCHEDULE TO FREE STORE P_DEST=X'110004' P_P2=0 DPON(P,5); ! KICK SELF(P_P1 INTACT!) RETURN DACT(4): ! CONTINUE CONFIGURING OFF STORE IF P_P2=0 THEN DONT SCHED=1; ! AFTER STOPPING SNOOZING ! NOW KEEP EVERYONE OUT P_P2=P_P2+1 TRIES=P_P2; ! COUNT OF ATTEMPTS IF SMAC RPAGES#0 START P_P3=SMAC RPAGES; ! DEBUGGING ONLY DPON(P,1) RETURN UNLESS MPLEVEL=0 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 TABLES ! CYCLE I=1,1,TOPST ST==STORE(I) IF ST_REALAD>>22&15=SMAC RCONFIGTHEN ST=0 REPEAT ! ! CLOSEUP BLOCK ARRAY AND RESET COUNT ! COM_SEPGS=COM_SEPGS-PAGES ONOFF MAXP4PAGES=P4PERCENT*COM_SEPGS//100 J=0 CYCLE I=0,1,COM_SBLKS-1 K=BLOCKAD(I) IF K>>22&15#SMAC RCONFIG THEN BLOCKAD(J)=K AND J=J+1 REPEAT BLKS=COM_SBLKS-J; ! DAP SIE COM_SBLKS=J ->DAPIN IF DAP FITTED=YES AND DEV=4; ! DAP IN NOT SMAC OFF J=64+16*SMAC RCONFIG PST(I)=0 FOR I=J,1,J+15 ! ! FINISH OFF INCLUDING CLOSING SAC PORT UNLESS INTERLEAVED ! COM_SMACS=COM_SMACS!!1<<SMAC RCONFIG J=SMAC RCONFIG!!8; ! INTERLEAVED SMAC IF COM_SMACS&1<<J=0 START ; ! IS NOT PRESENT K=COM_SDR4!SMAC RCONFIG<<COM_SMACPOS J=SAFE IS READ(K,I) J=J!SAFE IS WRITE(K,I!X'3C') FINISH IF DAP FITTED=YES START FOR I=1,1,MAXLDAP CYCLE LDAP==COM_CDR(I) IF SMAC RCONFIG=LDAP_IPDAPNO&15 THEN LDAP_IPDAPNO=0;! DAP REMOVED REPEAT FINISH SMAC RCONFIG=0 ->SUCC COFF(4): ! CONFIGURE OFF A DAP IF DAP FITTED=YES START ->FAIL UNLESS IDENT=LDAP_IPDAPNO&15 AND LDAP_DAPSTATE>0 ->FAIL IF SMAC RCONFIG#0 IF 1<LDAP_DAPSTATE<16 START ; ! DAP STILL IN USE P_SRCE=P_DEST P_DEST=X'1F0006'!LDAPNO<<8; ! TELL DAPDRIVER AND WAIT PON(P); ! P_P1 INTACT RETURN FINISH IF MYPORT#COM_OCPPORT0 THEN DPON(P,1) AND RETURN IF LDAP_DAPSTATE=16 THEN LDAP_DAPSTATE=0 AND ->SUCC LDAP_DAPSTATE=LDAP_DAPSTATE&16;! NO LONGER A DAP J=X'80000000'>>(LDAP_IPDAPNO>>4) ! ! NOW ACTIVE DAPS PRESENT. CLOSE OFF INTERRUPTS ! IF BASIC PTYPE<=3 START ; ! DAP ON 2970 *LSS_(X'600A') *OR_J *ST_(X'600A') FINISH ELSE START ; ! DAP ON P4 ARCHITECTURE *LSS_(X'4012') *SLSS_J; *NEQ_-1; *AND_TOS *ST_(X'4012') FINISH ! AND DROP THRO TO ADD AS STORE FINISH CIN(3): ! CONFIGURE IN A SMAC ->FAIL UNLESS DEV=4 OR COM_SMACS&1<<IDENT=0;! NOT ALREADY IN K=COM_SDR4!IDENT<<COM_SMACPOS J=SAFE IS READ(K,CONFIG)!SAFE IS READ(COM_SDR4,I) J=J!SAFE IS WRITE(K,CONFIG&X'FFFFFFC3'!I&X'3C') ->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' IF MULTI OCP=YES THEN SEMALOOP(STORESEMA,1) CYCLE I=COM_SBLKS,1,COM_SBLKS+BLKS-1 REALAD=BLOCKAD(I) IF DEV=3 START ; ! DPAS HAVE PST SET J=X'20000'; ! HALF A SEGMENT IF REALAD&X'20000'#0 THEN J=X'40000' PST(64+REALAD>>18)=PSTE!(REALAD&X'FFFC0000') ! C LENGTHENI(J-X'80')<<32 FINISH ! clear store to remove parities *LDTB_X'38002000'; *LDA_REALAD; *INCA_VIRTAD; *LB_0; *LSQ_0 AGN: *ST_(DR +B ); *CPIB_X'1FFF'; *JCC_4,<AGN> CYCLE J=0,1,SEGEPSIZE//2-1 K=K+1 WHILE STORE(K)_REALAD#0 STORE(K)_REALAD=REALAD+EPAGESIZE*1024*J IF IDENT=1 AND J<=1 AND REALAD&X'3FFFFF'=0 THEN C STORE(K)_USERS=255 ELSE START ! DONT USE PHOTO ATEA IN SMAC 1 P_P2=K; ! STORE INDEX RETURN EPAGE(P) FINISH REPEAT REPEAT ! CHANGE SCHEDULING PARAMS ! FOR REALLOCATED STORE J=PAGES ONOFF*OVERALLOC PERCENT//100 UNALLOCEPS=UNALLOCEPS+PAGESONOFF+J OVERALLOC=OVERALLOC+J MAX OVERALLOC=MAXOVERALLOC+J COM_SEPGS=COM_SEPGS+PAGESONOFF MAXP4PAGES=P4PERCENT*COM_SEPGS//100 COM_SBLKS=COM_SBLKS+BLKS COM_SMACS=COM_SMACS!1<<IDENT IF MULTI OCP=YES START ; *TDEC_(STORESEMA); FINISH ACT=DEV&1; ! TO GET RIGHT MESSAGE AS DAP OFF ! IN FACT ALSO MEANS SMAC ON ->SUCC IF DAP FITTED=YES START DAPIN: ! DAP STORE MUST BE CONTIGUOUS ! OR DAP CAN ONLY BE USED AS SMAC CYCLE I=1,1,COM_SBLKS-1 ->FAIL UNLESS BLOCKAD(I)=BLOCKAD(I-1)+X'20000' OR C BLOCKAD(I)>>22#IDENT OR IDENT#BLOCKAD(I-1)>>22 REPEAT LDAP_IPDAPNO=IDENT LDAP_DAP1=(COM_SDR4!(LDAP_IPDAPNO&15)<<COM_SMACPOS)&X'FFFFF000'!X'B00' LDAP_DAPBLKS=BLKS SMAC RCONFIG=0 P_DEST=X'1F0000'!LDAPNO<<8 P_SRCE=0 PON(P); ! INITIALISE DAP DRIVER ACT=1 ->SUCC FINISH FINISH DACT(2): ! FINISH CONFIGURIN OFF HIM IF MULTI OCP=YES START IF OCPGOING<0 THEN DEVNAME=DEVNAME.TOSTRING(17) OCPGOING=-1; ! IF DUE TO FAILURE FLASH MSG IF SSERIES=YES AND MYPORT#COM_OCPPORT0 START ; ! swap SCU ports J=COM_OCP0 SCU PORT COM_OCP0 SCU PORT=COM_OCP1 SCU PORT COM_OCP1 SCU PORT=J FINISH COM_NOCPS=1; COM_OCPPORT0=MYPORT COM_OCPPORT1=HISPORT IF SSERIES=NO THEN J=SMACPORT(1,HISPORT); ! CLOSE OFF HIS SMAC PORT FINISH SUCC: IF ACT&1#0 THEN ONOFF="ON" ELSE C IF DEV=4 THEN ONOFF="AS STORE" ELSE ONOFF="OFF" OPMESS(DEVNAME.STRINT(IDENT)." CONFIGURED ".ONOFF) if dev=1 start ; ! update oper info if act&1=0 then onoff=" ".strint(com_ocpport0)." " else c onoff="s ".strint(com_ocpport0)." ".strint(com_ocpport1) p_dest=x'320006'; ! display text with pon p_p1=x'04100000'; ! lest race with oper init string(addr(p_p1)+3)=onoff pon(p) { == display text(0,4,16,onoff) } finish RETURN CIN(*):COFF(*):DACT(*): FAIL: ! UNKNOWN DEVICE OR OTHERS OPMESS("CANNOT CONFIGURE ".DEVNAME.STRINT(IDENT)) RETURN INTEGERFN MAPDAP !*********************************************************************** !* FINDS THE LOGICAL DAP NO CORRESPONDING TO THE DAC(SMAC) NO * !*********************************************************************** IF DAP FITTED=YES START FOR LDAPNO=1,1,MAXLDAP CYCLE LDAP==COM_CDR(LDAPNO) IF LDAP_IPDAPNO&15=IDENT THEN RESULT =LDAPNO REPEAT IF ACT=1 OR ACT=4 START ; ! CONFGR ON EMPTY SLOT OK FOR LDAPNO=1,1,MAXLDAP CYCLE LDAP==COM_CDR(LDAPNO) IF LDAP_IPDAPNO=0 THEN RESULT =LDAPNO REPEAT FINISH FINISH RESULT =0 END INTEGERFN SMAC PORT(INTEGER OPEN,PORT) !*********************************************************************** !* OPEN (OPEN=0) %OR CLOSE A SMAC PORT IN ALL ONLINE SMACS * !*********************************************************************** INTEGER I,J,K,L,P,VAL,RES,DAPS K=X'20'>>PORT P=K L=K!!(-1) IF OPEN=0 THEN K=0 RES=0; DAPS=0 IF DAP FITTED=YES START FOR I=1,1,MAXLDAP CYCLE IF COM_CDR(I)_IPDAPNO>0 THEN DAPS=DAPS!1<<COM_CDR(I)_IPDAPNO&15 REPEAT FINISH CYCLE I=0,1,15 IF 1<<I&COM_SMACS#0 OR 1<<I&DAPS#0 START J=COM_SDR4!I<<COM_SMACPOS; ! SAMC CONFG REG RES=RES!SAFE IS READ(J,VAL) ! for SMACs 0/8 if the block0 bit is not set (because some ! other block is configured as block0) then writing back ! the config reg will lose block0 with disastrous results!! ! So...... IF (I=0 OR ((COM_OCPTYPE=4 OR COM_OCPTYPE=6) AND I=8)) C AND VAL&COM_BLOCKZBIT=0 START IF (OPEN=0 AND VAL&P#0) OR (OPEN=1 AND VAL&P=0) START IF OPEN=0 THEN ONOFF="Open " ELSE ONOFF="Close " OPMESS(ONOFF."Port ".STRINT(PORT)." now!!!") RES=-1 IF OPEN=0 FINISH FINISH ELSE RES=RES!SAFE IS WRITE(J,VAL&L!K) FINISH REPEAT RESULT =RES END FINISH END ROUTINE SHUTDOWN(RECORD (PARMF)NAME P) !*********************************************************************** !* KERNEL service 18 - complete system shutdown. * !* * !* ACT 1 - when system quiescent then :- * !* halt other OCP (if appropriate) * !* inhibit interrupts * !* master clear all controllers * !* * !* ACT 2 - as activity 1 plus:- * !* disconnect all DFC & GPC devices * !* * !* ACT 0 - cancel request * !* * !*********************************************************************** RECORD (PARMF) PP INTEGER I,J OWNINTEGER ACT=0 IF MONLEVEL&2#0 AND KMON&1<<18#0 THEN C PKMONREC("Shutdown:",P) I=P_DEST&255 UNLESS I=255 THEN ACT=I; ! 255 is reply from ELAPSED INT. RETURN IF ACT=0 UNLESS COM_USERS=0 START PP_DEST=X'A0002'; ! Elapsed int PP_SRCE=0 PP_P1=P_DEST!255 PP_P2=20 PON(PP) RETURN FINISH IF MULTI OCP=YES AND COM_NOCPS>1 THEN HALT OTHER OCP *LSS_X'382E'; *ST_(3); ! No unwanted interrupts IF SSERIES=NO START FOR I=0,1,31 CYCLE ; ! Master clear all controllers J=BYTEINTEGER(COM_CONTYPEA+I); ! controller type UNLESS J=0 START IF COM_NSACS=1 AND I>>4#COM_SACPORT0 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 GDC(PP) FINISH J=X'40000800'!I<<16 *LB_J; *LSS_2; *ST_(0+B ) FINISH REPEAT FINISH CYCLE *IDLE_X'DEAF'; ! Go to sleep REPEAT END !* !* !* ROUTINE UPDISP(INTEGER PROCESS,OFFSET,STRING (13) S) INTEGER LINE,POS PROCESS=PROCESS-1 LINE=PROCESS//3; ! 3 PER LINE +HEADER POS=(PROCESS-3*LINE)*13; ! 40CHARS FOR EACH 3 PROCS DISPLAY TEXT(-1,LINE+5,POS+OFFSET,S);! CURRENTLY 5 HEADER LINES END !----------------------------------------------------------------------- ! THE LOCAL CONTROLLER STACK HAS SEVERAL OTHER SEGMENTS MAPPED ONTO ITS ! FIRST PART. IT IS IMPORTANT THAT THESE SEGMENTS ARE ACCESSED VIA ! THEIR PROPER ADDRESSES AND NOT VIA ADDRESSES IN THE LOCAL CONTROLLER ! STACK AS THE SLAVES ARE NOT PROOF AGAINST 2 VIRTUAL ADDRESSES ! HAVING THE SAME REAL ADDRESS ! THIS AREA IS CURRENTLY LAID OUT AS FOLLOWS:- ! 0 TO X600 THE LOCAL SEGMENT TABLE 192 8BYTE ENTRIES ! X600 TO X680 THE LOCAL CONTROLLER SSN+1 ! X680 TO X700 SEGMENT 5 IE USER STACK SSN+1 ! X700 TO X780 SEGMENT 7 IE SIGNAL STACK SSN+1 ! X780 TO X800 RESERVED FOR SSN+1 OF CURRENTLY NOMINATED USER STACK ! X800 X1180 THE DIRERTOR-LOCALCONTROLLER COMMUNICATION SEGMENT(10) !----------------------------------------------------------------------- ROUTINE LOCAL CONTROL ! DIRECTOR COMMUNICATIONS RECORDS RECORDFORMAT SIGOUTPF(INTEGER DEST,SRCE,P1,P2,P3,P4,P5,P6, 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 SMULTIPLE CON=X'20'; ! SYSTEM SHRD COMPONENT CONSTINTEGER ADVISORY SEQ=X'40'; ! ADVISORY SEQUENTIAL ACCESS BIT CONSTINTEGER CONTINUATN BLK=X'80'; ! CBT BLOCK IS NOT THE FIRST LONGINTEGERARRAY AS(0:MAXAS) BYTEINTEGERARRAY ASEG(0:MAXAS) INTEGER ASFREE,ASWAP,ASWIP,ASSHR; ! %BITARRAY (0:MAXAS) INTEGERARRAY OLDASWIPS(0:MAXRESIDENCES) CONSTLONGINTEGER LTOPBIT=X'8000000000000000' CONSTINTEGER TOPBIT=X'80000000' !----------------------------------------------------------------------- ! LOCAL STACKS INFORMATION BYTEINTEGERARRAY LSTKSSN(1:LSTKN) !----------------------------------------------------------------------- ! CATEGORY INFORMATION INTEGER EPLIM,EPN,UEPN,RTLIM,RTN !----------------------------------------------------------------------- CONSTINTEGER SMALL SEQUENTIAL=8; !USED TO DECIDE TO RECAP OR NOT INTEGERFNSPEC CHECK RES(INTEGER WRITE,LEN,AD) INTEGERFNSPEC CHECKDA(INTEGER DA) ROUTINESPEC PAGEOUT(INTEGER VSSEG,VSEPAGE,RECORD (CBTF)NAME CBT) ROUTINESPEC ASOUT(INTEGER ASP) ROUTINESPEC STROBE(INTEGER SFLAGS) ROUTINESPEC WORKSET(INTEGER RECAP) ROUTINESPEC CLEAR ACCESSED BITS ROUTINESPEC DEACTIVATE(INTEGER MASK) ROUTINESPEC FREE AS ROUTINESPEC RETURN PTS INTEGERFNSPEC FIND PROCESS INTEGERFNSPEC CURSSN ROUTINESPEC WAIT(INTEGER DACT,N) !----------------------------------------------------------------------- RECORD (PARMF) P; ! FOR POFFING PARAMETERS RECORD (PROCF)NAME PROC RECORD (PARMF)NAME ALLOUTP; ! MAPPED ONTO DIROUTP OR ! SIGOUTP AS STACKS SWOP RECORD (SERVF)NAME SERV0,SERV,SERV3 RECORD (PARMF) POUT RECORD (SSNP1F)NAME SSNP1 RECORD (STOREF)NAME ST CONSTLONGINTEGERARRAYNAME LST=LSTVAD INTEGERARRAYNAME PT INTEGER PROCESS,ME,LSN3,PTAD,VSPARM,PEPARM,VSSEG,VSEPAGE,EPX,I,J,K, C NEWSTK,STOREX,DEST,SRCE,SUSP,SNOOZES,DA,LASTDA,NONSEQVSIS,LCERRS, 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(-4:0) CONSTINTEGER MAXDIROUT=28 CONSTLONGINTEGER DGLAEPAGES=4; ! EPAGES OF DIRECTOR GLA SPACE CONSTLONGINTEGER LONGONE=1; ! FOR COMPILE TIME COMPUTATIONS SWITCH DIROUT(0:MAXDIROUT) CONSTINTEGER MAXOUTACR=DIRACR; ! UP TO DIRECTOR LEVEL CONSTBYTEINTEGERARRAY PAGEOUT DELAY(0:10)=1,2,4,8,15(7) ! TOTAL PAGEOUT DELAY>120 SECS ! TO ALLOW TIME TO AUTOLOAD DFC ! !----------------------------------------------------------------------- ! PROCESS CREATE ENTRY ONLY *LSS_(LNB +0) *ST_PROCESS; ! FIND PROCESS NO PASSED BY FRIG PROCESS=INTEGER(PROCESS&X'FFFFFFFC') *LSS_OLDLNB *ST_(LNB +0); ! TO ENABLE %MONITOR TO FIND ! GLOBAL VARIABLES PROC==PROCA(PROCESS) ME=(PROCESS+LOCSN0)<<16 LSN3=PROCESS+LOCSN3 SERV0==SERVA(PROCESS+LOCSN0) SERV3==SERVA(LSN3) ! ***** SEMAPHORE?******** SUPPOFF(SERV0,P); ! OBTAIN STARTUP RECORD ! ! INITIALIZE LOCAL STACKS INFO ! LSTKSSN(1)=4; ! DIRECTOR/USER STACK SEGMENT LST(5)=LST(1)+X'80'+(DIRACR-LCACR)<<56;! AND SSN+1 LSTKSSN(2)=6; ! SIGNAL STACK LST(7)=LST(5)+X'80'; ! AND SIGNAL SSN+1 CYCLE I=3,1,LSTKN LSTKSSN(I)=0 REPEAT LST(DIRCSEG)=LST(0)&X'FFFC0000FFFFFFFF'+8+(DIRACR-LCACR)<<56+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 ASSHR=0 ASWIP=0 PEPARM=-1 PROCACTAD1=X'28000004' PROCACTAD2=ADDR(PROC_ACTW0); ! %INTEGERNAME DESCRIPTOR SUSP=0 ASDESTROY=0 ! FILL IN SCTI(3)[ALIGNED] INTEGER(SCTI0+24)=X'38000004' INTEGER(SCTI0+28)=SCTJ30 ! AND J-VECTOR FOR SCTI(3) LONG INTEGER(SCTJ30)=0 LONG INTEGER(SCTJ30+8)=0 ! REQUEST INPUT AS J=1 ENTRY LONG INTEGER(SCTJ30+16)=X'80F0000000140001' LONG INTEGER(SCTJ30+24)=RTDR(REQUEST INPUT);! YIELDS DESCR-DESCR ! REQUEST OUTPUT AS J=2 ENTRY LONG INTEGER(SCTJ30+32)=X'80F0000000140001' LONG INTEGER(SCTJ30+40)=RTDR(REQUEST OUTPUT); ! YIELDS DESCR-DESCR ! CHANGE CONTEXT AS J=3 ENTRY LONG INTEGER(SCTJ30+48)=X'80F0000000140001' LONG INTEGER(SCTJ30+56)=RTDR(CHANGE CONTEXT) !----------------------------------------------------------------------- ! CONNECT DIRECTOR FILES ! CODE AS SEG2 USING TOP 2 CBTS ! GLA AS SEG3 USING CBT0 ! STACK AS SEG4 USING CBT1 SST(2)=CBTLEN-2; SST(3)=0; SST(4)=1 LST(2)=X'5003FFFF00000000'!DIRACR<<52;! EXECUTE &READ CBTA(CBTLEN-2)_DA=P_P2 CBTA(CBTLEN-2)_TAGS=MAXBLOCK-1 CBTA(CBTLEN-2)_LINK=SMULTIPLE CON;! SYSTEM SHARING OF DIRECTOR CBTA(CBTLEN-1)_DA=P_P2+MAXBLOCK CBTA(CBTLEN-1)_TAGS=MAXBLOCK-1 CBTA(CBTLEN-1)_LINK=CONTINUATN BLK!SMULTIPLE CON LST(3)=X'400003FF00000000'!DIRACR<<52!DIRACR<<56! 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'01803BAE'; ! ONLY EVENT PENDING,PE,VSE&SYSERR *STSF_I ISTDUM_SF=I ISTDUM_IT=MAXIT ISTDUM_IC=MAXIT ISTDUM_CTB=0 J=X'80000000'!COM_OCPPORT0<<18; ! IST ADDRESS FOR IPL PROC K=J!!X'40000'; ! TOTHER OCP IIST ! SET VS ERROR IST ENTRY *JLK_<VSERRI> ; *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_<ITIMERI> ; *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_<PROGERRI> ; *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_<OUTI> ; *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_<ICOUNTERI> ; *LSS_TOS ; *ST_I ISTDUM_PC=I ISTDUM_IC=0 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_<ENTERI> ; *LSS_TOS ; *ST_I LSSNP1_PC=I LSSNP1_SSR=X'01803BAE' *STSF_I LSSNP1_SF=I LSSNP1_IT=MAXIT LSSNP1_IC=MAXIT LSSNP1_CTB=0 FINISH !----------------------------------------------------------------------- ! SET UP DIRECTOR CONTEXT NEWSTK=LSTKSSN(1)<<18 SSNP1==RECORD(NEWSTK!X'40000') SSNP1=0 SSNP1_LNB=NEWSTK SSNP1_PSR=X'00040001'!DIRACR<<20; ! PROG ERRORS UNMASKED SSNP1_PC=X'00080010'; ! TO M-C CODE DIRLOADER SSNP1_SSR=X'01800000'; ! ALL INTS ALLOWED SSNP1_SF=NEWSTK!X'14'; ! 5 WORDS ON FROM LNB SSNP1_IT=0 SSNP1_IC=MAXIT SSNP1_B=DIROUTPAD SSNP1_DR0=X'B1000000'; ! DESCRIPTOR TO ENTRY DESCRIPTOR SSNP1_DR1=X'000C0000'; ! AT START OF GLA PROC_STACK=NEWSTK; ! DIRECTOR STACK ON INITIAL ENTRY !----------------------------------------------------------------------- ! ! THE FOLLOWING RECORDS ARE SQUEEZED INTO THE SPARE WORDS OF SEGMENT 5 ! IOSTAT : WORDS 18 - 26 ! ICREVS : WORD 27 ! ACNT : WORDS 28 - 30 ! WORD 31 : USED BY DIRECTOR FOR COUNT OF KINSTRNS ! THERE IS NO MORE SPACE LEFT !!!! ! IOSTAT==RECORD(NEWSTK!X'40048') IOSTAT=0 ACNT==RECORD(NEWSTK!X'40070') ACNT=0 ICREVS==INTEGER(NEWSTK!X'4006C') ICREVS=X'12345678' !----------------------------------------------------------------------- ! SET UP SIGNAL CONTEXT NEWSTK=LSTKSSN(2)<<18 SSNP1==RECORD(NEWSTK!X'40000') SSNP1=0 SSNP1_LNB=NEWSTK SSNP1_PSR=X'0004FF01'!DIRACR<<20; ! PROGRAM ERRORS MASKED SSNP1_PC=X'00080010'; ! TO M-C DIRLOADER ENTRY POINT SSNP1_SSR=X'01800800'; ! NO INSTRUCTION COUNTER INTS SSNP1_SF=NEWSTK!X'14' SSNP1_IT=0 SSNP1_IC=MAXIT SSNP1_B=0; ! ZERO FOR SIGNAL ENTRY !!!!! SSNP1_DR0=X'B1000000' SSNP1_DR1=X'000C0000' ! ! THE FOLLOWING WORDS ARE SQUEEZED INTO SPARE WORDS OF SEGMENT 7 ! IE SSN+1 OF THE SIGNAL STACK ! WORD18 = SEMAHELD SET BY DIRECTOR WHEN A SEMAPHORE IS HELD ! SEMAHELD==INTEGER(NEWSTK!(X'40000'+4*18)) !----------------------------------------------------------------------- ! INITIALISATIONS FOR DIRECTOR STRING(DIROUTPAD)=SUPID DIROUTP_SRCE=EPAGESIZE<<16!MAXBLOCK DIROUTP_P1=PROCESS STRING(ADDR(DIROUTP_P2))=PROC_USER BYTEINTEGER(ADDR(DIROUTP_P3)+3)=PROC_INCAR DIROUTP_P4=SIGOUTPAD DIROUTP_P5=SCTI0 DIROUTP_P6=1; ! DACT FOR INT MESSGES FROM FE SIGOUTP_DEST=LSTLEN SIGOUTP_SRCE=SSTAD SIGOUTP_P1=CBTLEN-1; ! HIGHEST CBT ENTRY ! WAS ADDR(CBTASL) SIGOUTP_P2=CBTAD SIGOUTP_P3=ADDR(ACNT) SIGOUTP_P4=ADDR(ICREVS) SIGOUTP_P5=ADDR(IOSTAT) SIGOUTP_P6=ADDR(SEMAHELD) !----------------------------------------------------------------------- ! REPLY TO SCHEDULE POUT=0 POUT_DEST=X'30002'; ! SCHEDULE PROCESS CREATED POUT_SRCE=ME POUT_P1=PROCESS PON(POUT) !----------------------------------------------------------------------- RETURN: ! INTERRUPT BACK TO KERNEL *LSS_X'01803FFF'; ! NO SYSTEM ERROR INTS *ST_(3) LSSNP1P=LSSNP1; ! LOCAL CNTRLR REACTIVATE CONTEXT ! ! TO RETURN TO KERNEL REACTIVATE LOCAL CONTROLLER WITH EP SET ! THIS HORRENDOUS PROCEDURE WORKS SINCE WE ARE CERTAIN THAT:- ! 1) II (INSTRUCTION INCOMPLETE) IS NOT SET IN LC CONTEXTJUST SET ! 2) ALL OTHER INTERUPTS ARE MASKED ! HENCE EFFECT IS OF AN "OUT" TO KERNEL !!! ! WILL WORK OK FOR MULTIPROCESSORS (UNLIKE ACTIVATING BACK) ! *LXN_PROCACTAD2 *LSD_(XNB +0) *OR_X'0000000100000000' *SLSD_0; ! LC STACK ADDRESSS (0) NOT PARAMETERISED *ST_TOS IF MONLEVEL&4#0 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; UEPN=0 PROC_EPN=0 HIGHSEG=2 RETIME: ! START NEW TIMESLICE SSNP1==RECORD(PROC_STACK!X'40000');! PROCESS CONTEXT IF SSNP1_IT&X'FF800000'=0 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'FFFFCFF5'; *ST_(3);! UNMASK PERI&EXTERNAL INT *LXN_PROCACTAD2; ! ADRRESS OF ACTIVATE WORDS *ACT_(XNB +0) !----------------------------------------------------------------------- ACTIVITY(2): ! CONTINUE WITH CORE RESIDENCE PROC_STATUS=PROC_STATUS&(¬2); ! IN CASE CAME FROM ONFRUNQ ACTIVATE: ! CHECK ASYNCH MESSAGE ! **** SEMAPHORE FOR CHECK? IF SERV3_P<<2=0 OR PROC_STACK=LSTKSSN(2)<<18 THEN ->ACT IF SST(LSTKSSN(2))=X'FFFF' THEN ->ACT;! SIGNAL STACK NOT CREATED(STARTUP) ! OR HAS BEEN DESTROYED(CLOSEDOSN) !----------------------------------------------------------------------- ASYNCH: ! ASYNCHRONOUS MESSAGE POFFABLE SUPPOFF(SERV3,P) I=P_DEST&X'FFFF' IF I=0 THEN ->ASYN0(P_P1) IF I=X'FFFF' THEN OPMESS("PROCESS ".STRINT(PROCESS). C " TERMINATED") AND NEWSTK=PROC_STACK AND ->TERMINATE IF I=X'FFFE' THEN START *OUT_99; ! CRASH WITH MASKED OUT INT FINISH IF I=X'FFFD' START *PUT_0; *PUT_0; ! FAIL WITH ILLEGAL INSTRN FINISH UNLESS I=1 THEN ->SIGINT INTMESS<-P_INTMESS IF LENGTH(INTMESS)=1 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 ; *ST_I; ! OLD STACK *LSS_TOS ; ! PARAMETER *ST_VSPARM IF I=0 THEN ->LCPE; ! LC CAN HAVE NO VSIS! IF VSPARM<0 THEN PEPARM=9 AND ->PE;! PUBLIC VSI VSSEG=VSPARM>>18 IF 0<VSSEG<LSTLEN THEN TSTPTR=LST(VSSEG)>>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,<SSEMAGOT> SEMALOOP(STORESEMA,0) SSEMAGOT: FINISH IF FREE EPAGES>0 START STOREX=QUICK EPAGE(0,-1) IF MULTI OCP=YES START ; *TDEC_(STORESEMA); FINISH ->ACT9 FINISH POUT_SRCE=ME!9 POUT_P2=0; ! CLEAR TO ZERO GET EPN=GET EPN+1 IF MULTIOCP=YES START ; *TDEC_(STORESEMA); FINISH IF PAGEFREES<=1 AND GETEPN>=MPLEVEL+1-COM_NOCPS THEN 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 ST_USERS=1 EPN=EPN+1 UEPN=UEPN+1 PROC_EPN=EPN PTEPS=256 OLDPTP: ! ROOM IN OLD PAGETABLE PAGE LST(VSSEG)=LST(VSSEG)!X'0000000080000001'!PTAD IF VSSEG>HIGHSEG THEN HIGHSEG=VSSEG PTEPS=PTEPS-SEGLEN PTAD=PTAD+((SEGLEN*EPAGESIZE+1)//2)<<3;! 8 BYTE BOUNDARY ! ! RUN ON INTO A VSCAUSE(4) !----------------------------------------------------------------------- VSCAUSE(4): ! PAGE NOT AVAILABLE IF EPN>=EPLIM THEN ->NOPAGES CBTP=SST(VSSEG)+VSEPAGE//MAXBLOCK EPX=VSEPAGE&(MAXBLOCK-1) CBT==CBTA(CBTP) IF CBT_TAGS&X'20'=0 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 IF CBT_LINK&SMULTIPLE CON#0 THEN ASSHR=ASSHR!ASB ASFREE=ASFREE&(¬ASB); ! REMOVE BIT FINISH POUT_DEST=X'80001'; ! GET AMTX POUT_SRCE=0 POUT_P1=PROCESS POUT_P2=CBT_DA POUT_P3=(CBT_TAGS&X'80')<<24!CBT_TAGS ! NEWBIT<<31 ! LENGTH ! %IF CBT_TAGS&X'80'#0 %AND LST(VSSEG)>>56&15=0 %THEN %START ! OPMESS(PROC_USER."CONNECT MODE?? CALL PDS") ! OPMESS("DA=".STRHEX(CBT_DA)) ! %FINISH IF MONLEVEL&12=12 THEN START *LSS_(6); *ST_IC; *LSS_(5); *ST_IT FINISH ACTIVE MEM(POUT) IF MONLEVEL&12=12 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&12=12 THEN START *LSS_(6); *ST_IC; *LSS_(5); *ST_IT FINISH PAGETURN(POUT) IF MONLEVEL&12=12 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 THEN PTE=X'80000001'!POUT_P2 AND ->ACT10 IF CBT_LINK&ADVISORY SEQ#0 OR C (VSSEG#PROC_STACK>>18 AND AS(TSTPTR)<<VSEPAGE=0 AND C AS(TSTPTR)>>(64-VSEPAGE)&3=3) THEN C PAGEOUT(VSSEG,VSEPAGE-2,CBT) ELSE NONSEQVSIS=NONSEQVSIS+1 PROC_STATUS=PROC_STATUS!2; ! DEMAND PAGE PRIORITY ->RETURN !----------------------------------------------------------------------- ACTIVITY(10): ! EPAGE HERE ! P_P1=RUBBISH IDENT ! P_P2=STORE(EPAGE)_REALAD ! VSSEG,VSEPAGE&TSTPTR INTACT !! EPH: PROC_STATUS=PROC_STATUS&X'FFFFFFFD' PTE=X'80000001'!P_P2 ACT10: ! ENTERS HERE IF PAGE NOT TRANFRD ASP=TSTPTR AS(ASP)=AS(ASP)!LTOPBIT>>VSEPAGE ASB=TOPBIT>>ASP ASWAP=ASWAP!ASB ASWIP=ASWIP&(¬ASB) EPN=EPN+1 IF CBT_LINK&SMULTIPLE CON=0 THEN UEPN=UEPN+1 PROC_EPN=EPN ACNT_PTURNS=ACNT_PTURNS+1 ! ! PT==ARRAY(VIRTAD+LST(VSSEG)&X'0FFFFFF8'+VSEPAGE*EPAGESIZE<<2,PTF) ! %CYCLE I=0,1,EPAGESIZE-1 ! PT(I)=PTE+I<<10 ! %REPEAT ! THIS HAND CODE ASSUMES EPAGESIZE=4 I=VIRTAD+LST(VSSEG)&X'0FFFFFF8'+VSEPAGE*16 *LXN_I *LSS_PTE; *ST_(XNB +0) *IAD_1024; *ST_(XNB +1) *IAD_1024; *ST_(XNB +2) *IAD_1024; *ST_(XNB +3) ->ACTIVATE !-------------------------------------------- ACTIVITY(11): ! PAGE READ FAILURE IF P_P3<0 THEN ->DEAD POUT_DEST=LSN3<<16 POUT_P1=1 POUT_P2=VSSEG<<18!VSEPAGE*EPAGESIZE<<10 PON(POUT) ->EPH !----------------------------------------------------------------------- ! DEADLOCK RECOVERY DEAD: WORKSET(0); ! DEPART TO FREE STORE POUT_DEST=X'3000E' POUT_P1=PROCESS PON(POUT) ->RETURN !----------------------------------------------------------------------- AMTXSW(0): ! CHANGE BLOCK SIZE IN SITU ? AMTXSW(-4): ! clears still in progress WAIT(2,1); ! TRY AGAIN IN 1 SEC ->RETURN AMTXSW(-1): ! NO AMT CELLS AVAILABLE AMTXSW(-2): ! NOT ENOUGH GARBAGE DEACTIVATE(¬ASFREE) ->ACTIVATE AMTXSW(-3): ! CHANGE BLOCK SIZE WHEN STILL IN USE PEPARM=19 ->PE !----------------------------------------------------------------------- ITIMERI:*JLK_TOS ! INTERVAL TIMER INTERRUPTS ENTER HERE *LSS_TOS ; *LSS_TOS ! ! IF A SEMA HELD GIVE A SMALL AMOUNT MORE TIME WITHOUT LETTING NEXT ! PERSON ON RUNQ GET THE CPU AS HE MIGHT ALSO WANT THE SEMA ! IF SEMAHELD#0 START SEMAHELD=0 SSNP1==RECORD(PROC_STACK!X'40000') SSNP1_IT=TIMESLICE>>3; ! EIGHTH OF TIME SLICE IF MONLEVEL&4#0 THEN LPIT=LPIT+TIMESLICE>>3 ACNT_LTIME=ACNT_LTIME+COM_ITINT*(TIMESLICE>>3) ->ACT FINISH RTN=RTN+1 IF RTN=1 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 AND MONVAD>0 THEN C GARNER(7,2<<24!PROC_CATEGORY<<16!EPN) IF MONLEVEL&12=12 THEN START *LSS_(6); *ST_IC; *LSS_(5); *ST_IT FINISH SCHEDULE(POUT) IF MONLEVEL&12=12 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 PROCESS>1 AND (RUNQ1#0 OR (PREEMPTED!RUNQ2#0 AND PROC_RUNQ=2)) START POUT_DEST=ME!2 ->ONBRUNQA FINISH ->ACTIVATE; ! START NEXT TSLICE AT ONCE !----------------------------------------------------------------------- ONFRUNQ: ! PUT ON FRONT OF RUNQ POUT_DEST=ME!2 ONFRUNQA: PROC_STATUS=PROC_STATUS!2; ! SET PRIORITY BIT ONBRUNQA: ! TO THE BACK OF RUNQ PON(POUT) ->RETURN !----------------------------------------------------------------------- NOPAGES: ! NO EPAGES FOR PAGEFLT IF MONLEVEL&4#0 AND MONVAD>0 THEN C GARNER(7,3<<24!PROC_CATEGORY<<16!EPN) IF EPLIM<MAXEPAGES THEN START POUT_DEST=X'3000A'; ! MORE EPAGES ON THE FLY ? POUT_SRCE=0 POUT_P1=PROCESS POUT_P2=RTN POUT_P5=EPN POUT_P6=PROC_CATEGORY IF MONLEVEL&12=12 THEN START *LSS_(6); *ST_IC; *LSS_(5); *ST_IT FINISH SCHEDULE(POUT) IF MONLEVEL&12=12 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 EPN<EPLIM THEN ->ACTIVATE;! GOT SOME BACK ! FINISH WORKSET(1) POUT_DEST=X'30003'; ! OUT OF EPAGES POUT_SRCE=ME!1 POUT_P1=PROCESS POUT_P2=RTN; ! TIMESLICES USED SO FAR IF EPLIM>=MAXEPAGES AND RTN=0 AND PROCESS>=FIRST UPROC THEN C DPON(POUT,COM_USERS//10) ELSE PON(POUT) ->RETURN !----------------------------------------------------------------------- ACTIVITY(7): ! MORE ALLOCATION AVAILABLE !----------------------------------------------------------------------- PROGERRI:*JLK_TOS ! PROGRAM ERROR INTERRUPTS ENTER HERE *LSS_TOS *ST_I; ! CHECK OLD STACK FOR L-C STACK *LSS_TOS *ST_PEPARM ! ! SOME P4 TAKES PHOTO ON PROGERRORS SO CLEAR INHIBIT PHOTOT BIT OR WE ! MAY LOSE THE PHOTO ON SUBSEQUENT M-C FAILURE ! IF BASICPTYPE=4 START *LSS_(X'4012'); *AND_X'FEFFFFFF'; *ST_(X'4012') FINISH LCPE: ! L-C HAS PE OR ILLEAGL VSI IF I=0 START ; ! I IS OLD STACK NO *ASF_16; ! preserve stack top for diags OPMESS("LOCAL CNTRLR FAILS".STRHEX(PEPARM)) *LSS_(3); *USH_-26; *AND_3; *ST_J OPMESS("OCP".TOSTRING(J+48)." STK ".STRHEX(I)) DUMPTABLE(0,LST(1)&X'0FFFFF80'+X'81000000',72);! REGS DUMPTABLE(1,INTEGER(X'660')&X'0FFFFF80'+X'81000000',4096) ! PAGE 1 OF LCSTACK PEPARM=22; ! PASS TO DIRECTOR LCERRS=LCERRS+1 IF LCERRS>3 THEN ->RETURN FINISH PE: ! SOFTWARE DETECTED ERRORS JOIN ! 16 = ILLEGAL SYSTEM CALL ! 17 = EXCESS INTRUCTIONS ! 18 = DISC READ FAILS ! 19 = CHANGE BLOCK SIZE ! 20 = H-W ERROR (OCP OR STORE) ! 21 = ILLEGAL OUT ! 22 = LOCAL CONTROLLER FAILS SIGOUTP_P1=PEPARM SIGOUTP_P2=PROC_STACK SIGOUTP_TYPE=2 SIGOUTP_SSN=CURSSN SIGOUTP_SSNAD=PROC_STACK SIGOUTP_SUSP=0 NEWSTK=LSTKSSN(2)<<18 IF PROC_STACK=NEWSTK 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<<OUTN&X'1819C54B'=0 C THEN -> ILLEGAL OUT ! ALLOWS OUT 0,1,3,6,8,10,14,15 ! 16,19,20,27,28 FROM SIGNAL STACK ->DIROUT(OUTN) IF INTEGER(J!X'40004')>>20&X'F'<=MAXOUTACR FINISH ILLEGAL OUT: ! GIVE PROGRAM ERROR OUT ACR CHK PEPARM=21!OUTN<<8 ->PE FREACT: ! REACTIVATE AFTER INVALID OUT ! NB OUT19 USES SIGOUTP! ALLOUTP_DEST=-1 ->ACTIVATE REACT: ! REACTIVATE AFTER VALID OUT ALLOUTP_DEST=0 ->ACTIVATE !----------------------------------------------------------------------- TERMINATE: ! STOP THE PROCESS(EMERGENCY!) J=NEWSTK>>18+1; ! SSN+1 NUMBER J=LST(J)&X'0FFFFF80'; ! ITS REAL ADDRESS PRINTSTRING(PROC_USER." FAILING SSN+1") DUMP TABLE(0,X'81000000'+J,72) ! NEXT 2 LINES ARE TO HELP TONY PRINTSTRING("SEGMENT 5") DUMPTABLE(1,X'81000000'+LST(5)&X'0FFFFF80',72) ! CREATE STOPPING MSGE TO DIRECT ALLOUTP_P1=PROCESS ALLOUTP_P2=PROC_INCAR STRING(ADDR(ALLOUTP_P3))=PROC_USER ASDESTROY=0; ! PRESERVE EVERYTHING DOUT0: ! NORMAL STOPS JOIN HERE DEACTIVATE(¬ASFREE) ASDESTROY=0 IF SEMAHELD#0 THEN 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) IF DAP FITTED=YES AND PROC_STATUS&2****10#0 START ;! STILL HAS DAP POUT_DEST=X'1F0009' POUT_SRCE=ME PON(POUT) FINISH POUT_DEST=X'30008'; ! SCHEDULE/DESTROY POUT_SRCE=ME POUT_P1=PROCESS PON(POUT) ->RETURN !----------------------------------------------------------------------- DIROUT(0): ! DIRECTOR STOPS PROCESS(NORMAL) ASDESTROY=1; ->DOUT0; ! DESTROY ALL (REMAINING) FILES DIROUT(1): ! PRINT STRING FOR DIRECTOR IF ALLOUTP_DEST>>24>31 THEN ->FREACT PRINT STRING(STRING(ADDR(ALLOUTP_DEST))) ->REACT !----------------------------------------------------------------------- DIROUT(2): ! INPUT REQUEST MESSAGE IF ALLOUTP_P3#IOSTAT_IAD THEN ->ACTIVATE;! INPUT ALREADY HERE POUT=ALLOUTP POUT_DEST=X'00370006' POUT_SRCE=LSN3<<16!1 PON(POUT) SRCE=X'80000000'!LSN3; ! TOP BIT SET FOR INPUT WAIT ->SUSPWS !----------------------------------------------------------------------- DIROUT(3): ! DISCONNECT SEGMENT ! ALLOUTP_P1=SEG, P2#0 DESTROY VSSEG=ALLOUTP_P1 ->FREACT UNLESS 0<=VSSEG<LSTLEN AND SST(VSSEG)#X'FFFF' IF ALLOUTP_P2#0 THEN ASDESTROY=1 TSTPTR=LST(VSSEG)>>32&127 DA=CBTA(SST(VSSEG))_DA J=ACNT_PTURNS IF TSTPTR#127 THEN ASOUT(TSTPTR) J=ACNT_PTURNS-J; ! NO OF TRANSFERS STARTED BY DCONNECT ASDESTROY=0 LST(VSSEG)=LST(VSSEG)&X'FFFFFFFF00000000' IF J=0 OR PROCESS<=3 THEN ->REACT POUT_DEST=ME!16 ->ONBRUNQA; ! WILL REENTER AT ACTIVITY(16) ! ! SINCE PROCESSES ARE ARE ALLOWED TO RUN ON AFTER DISCONNECT VERY ! LARGE NUMBERS OF PAGEOUTS AND CLEARS CAN BUILD UP. THIS RUINS RESPONSE ! SO IF THERE ARE A LARGE NUMBER OF CLEARS HOLD THIS PROCESS UNTIL ! PREVIOUS DISCONNECT(WHICH INVOLVED TRANSFERS) HAS COMPLETED ! ACTIVITY(16): ! RE-ENTRY AFTER WAIT FOR CLEARS IF DCLEARS+PAGEFREES>100 AND LASTDA#0 C AND CHECKDA(LASTDA)>0 THEN WAIT(16,1) AND ->RETURN LASTDA=DA ->REACT !----------------------------------------------------------------------- DIROUT(4): ! reactivate for director ->REACT !----------------------------------------------------------------------- DIROUT(5): ! PON FOR DIRECTOR SRCE=PROCESS+LOCSN1 DIRPONS: ! OTHER PONS JOIN HERE DEST=ALLOUTP_DEST>>16 IF DEST=X'FFFF' THEN START ; ! RELAY MESSAGE IF FIND PROCESS=0 THEN ->ACTIVATE;! NOT LOGGED ON FINISH ELSE START J=DEST; IF J=63 THEN J=ALLOUTP_P6>>16 UNLESS 0<=J<LOCSN0 OR LOCSN1<J<=MAXSERV THEN ->FREACT 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 LOCKST#0 THEN ->ONBRUNQA; ! FOR EDAR AND TAPES ->ONFRUNQA !----------------------------------------------------------------------- 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=UEPN*COM_USERS ->DEPART UNLESS I<COM_SEPGS OR PROCESS<=3 OR C (SFC FITTED=NO AND (PROC_CATEGORY=3 OR LOCKST#0 OR C 8*UEPN<FREEEPAGES-MAXEPAGES)) POUT_DEST=X'30012' POUT_SRCE=SRCE&X'7FFFFFFF' POUT_P1=PROCESS POUT_P2=EPN IF MONLEVEL&12=12 THEN START *LSS_(6); *ST_IC; *LSS_(5); *ST_IT FINISH SCHEDULE(POUT) IF MONLEVEL&12=12 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 ; ! SUSPED ON FLY IF MONLEVEL&4#0 AND MONVAD>0 THEN GARNER(5,EPN) SUSP=SRCE; ->RETURN FINISH FINISH ACTIVITY(8):DEPART: ! suspended but must now go IF MONLEVEL&4#0 AND MONVAD>0 THEN C GARNER(7,1<<24!PROC_CATEGORY<<16!EPN) WORKSET(1) POUT_DEST=X'30005'; ! SUSPEND POUT_SRCE=SRCE&X'7FFFFFFF'; ! TO UNINHIBIT SRCE IN "SCHEDULE" POUT_P1=PROCESS POUT_P2=EPN; ! EPAGES USED SO FAR POUT_P5=EPN POUT_P6=PROC_CATEGORY PON(POUT) SUSP=SRCE IF PROC_STACK=LSTKSSN(2)<<18 THEN PRINT STRING(" SUSPENDED IN SIGNAL STATE") AND NEWSTK=LSTKSSN(2)<<18 AND ->TERMINATE ->RETURN !----------------------------------------------------------------------- DIRPONREPLY: ! REPLY HAS WOKEN PROCESS UP SERV==SERVA(SUSP) DPR: SUPPOFF(SERV,ALLOUTP) SUSP=0 ->ACTIVATE !----------------------------------------------------------------------- DIROUT(6): ! PON & CONTINUE SRCE=PROCESS+LOCSN1 DIRPONC: ! OTHER PONS JOIN HERE DEST=ALLOUTP_DEST>>16 IF DEST=X'FFFF' THEN START IF FIND PROCESS=0 THEN ->ACTIVATE FINISH ELSE START J=DEST; IF J=63 THEN J=ALLOUTP_P6>>16 UNLESS 0<=J<LOCSN0 OR LOCSN1<J<=MAXSERV THEN ->FREACT 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) ->ACTIVATE; ! PDS THINKS THIS WILL BE BETTER ! THAN THE ORIGINAL LINE ->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 0<DEST<=LOCSN0 THEN ->FREACT SRCE=ALLOUTP_SRCE ALLOUTP_SRCE=ME!13 PON(ALLOUTP) J=PROC_RUNQ; PROC_RUNQ=1 IF MULTIOCP=YES THEN START *INCT_SCHEDSEMA *JCC_8,<SSEMAGOT1> SEMALOOP(SCHEDSEMA,0) SSEMAGOT1: FINISH MPLEVEL=MPLEVEL-1; ! DECREASE MPLEVEL&CHECK DEADLOCKS IF PAGEFREES<=2 AND 0<GETEPN>=MPLEVEL-1 THEN C P_DEST=X'20000' AND PON(P) IF MULTIOCP=YES START ; *TDEC_SCHEDSEMA; FINISH ->RETURN; ! WAIT IN STORE FOR REPLY !----------------------------------------------------------------------- ACTIVITY(13): ! REPLY TO PON & WAIT IN STORE IF MULTIOCP=YES THEN START *INCT_SCHEDSEMA *JCC_8,<SSEMAGOT2> SEMALOOP(SCHEDSEMA,0) SSEMAGOT2: FINISH MPLEVEL=MPLEVEL+1 PROC_RUNQ=J IF MULTIOCP=YES START ; *TDEC_SCHEDSEMA; FINISH ALLOUTP=P ALLOUTP_DEST=SRCE IF PROCESS>=FIRST UPROC START I=PROC_STACK+X'40014' INTEGER(I)=(INTEGER(I)-OUT18CHARGE)&X'1FFFFFF' INTEGER(I+4)=(INTEGER(I+4)-OUT18INS)&X'1FFFFFF' FINISH ->ACT !----------------------------------------------------------------------- DIROUT(12): ! NOMINATE STACK SSN I=ALLOUTP_P1; ! STACK NO J=ALLOUTP_P2; ! SSN UNLESS 1<=I<=LSTKN AND LSTKSSN(I)=0 AND 4<=J<LSTLEN AND C J&1=0 AND SST(J!1)=X'FFFF' THEN ->FREACT 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) J=INTEGER(PROC_STACK!X'40020')>>2; ! sub-ident. in old XNB OPMESS(PROC_USER." bad syscall:".STRINT(J)) PEPARM=J<<8!16 ->PE !----------------------------------------------------------------------- DIROUT(16): ! INSTRUCTION COUNTER INTERRUPT ! (AFTER STACK SWITCH) PEPARM=17; ! TREAT AS PROGRAM ERROR ->PE !----------------------------------------------------------------------- DIROUT(17): ! CHECK ACTIVE BLOCKS ON DESTROY J=0 CYCLE I=0,1,7 RECHECK: K=INTEGER(DIROUTPAD+4*I) IF K=0 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 MONVAD=0 AND ->FREACT UNLESS CHECKRES(0,4096,MONVAD)=0 ->FREACT IF LOCKST=0 MONLIM=MONVAD+INTEGER(MONVAD+8) MONPTAD=INTEGER(LOCKST&X'0FFFFFF0'+VIRTAD+8*(MONVAD>>18)+4)C &X'0FFFFFF0'+VIRTAD FOR I=0,1,(INTEGER(MONVAD+8)-1)>>10 CYCLE ->FREACT IF INTEGER(MONPTAD+4*I)&1=0 REPEAT ->REACT FINISH DIROUT(21): ! DISABLE PROCMON DIROUT(22): ! PROCMON ON DIROUT(23): ! PROCMON OFF ->FREACT DIROUT(24): ! SPECIAL FOR REQUEST OUTPUT SRCE=PROCESS+LOCSN2 ->DIRPONS UNLESS ALLOUTP_DEST=X'370007' ALLOUTP_SRCE=X'80000000'!SRCE<<16 IF MONLEVEL&12=12 START *LSS_(6); *ST_IC; *LSS_(5); *ST_IT FINISH COMMS CONTROL(ALLOUTP) IF MONLEVEL&12=12 START *LSS_(6); *ST_ICC; *LSS_(5); *ST_ITT PERFORM_SERVIT(55)=PERFORM_SERVIT(55)+(IT-ITT) LCIT=LCIT-(IT-ITT) PERFORM_SERVIC(55)=PERFORM_SERVIC(55)+(IC-ICC) LCIC=LCIC-(IC-ICC) PERFORM_SERVN(55)=PERFORM_SERVN(55)+1 FINISH ->ACTIVATE DIROUT(25): ! LOCK IO AREA AND RETURN ST ADDR ! P_P5/P_P6=DESCR TO AREA. ALLOUTP_P5=ALLOUTP_P5&X'FFFFFF'; ! P_P1=1 LOCK ,=-1 UNLOCK IF ALLOUTP_P1>0 AND CHECK RES(0,ALLOUTP_P5,ALLOUTP_P6)#0 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,<SSEMAGOT3> SEMALOOP(STORESEMA,0) SSEMAGOT3: FINISH IF FREE EPAGES>0 THEN START STOREX=QUICK EPAGE(0,-1) IF MULTIOCP=YES START ; *TDEC_(STORESEMA); FINISH ->ACTF FINISH POUT_SRCE=ME!X'F' POUT_P2=0; ! CLEAR TO ZERO GET EPN=GET EPN+1 IF MULTIOCP=YES START ; *TDEC_(STORESEMA); FINISH IF PAGEFREES<=1 AND GETEPN>=MPLEVEL+1-COM_NOCPS THEN 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&12=12 THEN START *LSS_(6); *ST_IC; *LSS_(5); *ST_IT FINISH RETURN EPAGE(POUT) IF MONLEVEL&12=12 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&12=12 THEN START *LSS_(6); *ST_IC; *LSS_(5); *ST_IT FINISH PAGETURN(POUT) IF MONLEVEL&12=12 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,<OUT16>; ! JUMP IF B>=0 *OUT_16; ! TO SWITCH STACKS OUT16:*EXIT_-1; ! TO RESTORE PM,CC,ACS ETC. ! SIGNAL MECHANISM INVOKED AT DIROUT(16) !----------------------------------------------------------------------- INTEGERFN CHECKDA(INTEGER DA) !*********************************************************************** !* CHECKS A DISC ADDRESSAND REPLIES AS FOLLOWS * !* RESULT=0 ADDRESS NOT ACTIVE * !* RESULT=1 TRANSFERS OR CLEARS IN PROGRESS * !* RESULT<0 OTHER USERS OF SAME * !*********************************************************************** RECORD (PARMF) POUT POUT_DEST=X'80005' POUT_P1=DA IF MONLEVEL&12=12 THEN START *LSS_(6); *ST_IC; *LSS_(5); *ST_IT FINISH ACTIVE MEM(POUT) IF MONLEVEL&12=12 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 IF CBT_LINK&SMULTIPLE CON#0 THEN I=I!5 CBT==CBTA(SST(VSSEG)+VSEPAGE//MAXBLOCK) P_DEST=X'40002'; ! PAGETURN/PAGE-OUT P_P1=CBT_AMTX<<16!(VSEPAGE&(MAXBLOCK-1)) IF SFC FITTED=YES AND RESIDENCES>MIN RESIDENCES+1 THEN C I=I!4; ! TO DRUM IF THERE IS ONE P_P2=I IF MONLEVEL&4#0 AND MONVAD>0 THEN C GARNER(3+I>>3,VSSEG<<18!VSEPAGE<<12) IF MONLEVEL&12=12 THEN START *LSS_(6); *ST_IC; *LSS_(5); *ST_IT FINISH PAGETURN(P) IF MONLEVEL&12=12 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 IF CBT_LINK&SMULTIPLE CON=0 THEN UEPN=UEPN-1 EPN=EPN-1 IF EPN>0 THEN PROC_EPN=EPN AS(ASP)=AS(ASP)!!(LTOPBIT>>VSEPAGE) IF MONLEVEL&16#0 START I=PROC_CATEGORY SEQOUT(I)=SEQOUT(I)+1 FINISH FINISH END ROUTINE ASOUT(INTEGER ASP) !*********************************************************************** !* DISCARD ONE SEGMENT (INDEXED BY ASP) FROM ACTIVE STORAGE. * !* MAY INVOLVE WRITING PAGES OUT FROM STORE AND WILL INVOLVE * !* RETURNING ANY AMTXS ALLOCATED * !*********************************************************************** RECORD (CBTF)NAME CBT !%INTEGERARRAYNAME PT; ! NOT USED IN HAND CODING INTEGER MARK,VSSEG,VSEPAGE,SH,CBTP,PBLENS,ASB,POFL,I,PTAD,LASTEP LONGINTEGER MASK VSSEG=ASEG(ASP) IF ASDESTROY#0 AND 16<=VSSEG<=31 THEN 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) AS(ASP)=0 PTAD=VIRTAD+LST(VSSEG)&X'0FFFFFF8' ! PT==ARRAY(PTAD,PTF) CBTP=SST(VSSEG) CBT==CBTA(CBTP) PBLENS=MAXBLOCK VSEPAGE=-1 WHILE MASK#0 CYCLE *LSD_MASK ; *SHZ_SH ; *USH_1 ; *ST_MASK VSEPAGE=VSEPAGE+SH+1 IF VSEPAGE>=PBLENS START PBLENS=PBLENS+MAXBLOCK CBTP=CBTP+1 CBT==CBTA(CBTP) FINISH ! PAGE=VSEPAGE*EPAGESIZE ! MARK=0 ! %CYCLE I=PAGE,1,PAGE+EPAGESIZE-1 ! MARK=MARK!PT(I); ! GANG MARKERS TOGETHER ! PT(I)=0; ! MARK PAGE AS UNAVAILABLE ! %REPEAT ! THIS HANDCODING ASSUMES EPAGESIZE=4 ! I=PTAD+4*EPAGESIZE*VSEPAGE *LXN_I *LSS_(XNB +0); *OR_(XNB +1); *OR_(XNB +2); *OR_(XNB +3) *ST_MARK *LSQ_0 *ST_(XNB +0) IF ASDESTROY=0 THEN POFL=MARK<<3>>31<<3 ELSE POFL=0 ! NOTE:- DRUM NOT UPDATED POUT_DEST=X'40002'; ! PAGETURN/PAGE-OUT POUT_P1=CBT_AMTX<<16!(VSEPAGE&(MAXBLOCK-1)) POUT_P2=POFL ! %IF CBT_AMTX=0 %OR CBT_TAGS&X'20'=0 %THEN %C OPMESS("CBT STATE ??") AND CONTINUE ;! SHOULD NOT HAPPEN IF MONLEVEL&4#0 AND MONVAD>0 THEN C GARNER(1+POFL>>3,VSSEG<<18!VSEPAGE<<12) IF MONLEVEL&12=12 THEN START *LSS_(6); *ST_IC; *LSS_(5); *ST_IT FINISH PAGETURN(POUT) IF MONLEVEL&12=12 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 IF CBT_LINK&SMULTIPLE CON=0 THEN UEPN=UEPN-1 REPEAT IF EPN>0 THEN PROC_EPN=EPN NOP: CBTP=SST(VSSEG) CBT==CBTA(CBTP) CYCLE IF CBT_TAGS&X'20'#0 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&12=12 THEN START *LSS_(6); *ST_IC; *LSS_(5); *ST_IT FINISH ACTIVE MEM(POUT) IF MONLEVEL&12=12 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<MAXBLOCK THEN EXIT LASTEP=LASTEP-MAXBLOCK CBTP=CBTP+1 CBT==CBTA(CBTP) REPEAT LST(VSSEG)=LST(VSSEG)!X'7F00000000';! NOW MARKED AS INACTIVE ASEG(ASP)=0; ! FOR DUMP CRACKING ! NOT OTHERWISE NEEDED ASB=TOPBIT>>ASP ASWAP=ASWAP&(¬ASB) ASWIP=ASWIP&(¬ASB) ASSHR=ASSHR&(¬ASB) ! ! IT IS JUST POSSIBLE FOR A SEGMENT TO BE REACTIVATED AND BECOME ! INACTIVE AGAIN IN THE SAME RESIDENCE(EXTENDED ON THE FLY) TO ! PREVENT PREMATURE DISCARDING OF DRUM IN THIS RARE CASE REMOVE BIT ! FROM OLD ASIPS ! OLDASWIPS(0)=OLDASWIPS(0)&(¬ASB) ASFREE=ASFREE!ASB END !----------------------------------------------------------------------- ROUTINE STROBE(INTEGER SFLAGS) !*********************************************************************** !* WHIP THROUGH ALL THE ACTIVE PAGES IN EACH ACTIVE SEGMENT * !* ANY PAGES NOT REFERNECED ARE PAGED OUT. THE REFERENCE BITS ARE * !* CLEARED IN CASE THIS PAGES IS NOT USED FURTHER. * !* A CRITICAL ROUTINE FOR PERFORMANCE HENCE HAND CODING * !* 2**0 OF SFLAGS SET FOR NOT CLEARING PT USE BITS * !* 2**1 OF SFLAGS NOT USED * !*********************************************************************** RECORD (CBTF)NAME CBT !%INTEGERARRAYNAME PT; ! NOT USED IN HANDCODING ! %CONSTINTEGER USEMASK=X'DFFFFFFF' CONSTLONGINTEGER DUSEMASK=X'DFFFFFFFDFFFFFFF' INTEGER MARK,POFL,ASMASK,ASP,VSSEG,VSEPAGE,PTB,CBTP,PBLENS,ASB, 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 AS(ASP)=AS(ASP)&(¬(LTOPBIT>>VSEPAGE)) IF MONLEVEL&16#0 THEN STROUT(CAT)=STROUT(CAT)+1 POUT_DEST=X'40002'; ! PAGETURN/PAGE-OUT POUT_P1=CBT_AMTX<<16!(VSEPAGE&(MAXBLOCK-1)) POUT_P2=POFL IF MONLEVEL&4#0 AND MONVAD>0 THEN C GARNER(3+POFL>>3,VSSEG<<18!VSEPAGE<<12) IF MONLEVEL&12=12 THEN START *LSS_(6); *ST_IC; *LSS_(5); *ST_IT FINISH PAGETURN(POUT) IF MONLEVEL&12=12 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 IF CBT_LINK&SMULTIPLE CON=0 THEN UEPN=UEPN-1 FINISH REPEAT IF AS(ASP)=0 THEN START ASB=TOPBIT>>ASP ASWAP=ASWAP&(¬ASB) ASWIP=ASWIP!ASB FINISH REPEAT IF EPN>0 THEN PROC_EPN=EPN XSTROBE=XSTROBE&X'FFFF'+1; ! LOSE CHNGE CONTEXT BIT IF SET END !----------------------------------------------------------------------- ROUTINE WORKSET(INTEGER RECAP) !*********************************************************************** !* PAGE OUT THE WORKING SET BY GOING THROUGH THE ACTIVE SEGMENT * !* LIST AND WRITING OUT ACTIVE EPAGES IN THAT SEGMENT * !*********************************************************************** RECORD (CBTF)NAME CBT !%INTEGERARRAYNAME PT; ! NEEDED IN ALL IMP VERSION ONLY INTEGER MARK,POFL,ASMASK,VSSEG,VSEPAGE,ASP,CBTP,PBLENS,I,J,PTB LONGINTEGER EPMASK ASMASK=ASWAP ASP=-1 WHILE ASMASK#0 CYCLE ; ! THROUGH ACTIVE SEGMENNTS *LSS_ASMASK; *SHZ_B ; *USH_1 *ST_ASMASK; *ADB_1; *ADB_ASP; *STB_ASP VSSEG=ASEG(ASP) CBTP=SST(VSSEG) CBT==CBTA(CBTP) PBLENS=MAXBLOCK EPMASK=AS(ASP) AS(ASP)=0 VSEPAGE=-1 PTB=VIRTAD+LST(VSSEG)&X'0FFFFFF8' ! PT==ARRAY(PTB,PTF) WHILE EPMASK#0 CYCLE *LSD_EPMASK; *SHZ_B ; *USH_1; *ST_EPMASK *ADB_1; *ADB_VSEPAGE; *STB_VSEPAGE IF VSEPAGE>=PBLENS START PBLENS=PBLENS+MAXBLOCK CBTP=CBTP+1 CBT==CBTA(CBTP) FINISH ! PAGE=VSEPAGE*EPAGESIZE ! MARK=0 ! %CYCLE I=PAGE,1,PAGE+EPAGESIZE-1 ! MARK=MARK!PT(I); ! GANG MARKERS TOGETHER ! %REPEAT ! ! THIS HAND CODING ASSUMES EPAGESIZE=4 ! I=PTB+4*EPAGESIZE*VSEPAGE *LXN_I *LSD_(XNB +0); *OR_(XNB +2) *STUH_B ; *OR_B *ST_MARK POFL=MARK<<3>>31<<3!1<<2!RECAP;! WRIT & UPDATE DRUM & RECAPTURE POUT_DEST=X'40002'; ! PAGETURN/PAGE-OUT POUT_P1=CBT_AMTX<<16!(VSEPAGE&(MAXBLOCK-1)) POUT_P2=POFL IF MONLEVEL&4#0 AND MONVAD>0 THEN C GARNER(1+POFL>>3,VSSEG<<18!VSEPAGE<<12) IF MONLEVEL&12=12 THEN START *LSS_(6); *ST_IC; *LSS_(5); *ST_IT FINISH PAGETURN(POUT) IF MONLEVEL&12=12 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 START EPN=EPN-1 IF CBT_LINK&SMULTIPLE CON=0 THEN UEPN=UEPN-1 FINISH REPEAT REPEAT IF EPN>0 THEN PROC_EPN=EPN ASWAP=0 ! ! SHUFFLE DOWN LIST OF OLD ASWIPS AND REMOVE ANY SEGMENTS NOT USED OVER ! "RESIDENCES" RESIDENCES PERIODS FROM ACTIVE LIST ! J=ASWIP&(¬ASSHR); ! ONLY PRIVATE SEGMENTS CYCLE I=MAXRESIDENCES-1,-1,0 J=J&OLD ASWIPS(I) IF I<RESIDENCES OLD ASWIPS(I+1)=OLD ASWIPS(I) REPEAT OLD ASWIPS(0)=ASWIP ! ! DEACTIVATE INACTIVE SEGMENTS ! IF J#0 THEN DEACTIVATE(J) ASWIP=¬ASFREE IF SEMAHELD#0 THEN PROC_STATUS=PROC_STATUS!1 C AND SEMAHELD=0 ! ! REMOVE PAGE TABLE ADDRS( BUT NOT ANY DAP SEGMENTS) FROM SEGMENT TABLE ! IF DAP FITTED=YES AND PROC_STATUS&2****10#0 START ! DAP SEGS HAVE TOP(SP) BIT SET IN LST CYCLE I=2,1,HIGHSEG IF LST(I)>0 THEN LST(I)=LST(I)&X'FFFFFFFF00000000' REPEAT FINISH ELSE START ! %CYCLE I=2,1,HIGHSEG ! LST(I)=LST(I)&X'FFFFFFFF00000000' ! %REPEAT *LD_X'2800000100000014' *LSS_0 *LB_HIGHSEG *SBB_1 RPA: *ST_(DR ) *INCA_8 *DEBJ_<RPA> FINISH RETURN PTS END !----------------------------------------------------------------------- IF MONLEVEL&4#0 START ROUTINE GARNER(INTEGER FLAG,INTEGER PARAM) !*********************************************************************** !* COLLECT PAGING MONITORING. A DOUBLE WORD OF FLAG<<28!ICCOUNT * !* FOLLOWED BY 32BIT PARAM(NORMALLY VIRTUAL ADDRESS) IS * !* WRITTEN INTO LOCKED DOWN FILE * !* FLAG=0 FOR DEMAND PAGE * !* FLAG=1&2 FOR PAGEOUTS & UPDATED PAGEOUTS * !* FLAG=3&4 FOR STROBEOUTS & UPDATED STROBEOUTS * !* FLAG=5 FOR A SNOOZE PARAM=EPN * !* FLAG=6 FOR A CHANGE CONTEXT REQUEST. PARAM=EPN * !*********************************************************************** INTEGER AD,W1,PVAD0,PVAD1 PVAD0=INTEGER(MONPTAD)&X'0FFFFFF0'+VIRTAD;! PUBLIC VIRTUAL AD OF P0 AD=MONVAD+INTEGER(PVAD0); ! CURRENT POSN W1=FLAG<<28!(ICREVS&15)<<24!INTEGER(PROC_STACK!X'40018') IF AD<MONLIM START PVAD1=INTEGER(MONPTAD+4*(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<<J FINISH ELSE START I=ASWIP CYCLE J=0,1,MAX RESIDENCES K=I&OLD ASWIPS(J); ! BITS IN K FOR SEGMENTS THAT ! HAVE BEEN INACTIVE J RESIDENCIES IF K=0 THEN EXIT ; ! LEAVING OLDEST IN I I=K REPEAT FINISH DEACTIVATE(I) END !----------------------------------------------------------------------- ROUTINE RETURN PTS !*********************************************************************** !* RETURN ALL THE EPAGES USED FOR PAGE TABLES. THE LIST HEADED BY * !* "PTP" AND LINKED VIA THE STORE TABLE * !*********************************************************************** POUT_DEST=X'60000'; ! DACT=0 DO YOUR OWN SEMAING WHILE PTP#0 CYCLE POUT_P2=PTP STORE(PTP)_USERS=0 PTP=STORE(PTP)_LINK IF MONLEVEL&12=12 THEN START *LSS_(6); *ST_IC; *LSS_(5); *ST_IT FINISH RETURN EPAGE(POUT) IF MONLEVEL&12=12 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 REPEAT END !----------------------------------------------------------------------- INTEGERFN FIND PROCESS !*********************************************************************** !* BY SEARCHING THE PROCESS LIST. USED FOR RELAY SERVICES * !*********************************************************************** STRING (6) USER INTEGER I,J,K,DACT,INCAR USER=STRING(PROC_STACK!X'40030'); ! IN OLD ACC J=INTEGER(PROC_STACK!X'4003C') INCAR=BYTEINTEGER(PROC_STACK!X'40037');! LAST BYTE = INCARNATION IF 1<=J<=3 THEN START K=LOCSN0+J*MAXPROCS DACT=ALLOUTP_DEST&X'FFFF' UNLESS J=3 AND (DACT=0 OR DACT=X'FFFF') THEN START CYCLE I=1,1,MAXPROCS-1 IF USER=PROCA(I)_USER AND PROCA(I)_INCAR=INCAR THEN C ALLOUTP_DEST=(I+K)<<16!DACT AND RESULT =I REPEAT FINISH FINISH ALLOUTP_DEST=0 RESULT =0 END !----------------------------------------------------------------------- INTEGERFN CURSSN !*********************************************************************** !* FIND THE CURRENT STACK NO * !*********************************************************************** INTEGER I,J J=PROC_STACK>>18 CYCLE I=1,1,LSTKN IF J=LSTKSSN(I) THEN RESULT =I REPEAT MONITOR("CURRENT STACK ?") END !----------------------------------------------------------------------- ROUTINE WAIT(INTEGER DACT,N) POUT_DEST=X'A0002' POUT_SRCE=0 POUT_P1=ME!DACT POUT_P2=N PON(POUT) END !----------------------------------------------------------------------- END !----------------------------------------------------------------------- END !*********************************************************************** !* THESE THREE ROUTINES ARE SYTEMCALLED DIRECTLY FROM USER * !*********************************************************************** EXTERNALINTEGERFN REQUEST INPUT(INTEGER OUTPUT POSN,TRIGGER POSN) UNLESS IOSTAT_OUTBUFLEN>0 AND 0<=OUTPUT POSN<IOSTAT_OUTBUFLEN C AND IOSTAT_INBUFLEN>0 AND 0<=TRIGGER POSN<IOSTAT_INBUFLEN C THEN RESULT =-1 IF IOSTAT_IAD#TRIGGER POSN THEN RESULT =0 DIROUTP_DEST=X'370006' DIROUTP_P1=IOSTAT_INSTREAM DIROUTP_P2=OUTPUT POSN DIROUTP_P3=TRIGGER POSN *OUT_2 RESULT =0 END !----------------------------------------------------------------------- EXTERNALINTEGERFN REQUEST OUTPUT(INTEGER OUTPUT POSN,TRIGGER POSN) CONSTINTEGER INST REPLY=X'370007'; ! COMMC C REPLIES AT ONCE CONSTINTEGER WAIT REPLY=X'370006'; ! REPLIES WHEN OPUT FINISHED UNLESS IOSTAT_OUTBUFLEN>0 AND 0<=OUTPUT POSN<IOSTAT_OUTBUFLEN C AND -1<=TRIGGER POSN<IOSTAT_OUTBUFLEN THEN RESULT =-1 IF TRIGGER POSN<0 THEN DIROUTP_DEST=INST REPLY C ELSE DIROUTP_DEST=WAIT REPLY DIROUTP_P1=IOSTAT_OUTSTREAM DIROUTP_P2=OUTPUT POSN DIROUTP_P3=TRIGGER POSN *OUT_24 IF DIROUTP_P2#0 THEN RESULT =-2;! SOME COMMS DISASTER RESULT =DIROUTP_P5 END !----------------------------------------------------------------------- EXTERNALINTEGERFN CHANGE CONTEXT *OUT_26 RESULT =0 END !----------------------------------------------------------------------- LONGINTEGERFN RTDR(INTEGERFN A) *LSD_(LNB +5) *EXIT_-64 END !----------------------------------------------------------------------- ENDOFFILE