Trailing-Edge
-
PDP-10 Archives
-
BB-F493Z-DD_1986
-
10,7/703mon/segcon.mac
There are 12 other files named segcon.mac in the archive. Click here to see a list.
TITLE SEGCON - HIGH SEGMENT CONTROL FOR REENTRANT USER PROGRAMMING V1166
SUBTTL T. HASTINGS/TW/TNM/TH/AF/CHW/TW/PFC/DAL 18 MAR 86
SEARCH F,S
$RELOC
$HIGH
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
.CPYRT<1973,1986>
;COPYRIGHT (C) 1973,1974,1975,1976,1977,1978,1979,1980,1982,1984,1986
;BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
;ALL RIGHTS RESERVED.
;
;
XP VSEGCN,1166
;PUT VERSION NUMBER IN GLOB LISTING AND LOADER MAP
;ALL OF THE CODE DEALING WITH THE SECOND RELOCATION REGISTER HAS BEEN ISOLATED
;IN THIS ONE ROUTINE NAMED SEGCON
;SIX OF THE MONITOR MODULES CALL SUBROUTINES IN SEGCON WITH PUSHJ'S.
;THIS HAS BEEN DONE FOR TWO REASONS:
; 1.TO MAKE IT EASY TO BUILD SYSTEMS WITH OR WITHOUT 2 REG. CAPABILITY
; SEGCON CAN BE REPLACED BY A SHORT DUMMY ROUTINE(NULSEG), SO THERE
; IS NO CONDITIONAL ASSEMBLY REQUIRED TO ELIMINATE MOST OF THE CODE.
; THOSE CUSTOMERS WHO WOULD LIKE TO ELIMINATE ALL OF THE CODE MAY DO SO BY
; REASSEMBLING THE MONITOR WITH FEATURE SWITCH FT2REL=0.
; THIS WILL ELIMINATE ALL PUSHJ CALLS TO SEGCON
; 2. TO MAKE IT CLEAR EXACTLY WHERE TWO SEGMENTS ARE DEALT WITH
;ALL OF THE CALLS TO SEGCON ARE OF THE FORM:
;IFN FT2REL,<
; EXTERN XXXXXX
; PUSHJ P,XXXXXX
; ERROR RETURN OR NOTHING TO DO
; OK RETURN
;>
;OR:
;IFN FT2REL,<
; EXTERN XXXXXX
; PUSHJ P,XXXXXX
; OK RETURN
;>
;SEGCON IS GOOD FOR SWAPPING AND NON-SWAPPING SYSTEMS
;AND FOR SYSTEMS WITH AND WITHOUT DISK
;TO MAKE IT CLEAR WHERE EACH SUBROUTINE IS CALLED FROM
;AND WHAT FUNCTION IT IS PERFORMING, THE MODULES OF THE MONITOR HAVE BEEN REPLICATED
;IN SEGCON USING SUBTTL. THE MODULES ARE:
; 1. CLOCK
; 2. COMCSS
; 3. CORE1
; 4. SAVGET
; 5. SWAP
; 6. UUOCON
;ADDITIONAL MONITOR DATA TO HANDLE TWO SEGMENT USER PROGRAMS:
;A NUMBER OF THE ALREADY EXISTING JOB TABLES HAVE BEEN LENGTHENED
;BY AN AMOUNT SEGN(THE NUMBER OF POSSIBLE HIGH SEGMENTS). THE LOWER
;PART OT THESE TABLES HAVE REMAINED AS THEY WERE(O THRU JOBMAX=JOBN-1)
;WITH ONE WORD PER JOB( OR LOW SEGMENT). THE NEW HALF(GREATER THAN JOBMAX)
;HAVE ONE WORD FOR EACH HIGH SEGMENT. A HIGH SEGMENT NUMBER IS REALLY
;A LARGE JOB NUMBER AND IS AN INDEX INTO THE JOB TABLES.
;THE HIGHEST INDEX IN THESE LENGTHENED JOB TABLES IS JBTMAX.
;THERE IS AT LEAST ENOUGH TABLE SPACE SO THAT EACH JOB CAN HAVE A
;DIFFERENT HIGH SEGMENT. THE FOLLOWING TABLES HAVE BEEN LEGNTHENED:
;JBTSTS- JOB(SEG) STATUS
; LH=STATUS BITS:
; SWP=1 IF HIGH SEG SWAPPED OUT(WHETHER SPACE ON DISK OR NONE)
; OR ON WAY IN OR OUT. IE SWP=1 MEANS NOT RUNABLE COR IN CORE.
; SWP=0 WHEN HIGH SEG HAS RUNABLE COR IN CORE
; EVEN THOUGH ALSO HAS SPACE ONDISK.
; SNA=1 IF HIGH SEG NO. APPEARS IN AT LEAST ONE USER'S LOGICAL ADR. SPACE
; SNA IS SIGN BIT OF JBTSTS.
; SNA=0 IF HIGH SEG IS COMPLETELY FREE OR IS DORMANT,
; WHERE DORMANT MEANS THAT THE SEGMENT DOES NOT APPEAR IN ANY USER'S
; LOGINCAL ADDRESSING SPACE, BUT IS STILL AROUND PHYSICALLY ON DISK
; OR IN CORE
; SHRSEG=1 IF SEG IS SHARABLE(WHETHER IT STILL HAS A NAME OR
; HAS BEEN SUPERCEDED).
; BITS 9-17 ARE ACCESS PRIBILEGES - SAME FORMAT AS DISK FILES
; HSAPOS=RIGHT MOST BIT POSITION
; HSAMSK=MASK FOR BITS(ALL ONES)
; HSASIZ=SIZE OF FIELD
; RH=IN-CORE COUNT(RATHER THAN RUN TIME LEFT) IE NUMBER OF JOBS
; IN CORE USING HIGH SEG IN CORE
;JBTADR- HIGH JOB(SEG) CORE ASSIGNMENT
; LH=LENGTH-1 OF HIGH SEG(NOT PROTECTION LIKE LOW SEG)
; FOR LOW SEGS PROTECTION(HIGHEST LEGAL USER ADDRESS) AND LENGTH-1
; ARE THE SAME. HOWEVER THEY ARE DIFFERENT FOR HIGH SEGS, SO LENGTH-1
; WAS CHOSEN INSTEAD OF THE PROTECTION AS THE QUANTITY FOR THE LH.
; RH=ABSOLUTE ADR. OF BEG OF HIGH SEG(NOT RELOCATION LIKE LOW SEG)
; FOR LOW SEGS THE RELOACTION AND THE ABSOLUTE ORIGIN ARE THE SAME.
; HOWEVER THEY ARE DIFFERENT FOR HIGH SEGS, SO THE ABSOLUTE ORIGIN WAS
; CHOSEN INSTEAD OF THE RELOCATION AS THE QUANTITY FOR THE RH.
; 0 MEANS NO CORE IN MEMORY AT ALL
; CORE IS ASSIGNED DURING SWAP IN AND OUT TOO
;JBTIMI/JBTIMO JOB SWAP INFO
; JBTIMI/JBTIMO REPLACE OLD IMGIN/IMGOUT RESPECTIVELY=# OF PAGES WHEN
; BROUGHT IN OR # OF PAGES ON DISK
; OLD LEFT HALF OF JBTSWP-DSK ADDR-NOW LEFT HALF OF JBTSWP
;JBTCHK- CHECKSUM FOR HIGH SEG WHEN SWAPPED OUT
;THE FOLLOWING JOB TABLES HAVE BEEN ADDED:
;JBTSGN(0...JOBMAX) - HIGH SEG NUMBER WHICH JOB IS USING IN CORE OR ON DISK
; 0 MEANS JOB DOES NOT HAVE A HIGH SEGMENT.
; LH BITS:
; SPYSEG=1(SIGN BIT) HIGH SEG IS PART OF PHYSICAL CORE(SPY UUO),
; RH IS HIGHEST PHYSICAL ADR FOR THIS USER TO LOOK AT
; SERSEG=1 MEANS THAT THE HIGH SEG WHICH THIS USER IS USING IS SHARABLE
; THIS BIT ALSO APPEARS IN THE JBTSTS WORD IN THE SAME POSITION
; IN THE WORD, SINCE SHARABLE IS A PROPERTY OF A SEGMENT, NOT OF
; THE JOB USING THE SEGMENT. IT IS DUPLICATED HERE ONLY AS
; A CONVENIENCE SO IT WILL APPEAR IN THE LH OF AC ITEM.
; UWPOFF=1 USER WRITE PROTECT IS OFF FOR THIS USER(NORMALLY
; UWP OS ON, SO UWPOFF=0)
; MEDDLE=1 IF USER HAS MEDDLED WITH PROGRAM SO HE SHOULD NOT BE ALLOWED
; TO TURN OFF UWP OR CHANGE CORE ASSIGNMENT
; MEDDLE IS SET ONLY IF HIGH SEG IS SHARABLE OR A SPY SEG
; MEDDLING IS DEFINED AS ANYTHING WHICH CAUSES THE PROGRAM NOT
; NOT TO BE IN CONTROL OF ITSELF:
; 1. START COMMAND WITH ARG
; 2. DEPOSIT COMMAND(D) IN LOW SEG(HIGH SEG ALWAYS ILLEGAL)
; 3. RUN UUO WITH BIGGER START ADR. INCREMENT THAN 0 OR 1
; 4. GETSEG UUO
; 5. HIGH SEG IS PHYSICAL CORE(SPY UUO)
;CORCNT=1 IF HIGH SEG IN CORE COUNT HAS BEEN INCREMENTED FOR THIS JOB
; (JOB LOW SEG MAY OR MAY NOT BE IN CORE)
; SET BY INCCNT ROUTINE, CLEARED BY DECCNT ROUTINE
;JBTDEV(JOBN...JBTMAX) - HIGH SEG DEVICE NAME OF FILE STRUCTURE NAME
; (EG DSKA,DSKB,DTAN,MTAN)
;JBTPPN(JOBN...JBTMAX) - HIGH SEG DIRECTORY NAME(EXTENSION OF JBTPPN TABLE)
; IS PROJECT-PROGRAMMER IF DISK, 0 IF DTA OR MTA
;JBTNAM(JOBN...JBTMAX) - HIGH SEG NAME(EXTENSION ASSUMED TO BE SHR)
; (EXTENSION OF JBTPRG TABLE)
; THE NAME(AND DISK COPY) IS RETAINED EVEN AFTER NO JOBAS ARE USING
; HIGH SEG IN CORE OR ON DISK, THUS SAVING TIME FOR GET'S.
; HOWEVER, IF SWAPPING SPACE BECOMES FULL, THESE UNUSED HIGH SEGS
; ARE DELETED ONE AT A TIME, UNTIL THERE IS ROOM. IF STILL NO ROOM,
; COPIES OF HIGH SEGS WHICH ARE ALSO IN CORE ARE DELETED.
; ANY HIGH SEG WHICH HAS A NAME IS SHARABLE AND HAS SHRSEG SET IN JBTSTS.
; A HIGH SEG WITH SEGSHR SET AND JBTNAM=0 IS A HIGH SEG WHICH HAS BEEN
; SUPERCEDED BY A LATER VERSION OF A HIGH FILE.
;THE FOLLOWING LOCATION HAS BEEN ADDED TO THE JOB DATA AREA:
;JOBHRL - RH IS ANALOGOUS TO JOBREL, HIGHEST RELATIVE(USER) ADR. IN HIGH SEG
; IE HIGHEST LEGAL USER ADDRESS IN HIGH SEG
; 0 MEANS JOB DOES NOT HAVE A HIGH SEG
; SET BY MONITOR EVERY TIME JOB RUNS
; LH IS ANALOGOUS TO LH OF JOBSA, FIRST FREE(RELATIVE) LOCATION IN HIGH SEG
; SET BY LINKING LOADER, USED ON SAVE FOR AMOUNT TO WRITE
; THE FIRST FREE LOCATION CONTAINS THE STARTING ADDRESS OF JOB
; WHICH IS SET BY SAVE FROM JOBSA WHICH WAS SET BY LINKING LOADER
; BOTH HALVES ARE 0 IF NO HIGH SEG
;JOBCOR - LH IS HIGHEST LOC LOADED WITH DATA IN LOW SEG
; SET BY LINKING LOADER
; USED BY SAVE FOR 2 SEG PROGRAM ONLY, WRITE LOW SEG IF LH JOBCOR IS
; GREATER THAN 137(HIGHEST LOC IN JOB DATA AREA
;THE HIGH SEGMENT HAS A VERY SMALL JOB DATA AREA(10 LOCATIONS)
;WHICH IS USED FOR INITIALIZING THE REGULAR JOB DATA AREA ON A GET
;IN CASE THE JOB DOES NOT HAVE A LOW SEGMENT FILE(HIGHLY DESIRABLE)
;SEE JOBDAT FOR DEFINITIONS.
;THE CONTENTS OF AC J MAY BE A JOB NUMBER OR A HIGH SEGMENT NUMBER
;AC J IS LOADED FROM JBTSGN INDEXED BY JOB NUMBER
;SO THAT AC J CONTAINS LH BITS FOR EASY TESTING WHEN THE RH
;HAS A HIGH EGMENT NUMBER IN IT. WHEN AC J HAS A JOB NUMBER
;IN IT, THE LH IS ALWAYS 0
;IN SWAP, AC J IS DEFINED TO BE AC J
;HOWEVER, A COMPARE WITH JOBMAX WILL STILL GIVE HIGH SEG OR LOW SEG
;NOTE, THAT SPYSEG IS SIGN BIT SO 'SKIPG' TEST FOR REAL HIGH SEG
;TERMINOLOGY IN THE COMMENTS OF SEGCON:
;'SEG' IS AN ABREVIATION FOR 'SEGMENT'
;'JOB' OR 'JOB NUMBER' ALWAYS REFERS TO NUBERS LESS-THAN OR EQUAL-TO JOBMAX
;THE COMMENTS IN THE REST OF THE MONITOR HAVE NOT BEEN CHANGED, SO THAT THERE ARE
;MANY ROUTINES WHICH ARE NOW DEALING WITH BOTH JOB NUMBERS AND HIG SEG NUMBERS
;(MAINLY IN CORE AND SWAP ROUTINES) WITHOUT KNOWING IT.
;'SEGMENT' REFERS TO BOTH LOW AND HIGH SGMENTS, RATHER THAN JUST HIGH SEGMENTS
;AND WILL ALWAYS BE PRECEDED BY 'LOW' OR 'HIGH' IF BOTH IS NOT INTENDED.
;'JOB NUMBER' IS USED INTERCHANGEABLE WITH 'LOW SEG NUMBER'.
;'ADDRESS','ADR','LOCATION','LOC', AND 'ORIGIN' ALL
;REFER TO USER(IE BEFORE HARDWARE OR SOFTWARE RELOCATION) QUANTITIES.
;MOST OF THE TIME THESE WORDS ARE MODIFIED WITH 'USER' OR 'RELATIVE'.
;HOWEVER, THIS IS NOT COMPLETELY CONSISTENT.
;OCCASIONALLY ABSOLUTE ADDRESSES ARE COMPUTED BY THE MONITOR. IN ALL THESE
;CASES, 'ABSOLUTE' OR 'ABS' PRECEEDS THESE WORDS.
;THE REENTRANT CAPABILITY IMPROVES SYSTEM THRUPUT BY REDUCING THE DEMANDS ON:
; 1. CORE MEMORY - SHARING
; 2. SWAPPING STORAGE - SHARING
; 3. SWAPPING CHANNEL READS
; 4. SWAPPING CHANNEL WRITES
; 5. STORAGE CHANNEL READS - GET
;HOWEVER, 2 COMPETES WITH 4 AND 5, IN THAT TO REDUCE THE DEMANDS 4 AND 5,
;COPIES OF UNUSED (DORMANT) HIGH SEGMENTS ARE KEPT ON THE SWAPPING DEVICE, THEREBY
;INCREASING THE DEMAND FOR SWAPPING STORAGE(2). THE QUESTION NATURALLY ARISES,
;HOW DOES THE SYSTEM DETERMINE THIS SPACE-TIME TRADEOFF?
;THE MONITOR ACHIEVES THE BALANCE DYNAMICALLY, AFTER THE OPERATOR
;ESTABLISHED THE SIZE OF THE SWAPPING SPACE WHEN THE SYSTEM IS STARTED
;(ONCE ONLY DIALOG). THE MONITOR ASSUMES THAT THERE IS NO SHORTAGE
;OF SWAPPING SPACE, AND SO KEEPS A SINGLE COPY OF AS MANY HIGH SHARABLE
;SEGMENTS IN THE SWAPPING SPACE AS THERE ARE HIGH SEG NUMBERS.
;(THE MAX NUMBER OF HIGH SEG NUMBERS IS ESTABLISHED AT BUILD TIME
;AND IS EQUAL TO OR GREATER THAN THE NUMBER OF JOBS(COUNTING THE NULL JOB).
;THUS DEMANDS 4 AND 5 ARE MINIMIZED.
;HOWEVER IF SWAPING SPACE IS EXHAUSTED, THE MONITOR WILL TRY DELETING
;A HIGH SHARABLE SEG THAT IS NOT IN USE BY ANY JOB.(A SO-CALLED DORMANT SEG)
;WHEN DELETED SEG IS NEXT NEEDED(A GET OCCURRED), IT WILL
;BE GOTTEN FROM STORAGE DEVICE, INCREASING DEMAND 5. IF NO UNUSED HIGH SEGS EXIST
;THE MONITOR WILL TRY DELETING A HIGH(SHARABLE OR NON-SHARABLE) SEG THAT
;IS IN USE AND HAS A COPY, BOTH ON THE DISK AND IN CORE. THUS WHEN THIS HIGH SEG IS
;SWAPPED OUT, IT WILL REQUIRE A WRITE, INCREASING DEMAND 4.
;TO RESTATE: THE MONITOR USES ALL THE SWAPPING SPACE AVAILABLE. IF IT RUNS OUT,
;IT INCREASES STORAGE CHANNEL READS(GET), THEN SWAPPING CHANNEL WRITES IN ORDER
;TO OVERCOME THE SPACE SHORTAGE.
;THE SAME LOOK-A-SIDE TECHNIQUE IS USED FOR CORE IN BOTH SWAPPING AND NON-SWAPPING
; SYSTEMS IN THAT THE MONITOR KEEPS DORMANT SEGMENTS IN CORE
;UNTIL THEY ARE NEEDED OR CORE DEMAND REQUIRES THAT THEY BE RETURNED
;THERE IS A THIRD CLASS OF SEGMENTS, CALLED 'IDLE'.
;AN IDLE SEGMENT IS A SHARABLE SEG WHICH IS IN CORE, BUT NO JOB IN CORE
;IS USING IT, BUT SOMEONE ON DISK IS. IT WILL BE DELETED IF CORE IS NEEDED
;THE 3 CLASSES OF SEGMENTS ARE ACTIVE,IDLE,DORMANT.
;LOCATION CORTAL CONTAINS THE SUM OF FREE BLOCKS+DORMANT BLOCKS
;HOWEVER CORTAB CONTAINS 0 BITS ONLY FOR FREE BLOCKS
;TO FREE STORAGE
;THE CORE COMMAND WITH NO ARG STILL PRINTS CORE AS IF NO DORMANT SEGS IN CORE
;VIRTAL CONTAINS THH AMOUNT OF FREE VIRTUAL CORE LEFT IN SYSTEM
;INCLUDING HIGH SEGMENTS. SINCE THIS QUANTITY IS USED TO PREVENT
;THE CORE ROUTINES FROM OVER COMMITTING SWAP SPACE. SHARED SEG ARE ONLY
;COUNTED ONCE, AND DORMANT SEGMENTS ARE NOT INCLUDED. THUS VIRTAL IS
;DECREMENTED WHEN THE FIRST USER SHARES A SEGMENT CHANGING IT FROM DORMANT
;TO ACTIVE
ENTRY SEGCON
SEGCON:: ;ENTRY POINT SYMBOL TO CAUSE LOADING OF SEGCON
;(AS OPPOSED TO NULSEG OR NEITHER)
SUBTTL ONCE - ONCE ONLY STARTUP CODE
;LOCATION 'TWOREG' IS A FLAG WHICH IS TESTED AT POINTS WHERE A HIGH
;SEGMENT CAN BE CREATED, TO SEE IF BOTH HARDWARE AND SOFTWARE HAVE TWO
;REGISTER CAPABILITY
;INITIALIZE LOC TWOREG TO 0 IF SOFTWARE OR HARDWARE DOES NOT HAVE 2 SEGMENT
;CAPABILTIY. SET TWOREG TO -1 IF BOTH DO HAVE 2 SEGMENT CAPABILITY.
;SYMBOL AND2RG IS ANDDED TO 'TWOREG' FROM ONCE ONLY CODE AFTER THE HARDWARE IS
;EXAMINED AND TWOREG HAS BEEN SET TO 0 OR -1 ACCORDINGLY.
SUBTTL COMCSS - COMMAND DECODER SUBROUTINES
;ROUTINE TO STOP NEW USERS FROM SHARAING EXISTING SEGMENTS ON DECTAPE
;AND MAGTAPE WHICH HAVE BEEN JUST ASSIGNED, SINCE THE NEW TAPE MAY HAVE
;A LATER VERSION OF THE FILE WITH THE SAME NAME AS THE SEGMENT.
;REMSEG - DELETE ALL SEGS OF DISK FILE STRUCTURE BEING REMOVED
;CALLED FROM ASSIGN,DEASG(DEASSIGN,FINISH,KJOB) CONSOLE COMMAND. REMSTRR UUO
;CALL: MOVE F,DEVICE DATA BLOCK ADDRESS OR STR DATA BLOCK ADR.
; MOVE T2,DEVMOD(F) ;DEVICE CHARACTERISTICS
; PUSHJ P,ASGHGH
; ALWAYS RETURN, C(T2) DESTROYED
ASGHGH::TLNN T2,DVDTA!DVMTA ;IS THIS DEVICE JUST ASSIGNED A DTA OR MTA?
POPJ P, ;NO, NO CONFLICT POSSIBLE
REMSEG::
IFN FTMP,<
PUSHJ P,GGVMM## ;GET MM RESOURCE FOR CALL TO CLRNAM
>
PUSH P,J ;YES, SAVE JOB NUMBER
ASG1: MOVE J,SEGPTR## ;SCAN ALL HIGH SEGMENTS
ASG2: MOVE T1,DEVNAM(F) ;GET DEVICE NAME(PHYSICAL)
CAME T1,JBTDEV##(J) ;DOES IT MATCH DEVICE NAME OF SEG?
AOBJN J,ASG2 ;NO, KEEP LOOKING, FINISHED?
JUMPG J,IPOPJ## ;RETURN IF FINISHED AND RESTORE JOB NUMBER
TLZ J,-1 ;CLEAR OUT LH BITS OF HIGH SEG NO.
PUSHJ P,CLRNAM ;NOT FINISHED, CLEAR SEG NAME
;AND RETURN DISK SPACE IF NOT IN USE
JRST ASG1 ;CONTINUE SCAN, RESTORE T1 TO DEVICE NAME
;ROUTINE TO PRINT SIZE OF HIGH SEG LOGICAL CORE
;CALL: MOVE J,JOB NO.
; PUSHJ P,PRTHGH
; ALWAYS RETURN WITH J RESTORED
;PRINTS +N(UNLESS NOT TWO REG HARDWARE, SO USERS CAN TELL IF 2 REG. HARD.)
PRTHGH::PUSHJ P,PRTPLS## ;YES, PRINT +
PUSH P,J ;SAVE JOB NUMBER
SKIPG J,JBTSGN##(J) ;DOES JOB HAVE A REAL HIGH SEG?
MOVEI J,0 ;NO, MAKE SURE NO HIGH SEG(IN CASE SPY SEG)
PUSHJ P,PRTSEG## ;PRINT SIZE OF LOGICAL ADR. HIGH SEG
JRST IPOPJ## ;RESTORE JOB NUMBER AND RETURN
;ROUTINE TO CHECK TO SEE IF USER IS MEDDLING WITH A SHARABLE PROGRAM
; IF YES, TURN UWPOFF OFF SO UWP(USER MODE WRITE PROTECT) WILL BE ON
; AND SET MEDDLE, SO HE CANNOT TURN UWP BACK OFF AND CANNOT CHANGE CORE
; ASSIGNMENT OF HIGH SEG(EXCEPT TO REMOVE IT COMPLETELY)
;CALL: MOVE J,JOB NO.
; PUSHJ P,CHKMED
; ALWAYS RETURN, J RESTORED AND T2 PRESERVED(T1 USED)
;CALLED FROM DEPOSIT, START N, RUN UUO, GETSEG UUO
;T2 PRESERVED
CHKMED::SKIPLE T1,JBTSGN##(J) ;DOES JOB HAVE A REAL HIGH SEG?
TLNN T1,SHRSEG ;YES, IS IT SHARABLE?
POPJ P, ;NO(NONE OR SPY SEG(MEDDLE ALREADY ON))
TLO T1,MEDDLE ;YES, FLAG TIS USER AS MEDDLING
TLZ T1,UWPOFF ;AND FORCE UWP ON IN HARDWARE SO WRITES TRAP
MOVEM T1,JBTSGN##(J) ;NEXT TIME USER RUNS
POPJ P,
;ROUTINE TO COMPUTE NO. OF K USED BY A JOB
;BOTH LOW AND HIGH SEGMENTS
;CALL: MOVE J, JOB NO.
; PUSHJ P,JOBSIZ
; RETURN WITH T2=SIZE IN K, J PRESERVED
JOBSIZ::PUSHJ P,SEGSIZ## ;SIZE OF LOW SEG
MOVE T1,T2 ;SAVE IN T1
PUSH P,J ;SAVE LOW SEG NUMBER
SKIPG J,JBTSGN##(J) ;DOES JOB HAVE REAL HIGH SEG?
JRST JOBSZ1 ;NO, RESTORE JOB NUMBER
PUSHJ P,SEGSIZ## ;YES, GET SIZE OF HIGH SEG
ADD T2,T1 ;ADD LOW SIZE TO HIGH SIZE
JOBSZ1: POP P,J
LDB T1,NFYPGS## ;ROUND UP TO NEXT ONE K BOUNDARY
ADDI T2,-UPMPSZ##(T1)
LSH T2,P2KLSH## ;CONVERT PAGES TO K
POPJ P, ;RESTORE JOB NO. AND RETURN
SUBTTL CORE1 - LOGICAL AND PHYSICAL CORE ALLOCATION
;ROUTINE TO CHECK FOR SAVE IN PROGRESS FROM A HIGH SEG
;ABOUT TO BE SHUFFLED OR SWAPPED, OR CORE REASSIGNED
;CALL: MOVE J,LOW OR HIGH SEG TO BE SHUFFLED OR SWAPPED
; PUSHJ P,ANYSAV
; RET1 - THIS IS A HIGH SEG WHICH SOME JOB IS DOING A SAVE OF
; RET2 - THIS IS A HIGH SEG WHICH CAN BE SHUFFLED OR SWAPPED
;CALLED FROM ANYACT IN CORE MODULE,T2 PRESERVED FOR SWAPPER
ANYSAV::CAILE J,JOBMAX## ;IS THIS A LOW SEG?
SKIPN JBTADR##(J) ;NO, IS THIS HIGH SEG IN CORE?
JRST CPOPJ1## ;YES, GIVE SINGLE SKIP RETURN
PUSH P,T1 ;SAVE T1 FOR SHUFFLER
HRRZ T1,JBTSHR##(J) ;GET SEGMENT'S SHARE COUNT
JUMPE T1,TPOPJ1## ;IF NO SHARERS, IT'S NOT BEING SAVED
PUSH P,T2 ;FOR THE SWAPPER
PUSH P,J ;SAVE HIGH SEG NUMBER
MOVE J,HIGHJB## ;HIGHEST JOB NUMBER ASSIGNED
ANYSV0: SKIPN JBTADR##(J) ;IS JOB IN CORE (R=R)?
JRST ANYSV1 ;NO
MOVE T2,[USRHCU##-.UPMP+.UPMVP] ;FOR MAPWRD
PUSHJ P,MAPWRD ;MAKE JOBHCU ADDRESSABLE
SKIPL (T2) ;YES, IS A SAVE OR GET FOR EITHER SEG IN PROGRESS?
ANYSV1: SOJG J,ANYSV0 ;NO, KEEP LOOKING, FINISHED?
JUMPLE J,ANYSV2 ;YES, FIND A SAVE OR GET IN PROGRESS
MOVSI T1,SWP ;JOB SWAPPED OUT OR ON WAY IN OR OUT BIT
TDNE T1,JBTSTS##(J) ;IS THIS JOB SWAPPED OUT OR ON WAY IN OR OUT
JRST ANYSV1 ;YES, DO NOT LOOK AT JOB DATA AREA
; SINCE IT MAY NOT HAVE BEEN WRITTEN INTO
; IF THIS IS A SWAP IN
HRRZ T1,JBTSGN##(J) ;NO, GET ITS HIGH NUMBER, IF ANY
SKIPLE JBTSGN##(J) ;A REAL HIGH SEGMENT?
CAIE T1,@(P) ;IS IT SAME AS HIGH SEG IN QUESTION?
; (INDIRECT AND INDEX BITS ALWAYS 0)
JRST ANYSV1 ;NO, KEEP LOOKING
CAIA ;YES, GIVE SAVE ACTIVE RETURN
ANYSV2: AOS -3(P) ;NO SAVE IN PROGRESS
POP P,J ;RESTORE HIGH SEG NUMBER
JRST TTPOPJ## ;GIVE ERROR OR OK RETURN
;ROUTINE TO DEPOSIT USER COMMAND ARG IN HIGH SEG IF USER HAS PRIVILEGES
; TO WRITE OR SEG IS NON-SHARABLE
;CALL: MOVE J,JOB NO.
; MOVE R,JOB RELOC.
; MOVE T2,REL. USER ADR. NOT IN LOW SEG
; MOVE S,WORD TO DEPOSIT
; PUSHJ P,HGHDEP
; ERROR RETURN
; OK RETURN - JOBEXM SET TO USER ADR IN HIGH SEG, S STORED IN HIGH SEG
HGHDEP::HRR M,T2 ;MOVE REL. ADR. TO M FOR HGHWRD ROUT.
PUSHJ P,HGHWRD ;SET T1 TO HIGH WORD, T2 TO ADR.
POPJ P, ;NOT IN BOUNDS, ERROR RETURN OR NO HIGH SEG
MOVE P2,J ;SETUP JOB NUMBER FOR CHKHSW ROUT.
PUSH P,J ;SAVE JOB NUMBER
PUSHJ P,MAPWRD ;T2 = EVA OF WORD
PUSH P,T2 ;SAVE ABS. ADR. OF LOC. IN HIGH SEG
SKIPLE J,JBTSGN##(J) ;GET HIGH SEG NUMBER
PUSHJ P,CHKHSW ;CAN JOB(P2) WRITE IN HIGH SEG(J)?
JRST HGHDP1 ;NO, ERROR RETURN
IFN FTMP,<
;THE FOLLOWING TWO INSTRUCTIONS ARE PROBABLY NOT NECESSARY AND ARE
; HERE ONLY FOR SAFETY SAKE, (SOMEONE STORING IN A HIGH SEG AT IRP LEVEL?)
CONSZ PI,PI.IPA-PI.IP7;IF AT HARD INTERRUPT LEVEL,
JRST HGHDP1 ; CAN'T GET THE MM RESOURCE SO MUST FAIL
PUSHJ P,GETMM## ;GET THE MM RESOURCE
JRST .-1 ;MUST WAIT UNTIL ITS AVAILABLE
>
MOVEM S,@(P) ;YES,STORE USER ARG
HRRZM M,.JDAT+JOBEXM## ;STORE LOC OF DEPOSIT FOR D,E WITH NO ARG
; LH=O MEANING D WAS LAST DONE RATHER THAN E
HRRZS J
PUSHJ P,ZERSWP## ;DELETE SWAPPING SPACE,IF ANY
IFN FTMP,<
PUSHJ P,GIVMM## ;RETURN THE MM RESOURCE
>
AOS -2(P) ;SET FOR SKIP RETURN
HGHDP1: POP P,(P) ;RESTORE ADR
JRST JPOPJ## ;RESTORE JOB NUMBER AND ERROR OR OK RETURN
;ROUTINE TO MAKE ANY WORD OF ANY JOB ADDRESSABLE
; (IN FACT WRITABLE) BY MAPPING IT THROUGH THE
; PER PROCESS MAP OF THE CURRENT JOB
;CALLING SEQUENCE:
; MOVE T2,USER VIRTUAL ADDRESS TO BE MAPPED
; MOVE J,JOB NUMBER OF JOB CONTAINING THE WORD
; PUSHJ P,MAPWRD
; ... RETURN HERE
;ON RETURN FROM CALL TO MAPWRD T2=EVA OF WORD
MAPWRD::PUSH P,T2 ;SAVE UVA
PUSHJ P,RTPTA ;GET POINTER FROM TARGET JOBS MAP
HRLI T2,(<PM.DCD>B2+PM.WRT+PM.PUB) ;BITS
MOVEM T2,.UPMP+.UMTMP ;MAKE THAT ADDRESSABLE (EVEN WRITABLE) IN OUR CONTEXT
CLRPGT (0,.TEMP) ;CLEAR AM FOR THIS PAGE
MOVEI T2,.TEMP/PAGSIZ## ;PAGE # IN EV ADDRESSING SPACE
DPB T2,[POINT 9,(P),26] ;EVA OF WORD
JRST T2POPJ## ;RESTORE EVA AND RETURN
;ROUTINE TO RETURN CONTENTS OF A MAP SLOT WHICH MAPS A VIRTUAL PAGE NUMBER
;CALLING SEQUENCE:
; MOVE T2,VIRTUAL PAGE NUMBER
; MOVE J,JOB NUMBER
; PUSHJ P,RTPTR
; ALWAYS RETURNS HERE, T2 = CONTENTS OF TARGET JOBS MAP SLOT
;PRESERVES ALL ACS AND THE MAP
RTPTA: LSH T2,W2PLSH## ;CONVERT FROM VIRTUAL ADDRESS TO PAGE NUMBER
RTPTR:: SE1ENT ;MUST BE IN SECTION 1 TO REFERENCE PAGTAB
PUSH P,T1 ;SAVE A WORKING AC
PUSH P,.UPMP+.UMTMP
HRRZ T1,JBTUPM##(J) ;TARGET JOB'S PROCESS TABLE
HRLI T1,(<PM.DCD>B2+PM.WRT+PM.PUB) ;BITS
MOVEM T1,.UPMP+.UMTMP ;MAKE THE JOBS MAP ADDRESSABLE
CLRPGT (0,.TEMP) ;CLEAR PAGING MEMORY FOR THIS VIRTUAL ADDRESS
CAIL T2,.MCFV/PAGSIZ## ;POINTER IN PAGE TABLE OR PROCESS TABLE?
JRST RTPT4 ;IF A FUNNY SPACE PAGE, NO MORE MAPPING
MOVE T1,T2 ;GET SECTION PAGE IS IN
LSH T1,P2SLSH## ;..
RTPT0: MOVE T1,.TEMP+SECTAB(T1) ;GET SECTION MAP POINTER
TLNN T1,(<<PM.ACD^!PM.DCD>B2>) ;INDIRECT?
JRST RTPT1 ;NO, JUST MAP IT
LDB T1,[POINT POINT 5,T1,17] ;SEE RSECT4 IN VMSER FOR DETAILS
JRST RTPT0 ;CHECK AGAIN
RTPT1: MOVEM T1,.UPMP+.UMTMP ;MAKE IT ADDRESSIBLE
CLRPGT (0,.TEMP) ;CLEAR MEMORY
ANDI T2,HLGPNO ;GET SECTION RELATIVE PAGE NUMBER
RTPT2: MOVE T2,.TEMP(T2) ;GET POINTER FROM THE MAP
POP P,.UPMP+.UMTMP
CLRPGT (0,.TEMP) ;CAUSE A REFILL FOR SLOT USED TEMPORARILY
JRST TPOPJ## ;RESTORE TEMPORARY AND RETURN
RTPT4: CAIG T2,<.UPMVP/PAGSIZ##> ;IS IT TRADITIONAL OR A MAP?
SKIPA T1,[<.MCFV/PAGSIZ##>-.UMORG]
HRREI T1,<.UPMVP/PAGSIZ##>-SECTAB ;MAP, POINT TO SECTAB
SUB T2,T1 ;POINT TO CORRECT SLOT
JRST RTPT2
;ROUTINE TO REMOVE HIGH SEGMENT FROM USER'S LOGICAL ADDRESSING SPACE
;THIS IS CONTRANSTED WITH REMOVING A HIGH SEGMENT FROM PHYSICAL CORE
;WHICH THE SWAPPER DOES EVERY TIME A JOB WITH A HIGH SEG IS SWAPPED OUT (KCORE1)
;THE SEGMENT NUMBER ASSOCIATED WITH THE JOB IS ERASED (JBTSGN)
;IF NO OTHER JOB IS USING HIGH SEG IN CORE(IN CORE COUNT GOES TO 0)
; HIGH SEG IS NOT DELETED FROM CORE(UNLESS NOT SHARABLE) BUT RATHER BECOMES 'IDLE'.
; WHERE IDLE HAS SNA SET.
;IF NO OTHER JOB IS USING HIGH SEG IN LOGICAL ADR. SPACE, HIGH SEG IS
; NOT DELETED FROM CORE OR DISK(UNLESS NOT SHARABLE) BUT RATHER BECOMES 'DORMANT'.
; WHERE DORMANT HAS SNA TURNED OFF, BUT HAS CORE AND/OR DISK SPACE.
;RATHER IT BECOMES DORMANT(UNLESS IT NO LONGER HAS A NAME OR WAS NEVER SHARABLE)
;A DORMANT SEGMENT IS LEFT IN SYSTEM ACCORDING TO:
; A. SWAP SYS - LEFT ON BOTH SWAPPING DEVICE AND CORE
; B. NON-SWAP SYS - LEFT IN CORE
;DORMANT SEGMENTS HAVE JNA BIT OFF, HOWEVER THEY HAVE DISK SPACE AND/OR CORE
;DORMANT SEGMENTS ARE FLUSHED ONLY WHEN DISK OR CORE IS NEEDED
; OR HIGH SEGMENT NUMBERS ARE NEEDED
;KILHGH IS CALLED AT CLOCK AND UUO LEVELS BY:
;GET,R,RUN,LOGIN COMMANDS
;CORE 0 COMMAND
;CORE UUO(0 LESS-THAN LH LESS-THAN 400000)
;KJOB COMMAND AT UUO LEVEL
;REMAP UUO
;CALLER MUST INSURE THAT NEITHER LOW OR HIGH SEG ARE BEING SWAPPED
;CALL: MOVE J,JOB NUMBER
; MOVE R,LOW SEG RELOC. AND PROT.
; PUSHJ P,KILHGH
; OK RETURN - J,R RESTORED TO JOB (LOW SEG) RELOCATION
;ROUTINE TO REMOVE SEG FROM LOGICAL ADR. SPACE AND RESET HARDWARE RELOC
; KILHSH IS CALLED ONLY WHEN CALLER KNOWS THAT NO NEW HIGH SEG WILL
; TAKE THE PLACE OF THE ONE BEING REMOVED (SO LESS OVERHEAD).
;CALL: SAME AS KILHGH
;SUB TO REMOVE HIGH SEG - FROM LOG. ADR. SPACE AND CHANGE HARDWARE RELOC., THEN SKIP
KILHG1: AOS (P) ;HERE FROM CORE UUO (UCORHI) TO REMOVE HIGH SEG
; ALWAYS SKIP RETURN
KILHGS::
PUSHJ P,VERWAT## ;SEE IF WATCHING
SKIPA ;NO..PROCEED, DO NOT PRINT "]"
PUSHJ P,PRRBKC## ;YES - AND RIGHT BRACKET CRLF
;SUB TO REMOVE HIGH SEG FROM LOG. ADR. SPACE AND CHANGE HARDWARE RELOC
KILHSH::PUSHJ P,KILHGC ;REMOVE HIGH SEG FROM LOGICAL ADR. SPACE OF CURRENT JOB
PJRST SETMAP## ;THEN RESET HARDWARE RELOC. SO USER CANNOT REFERENCE
;SUB. TO REMOVE HIGH SEG FROM LOGICAL ADR. SPACE OF CURRENT JOB
KILHGC: MOVE J,.CPJOB## ;KILL HIGH SEG FOR CURRENT JOB(GETSEG,REMAP,CORE UUO)
KILHGH::PUSHJ P,SAVE1## ;SAVE P1
PUSH P,J ;SAVE JOB NUMBER
SKIPG J,JBTSGN##(J) ;DOES JOB HAVE A REAL HIGH SEG?
JRST KILFIN ;NO, ZERO HIGH SEG NUMBER FOR THIS JOB IN CASE SPY SEG
PUSHJ P,SEGSIZ## ;T2=SIZE OF HIGH SEG
PUSH P,T2 ;SAVE SIZE IN CASE NEED TO INCREASE AMOUNT
;OF FREE VERTICAL CORE LEFT.
SKIPN R,JBTADR##(J) ;YES, IS HIGH SEG ALSO IN CORE?
JRST SCNLOG ;NO, SCAN TO SEE IF OTHER USERS USING THIS HIGH SEG
; IN THEIR LOGICAL ADDRESSING SPACE
MOVE T1,-1(P) ;JOB NUMBER
PUSHJ P,DECCNT ;YES, DECREMENT HIGH SEG IN CORE COUNT FOR THIS JOB
; HIGH SEG IN-CORE COUNT TRANSITION TO 0?
JRST KILFN0 ;NO, JUST REMOVE HIGH SEG FROM THIS
; USER'S LOG. ADR SPACE
SCNLOG: MOVE T1,-1(P) ;RETRIEVE JOB NUMBER
PUSHJ P,DECSHR ;WE'RE NOT SHARING ANY MORE
JRST [TLNN J,SHRSEG ;IF NOT SHARABLE,
PUSHJ P,KCOREV## ;DELETE CORE IN CORE
JRST KILFN1] ;GO IF NOT LAST SHARER
IFN FTLOCK,<
PUSHJ P,UNLOCK## ;NO. UNLOCK IT
>
SKIPE JBTNAM##(J) ;NO, COULD NEW USER'S SHARE THIS HIGH SEG
; ON A GET IF WE LEFT IT ON SWAPPING SPACE?
JRST KILLP1 ;YES, DON'T DELETE IT
PUSHJ P,KCOREV## ;RETURN REAL PLUS VIRTUAL CORE
PUSHJ P,ZERSWP## ;DELETE DISK SPACE(IF ANY)
KILLP1: MOVSI T1,SNA ;FLAG HIGH SEG AS UNASSIGNED(OR DORMANT
; IF STILL IN
; CORE OR DISK).
ANDCAM T1,JBTSTS##(J)
MOVE T1,(P) ;SIZE IN K OF HIGH SEG WHICH IS BECOMING DORMANT
ADDM T1,VIRTAL## ; OR UNASSIGNED, INCREASE AMOUNT OF VIRTUAL CORE LEFT
; IN SYSTEM,(EVEN THOUGH CORE AND DISK SPACE
; MAYBE STILL USED)
JRST KILFN1 ;SKIP CALLS TO UNLOKH AND DECSHR
KILFN0: MOVE T1,-1(P) ;GET JOB NUMBER AGAIN
PUSHJ P,DECSHR ;WE'RE NO LONGER SHARING
CAIA ;CONTINUE IF NOT LAST SHARER
STOPCD .,STOP,SICDNA, ;++SHARE AND IN-CORE COUNTS DO NOT AGREE
IFN FTLOCK,<
PUSHJ P,UNLOKH## ;IF THE HIGH SEGMENT IS LOCKED, UNLOCK IT IF
; NO OTHER LOCKED LOW SEGMENT IS SHARING IT
>
KILFN1: MOVE J,-1(P) ;GET JOB NUMBER
MOVE J,JBTSGN##(J) ;GET SEGMENT NUMBER
MOVE T2,[NSWP,,ICCMSK]
TDNN T2,JBTSTS##(J) ;SEG IN USE OR STILL LOCKED?
SKIPN JBTADR##(J) ;NO, DOES IT STILL HAVE PHYSICAL CORE?
JRST KILFN2 ;DON'T ADJUST CORTAL IF LOCKED, SHARED,OR 0 CORE
TLNN J,SHRSEG ;NON-SHARABLE?
JRST KILFN2 ;YES
LDB T1,PCORSZ## ;SIZE OF SEGMENT IN K
AOS T1 ;ROUND UP
ADDM T1,CORTAL## ;INCREASE TOTAL FREE+DORMANT+IDLE CORE
PUSHJ P,INDISQ ; JUST WENT IDLE, INSERT IN QUEUE
KILFN2: PUSHJ P,CHKTAL ;CHECK CORTAL AGAINST CORTAB, HALT IF BAD
POP P,T1 ;REMOVE SIZE OF SEG IN K
KILFIN: POP P,J ;RESTORE JOB NUMBER
HRRZ T4,JBTUPM##(J) ;NO HI SEG TO REMOVE IF NO MAP
SKIPE T4
PUSHJ P,REMHGH## ;REMOVE THE HIGH SEGMENT FROM THE PAGE MAP
SETZM JBTSGN##(J) ;REMOVE HIGH SEG FROM THIS USER'S LOGICAL ADR. SPACE
SKIPN R,JBTADR##(J) ;RESTORE LOW SEG RELOC AND PRTECTION
POPJ P, ;IF NONE, RETURN
HLRZ P1,JBTADR##(J) ;GET LOW-SEG END
CAME J,.CPJOB## ;CURRENT JOB?
PUSHJ P,SVEUB## ;NO, MAKE SURE ITS ADDRESSABLE
HRRZ T1,.JDAT+JOBSA## ;GET START ADDRESS
CAMLE T1,P1 ;SEE IF LOW SEG
HLLZS .JDAT+JOBSA## ;NO - CLEAR IT
HRRZ T1,.JDAT+JOBREN## ;GET REENTER ADDRESS
CAMLE T1,P1 ;SEE IF LOW SEG
HLLZS .JDAT+JOBREN## ;NO - CLEAR IT
HRRZS .JDAT+JOBHRL## ;CLEAR OUT SIZE OF HIGH SEG AS SET BY LOADER
; SO USER'S CAN TEST FOR HIGH SEG BY SKIPN JOBHRL
SETZB T1,.USHSE ;NO HIGH SEGMENT NOW
DPB T1,HIVSIZ## ;HIGH SEG SIZE IS NOW 0
DPB T1,JBYSG2## ;AND NO LEFTOVER SECTION #S
POPJ P, ;RETURN
;ROUTINE TO CLEAR A HIGH SEGMENT NAME SO NO NEW USERS CAN SHARE
;AND RETURN BOTH DISK AND CORE SPACE (IF ANY) IF HIGH SEG WAS DORMANT(SNA=0)
;IE NO LONGER IN ANY USER'S VIRTUAL ADR. SPACE
;CALL: MOVE J, HIGH SEG NUMBER
; PUSHJ P, CLRNAM
; RETURN J AND R PRESERVED
;CALLED FROM FRESWP,FRECOR,FNDSGN (UREMAP,UCORHI), ASGHGH,RELSEG
CLRNAM::SETZM JBTDEV##(J) ;CLEAR DEVICE NAME OR STR NAME
TDZA T2,T2 ;ZERO THE PPN
CLRNM1: MOVE T2,JBTPPN##(J) ;PERPETUATE THE CROCK WHICH ALLOWS SYSTAT TO
EXCH T2,JBTPPN##(J) ; REPORT THE PPN WHICH AN OBSOLETED SEGMENT CAME FROM
SKIPE T2
TLNE T2,-1 ;POINTER TO A PATH?
JRST CLRNM2 ;NO
MOVEI T1,MAXLVL##+2 ;YES, RETURN PATH BLOCK TO MONITOR FREE CORE
PUSHJ P,GIVWDS##
SETZM JBTPPN##(J) ;AND ZERO THE PATH POINTER
CLRNM2: SETZM JBTNAM##(J) ;AND SEG NAME SO NEW USER'S CAN USE
; CLRNM2 CALLED PQOM ASGHGH AND RELSEG
; WHEN FILE SUPERCEDED, BUT LEAVE DIR
; NAME FOR SYSTAT TO PRINT (OBS)
SKIPGE JBTSTS##(J) ;IS SEG DORMANT(IE NOT IN ANY USER'S VIRTUAL
; ADR. SPACE)?
POPJ P, ;NO,(SNA=1) ALLOW USER'S TO CONTINUE TO SHARE
; UNTIL FINISHED, HOWEVER NO NEW USERS CAN
; SHARE SINCE NO LONGER A NAME
HRRZ T1,JBTSHR##(J) ;GET SHARER COUNT TO CHECK
SKIPE T1 ;DOES IT AGREE?
STOPCD .,STOP,SNASHR, ;++SNA/JBTSHR DISCREPENCY (NO)
PUSHJ P,ZERSWP## ;YES, RETURN DISK SPACE, IF ANY
;FALL INTO ROUTINE TO KILL DORMANT CORE
;ROUTINE TO RETURN DORMANT OR IDLE CORE (IF ANY)
;CALL: MOVE J, HIGH SEG NUMBER
; PUSHJ P,KDORCR
; RETURN J,R PRESERVED
;CALLED FROM CLRNAM AND FRECOR
KDORCR: PUSH P,R ;SAVE R(EITHER HIGH OR LOW RELOC)
PUSH P,CORTAL## ;SAVE FREE CORE COUNT
PUSH P,LOKTAL##
SKIPE R,JBTADR##(J) ;DOES DORMANT SEG HAVE CORE?
PUSHJ P,KCOREH ;YES, RETURN PHYSICAL COREAND FLAG HIGH SEG
; AS ON DISK IF IT HAS DISK SPACE(SET SWP=1)
POP P,LOKTAL##
POP P,CORTAL## ;RESTORE FREE CORE COUNT, SINCE DORMANT
; SEGS ALREADY INCLUDED IN CORTAL
PUSHJ P,CHKTAL ;CHECK CORTAL WITH CORTAB, HALT IF BAD
POP P,R ;RESTORE R
POPJ P, ;RETURN
;ROUTINE TO RETURN HIGH SEGMENT CORE(MUST BE SOME) AND FLAG SEG AS ON DISK
; IF HIGH SEG HAS DISK SPACE(IE SET SWP=1 IF JBTIMO NON-ZERO)
;CALL: MOVE J,HIGH SEG NUMBER
; MOVE R,HIGH SEG RELOC AND PROTECTION
; PUSHJ P,KCOREH
;CALLED FROM KDORCR(FRECOR,CLRNAM,KILHGH) AND FORHGH
KCOREH::PUSHJ P,DLDISQ ; SEG NOT IN CORE ANY MORE
LDB T1,IMGOUT## ;DOES HIGH SEG HAVE DISK SPACE?
JUMPE T1,KCORE1## ;NO, RETURN CORE
MOVSI T1,SWP ;YES, FLAG HIGH SEG AS SWAPPED OUT
IORM T1,JBTSTS##(J) ;SET SWP=1
JRST KCORE1## ;THEN RETURN CORE
;CORE UUO ROUTINE TO ASSIGN OR REASSIGN CORE FOR HIGH SEG
;CALLED AFTER LOW SEG SEG IS REASSIGNED IF USER HAS NON-ZERO RH IN AC
;CALL: HRRZ T1,DESCRED HIGHEST USER ADR. IN HIGH SEG
; MOVE J, JOB NUMBER
; PUSHJ P,UCORHI
; ERROR RETURN - SUM OF SEGMENTS EXCEED MAX. PHYSICAL CORE OR
; EXCEED TOTAL SYSTEM VIRTUAL CORE CAPACITY
; SHARABLE PROGRAM MEDDLED WITH(AND NO WRITE PRIV.)
; OR HIGH SEG IS SPY SEG
; OK RETURN - CORE ASSIGNED(MAYBE NOT IN MEMORY) OR USER ASKED NO CHANGE(LH=0)
; J AND R RESTORED TO LOW SEG NO AND RELOC
;IF LH IS NON-ZERO BUT LESS THAN 400000 OR END OF LOW SEG(IF GREATER THAN 400000)
;THE HIGH SEGMENT WILL BE REMOVED FROM USERS LOGICAL ADDRESSING SPACE
UCORHI::JUMPE T1,CPOPJ1## ;ASKING FOR ANY CHANGE?
MOVE T3,T1 ;SAVE THE USER'S ARGUMENT
PUSHJ P,HSVAD ;GET ORIGIN AND LENGTH OF THE HIGH SEGMENT
CAMGE T3,T2 ;IF NEW HIGHEST ADDRESS .LT.ORIGIN,
JRST KILHG1 ; REMOVE THE HIGH SEGMENT
SKIPN T1 ;CREATING A HIGH SEGMENT?
MOVE T1,T2 ;YES, HIGHEST ADDRESS EQUALS ORIGIN
EXCH T1,T3 ;SETUP ARGS FOR CKNZ1
EXCH T2,T3 ; ..
IORI T1,PG.BDY## ;ROUND UP TO A PAGE BOUNDRY
PUSHJ P,CKNZ1## ;WILL HI SEG OVERLAP LOW SEG?
POPJ P, ;YES, LOSE
SUB T1,T3 ;NEW LENGTH OF THE HIGH SEG
PUSH P,T1 ;SAVE THAT
LSH T3,W2PLSH## ;HIGH SEG ORIGIN PAGE
PUSH P,T3 ;SAVE THAT
IFN FTLOCK,< ;LOCK UUO FEATURE?
PUSHJ P,LOKCHK## ;IS JOB LOCKED?
JRST UCORHE ;YES, ERROR RETURN-CANNOT CHANGE SIZE
>
SKIPGE J,JBTSGN##(J) ;GET HIGH SEG NUMBER(IF ANY),SPY SEG?
JRST UCORHE ;YES, GIVE ERROR RETURN TO USER
PUSHJ P,CHKHWC ;NO, SEE IF CURRENT JOB HAS NOT BEEN MEDDLING OR
; HAS UPDATE PRIVILEGES IF HAS MEDDLED WITH HIGH SEG
JRST UCORHE ;NO, ERROR RETURN TO USER
SKIPN J ;YES, DOES JOB HAVE A HIGH SEG YET?
; OR IS THIS FIRST ASSIGNMENT OF CORE TO HIGH SEG
PUSHJ P,FNDSGN ;NO, FIND FREE SEG NUMBER BEFORE ASSIGNING CORE
POP P,T1 ;HIGH SEGMENT ORIGIN
DPB T1,JBYHSO## ;STORE IT FOR POSTERITY
LSH T1,P2WLSH## ;HI SEG ADDR
MOVEM T1,.USHSS ;STORE THAT
PUSHJ P,ZERSWP## ;RETURN SWAPPING SPACE, IF ANY (NULL JOB NEVER HAS
; SINCE NEW SIZE MAY BE DIFFERENT FROM OLD SIZE
; SO IT SHOULD BE WRITTEN NEXT SWAPOUT
; EVEN IF WRITE PROTECTED.
MOVE T1,(P) ;CORE ARGUMENT
;HERE TO MAKE SURE THAT ALLOWING THIS HIGH SEGMENT EXPANSION WILL NOT KEEP
; OTHER JOBS SHARING IT FROM BEING ABLE TO BE RUN (SWAPPED IN)
HLRZ T2,JBTADR##(J) ;CURRENT SIZE OF THE HIGH SEGMENT
CAIG T2,(T1) ;ALWAYS OK TO GET SMALLER
TLNN J,SHRSEG ;ALWAYS OK TO MAKE A NON-SHARABLE SEGMENT BIGGER
JRST UCORH4 ;OK TO DO THE CORE UUO
PUSH P,P1
MOVSI P1,PHONLY ;CHECK PHYSICAL LIMITS
PUSH P,J ;SAVE THE HIGH SEGMENT NUMBER
MOVE J,HIGHJB## ;HIGHEST JOB NUMBER ASSIGNED
UCORH2: HRRZ T2,JBTSGN##(J) ;THIS JOB'S HIGH SEGMENT NUMBER
SKIPLE JBTSGN##(J) ;A REAL HIGH SEGMENT?
CAIE T2,@(P) ;EQUAL TO THE SEGMENT NUMBER OF THE EXPANDING SEG?
JRST UCORH3 ;NO
PUSHJ P,CORBND## ;AMOUNT OF CORE THIS JOB IS ALLOWED
PUSHJ P,SEGSIZ## ;CURRENT SIZE OF THE LOW SEGMENT
LSH T2,P2WLSH##
ADD T2,-2(P) ;SIZE JOB WILL BE IF HI SEG EXPANDS
SUBI T2,UPMSZW## ;CORBND DOESN'T COUNT UPMP SIZE
CAMLE T2,T1 ;WILL THIS JOB STILL FIT?
JRST [POP P,J ;NO, LOSE
POP P,P1
JRST UCRHE0]
UCORH3: SOJG J,UCORH2 ;LOOK AT ALL JOBS SHARING THIS SEGMENT
POP P,J ;RESTORE THE HIGH SEGMENT NUMBER
POP P,P1 ;RESTORE USERS P.O. BITS
UCORH4: POP P,T1 ;RESTORE AMOUNT OF CORE REQUEST
MOVSI R,SHRSEG ;THIS A SHARABLE HIGH SEG?
TDNE R,JBTSTS##(J) ;(ONLY NEED SCDLOK FORR SHARABLE)
CPLOCK (SCD)
MOVE R,JBTADR##(J) ;R TO PREVIOUS HIGH SEG CORE ASSIGNMENT(IF ANY)
;DON'T ALLOW CPU1 TO RUN THIS SEGMENT
;WHILE CORE SIZE IS CHANGING
PUSHJ P,CORE0## ;TRY TO ASSIGN CORE TO HIGH SEG(ON DISK OR MEMORY)
JRST [MOVSI T1,SHRSEG
TDNE T1,JBTSTS##(J)
CPUNLK (SCD)
JRST UCRHE1]
;ERROR, CORE REQUEST TOO BIG, IF NO ONE IS USING
; (INCLUDING THIS USER) LEAVE SEG NON-EXISTENT,
; OTHERWISE DORMANT OR STILL IN USE BY THIS AND/OR
; OTHER USERS
MOVSI T1,SHRSEG
TDNE T1,JBTSTS##(J)
CPUNLK (SCD)
MOVSI T1,SWP ;IF THIS IS A HIGH SEGMENT WHICH WAS CREATED
SKIPN JBTADR##(J) ; BY THIS CORE UUO, CORE MAY BE ASSIGNED ON DISK
IORM T1,JBTSTS##(J) ;IT WAS - MARK THE HIGH SEGMENT AS SWAPPED
; SHARE1 WILL MARK THE LOW SEGMENT
SJSP T3,SHARE1 ;OK RETURN, MARK USER AS HAVING THIS HIGH SEG IN LOG.
; ADR. SPACE(IN CASE IT WAS NOT BEFORE)
; SET RELOC AND SKIP RETURN
; AND INCREMENT HIGH SEG IN CORE CONT FOR THIS JOB
; IF NOT ALREADY DONE SO.
; FLAG (T3) NOT TO CHECK FOR CONNECTING TO IDLE
; HI-SEG SINCE IT CANNOT BE (BUT LOOKS IDLE)
UCORHE: POP P,T1 ;POP OFF JUNK
UCRHE0: POP P,T1 ;RESTORE PDL
UCRHE1: JRST SETMAP## ;AND SETUP HARDWARE, SET R TO LOW SEG
; RELOC, J TO CURRENT JOB, AND ERROR RETURN
;UUO TO REMAP TOP PART OF LOW SEGMENT INTO HIGH SEGMENT
;PREVIOUS HIGH SEGMENT(IF IT EXISTED) IS REMOVED FROM LOGICAL ADDRESSING SPACE
;CALL: MOVE T1,HIGHEST DESIRED REL. ADR. IN NEW LOW SEG.
; (EXEC ORES IN 1777 TO MAKE EVEN 1K-1)
; MOVE R,XWD PROTECTION,RELOCATION FOR LOW SEGMENT
; PUSHJ P,UREMAP
; ERROR RETURN - DESIRED HIGHEST REL. ADR PAST END OF LOW SEG
; ;OR 1 REGISTER MACHINE
; OK RETURN - HARDWARE AND SOFTWARE RELOCATION INFO RESET
; J RESET TO CURRENT JOB NUMBER, AND R TO RELOC
;MUST BE CALLED AT UUO LEVEL ONLY
UREMAP::SETZM .JDAT+SGAEXT## ;SO NEW HGH CAN TELL SHR FROM HGH
MOVSI T2,(UP.GET)
ANDCAM T2,.USBTS ;GET NO LONGER IN PROGRESS
UREMA0: MOVSI T2,NSWP!NSHF
TDNE T2,JBTSTS##(J) ;LOCKED?
POPJ P, ;YES, ERROR RETURN
IORI T1,PG.BDY## ;MAKE AN EVEN MULTIPLE OF 1K-1
PUSH P,T1 ;YES, SAVE DESIRED HIGHEST ADR OF NEW LOW SEG
HRRZS T1 ;CLEAR POSSIBLE HIGH SEGMENT ORIGIN
CAMLE T1,.CPREL## ;YES, IS NEW TOP OF LOW SEG LESS THAN OR EQUAL TO OLD?
JRST TPOPJ## ;NO, ERROR RETURN - 1 REG MACHINE OR ARG TOO BIG
PUSH P,F ;SAVE F (IOWAIT CHANGED IT)
PUSHJ P,IOWAIT## ;WAIT FOR IO TO STOP IN LOW SEG
POP P,F ;RESTORE F
IFN FTMP,<
PUSHJ P,UPMM## ;MUST OWN THE MM RESOURCE TO DO A REMAP
>
HRRZ T2,(P) ;RESTORE DESIRED HIGHEST ADR IN NEW LOW SEG
SKIPE T1,.USREL ;IF NON-ZERO, PREVIOUS HIGHEST ADR IN LOW SEG
JRST UREMA2 ;DON'T CHANGE JBTADR
HLRZ T1,JBTADR##(J) ;GET PREVIOUS HIGHEST ADR OF LOW SEG
HRLM T2,JBTADR##(J) ;STORE NEW(LESS THAN OR EQUAL) HIGHEST ADR OF LOW SEG
UREMA2: SUBI T1,1(T2) ;COMPUTE LENGTH-1 OF NEW HIGH SEG
JUMPL T1,UREMA3 ;-1 MEANS NEW LOW SEG=OLD LOW SEG
; RESET HARDWARE BECAUSE NO HIGH SEG ANY MORE
; FOR SURE, SET RELOC. HARD. AND SKIP RETURN
ADD T2,JBTADR##(J) ;ADD ABS. ADR. OF LOW SEG TO LENGTH-1 OF LOW SEG
;TO FORM LENGTH-1 OF NEW HIGH SEG
HRLI T1,1(T2) ;MOVE ABS ADR. OF NEW HIGH SEG TO LH
POP P,T2 ;RESTORE USER'S ARGUMENT (NEWHGH WILL
; PUT THE HIGH SEGMENT AT THE LEFT HALF
HRRZ T4,T2 ;SAVE WHERE,,NEW LOW SEGMENT SIZE
HLRZS T2 ;WHERE TO PUT THE HIGH SEGMENT
ANDI T2,777000 ;MAKE SURE ITS ON A PAGE BOUNDARY
JUMPN T2,UREMA1 ;JUMP IF HIGH SEGMENT STARTING ADDRESS SPECIFIED
TRNE T4,400000 ;IS THE LOW SEGMENT BIGGER THAN 128K?
SKIPA T2,T4 ;YES, HIGH SEGMENT ORIGIN IS FIRST PAGE ABOVE
; THE LOW SEGMENT
MOVEI T2,377777 ;NO, HIGH SEGMENT GOES AT 400000
MOVEI T2,1(T2) ;HIGH SEGMENT ORIGIN (ALSO CLEAR LEFT HALF OF T2)
UREMA1: MOVE T3,.CPJOB## ;CURRENT JOB NUMBER
MOVEM R,JBTADR##(T3) ;STORE PREVIOUS PROTECTION,,JDAT IN CASE OF ERROR
MOVEI T3,1(T1) ;NUMBER OF WORDS IN NEW HIGH SEGMENT
MOVEI T1,1(T4) ;ADDRESS WHERE REMAP STARTS
LSHC T1,W2PLSH## ;T1=FROM PAGE, T2=TO PAGE
LSH T3,W2PLSH## ;NUMBER OF PAGES
HLRZ T4,.JDAT+SGAEXT## ;FILE EXTENSION
CAIN T4,'SHR' ;SHARABLE?
TDZA T4,T4 ;YES
MOVSI T4,(1B0) ;INDICATE NON-SHARABLE TO NREMAP
PUSHJ P,NREMAP## ;REMAP IT
JRST UREMA4 ;HIGH SEGMENT WOULD OVERLAP THE LOW SEGMENT
MOVSM T1,JBTADR##(J) ;STORE LENGTH-1 AND ABS. ADR. OF NEW HIGH SEG
SJSP T3,SHARE1 ;SET IN CORE COUNT TO 1, FLAG THIS SEG IN CURRENT
; JOB'S LOG. ADR. SPACE, AND FLAG HIGH SEG NO.
; AS ASSIGNED(SNA=1)
; RESET HARD. AND SOFT. RELOC, AND SKIP RETURN
; (SET FLAG(T3) SO NOT CHECK FOR CONNECTING TO
; IDLE HI-SEG SINCE IT CANNOT BE IDLE, BUT
; IT WILL LOOK LIKE IT IS.)
UREMA4: SOSA (P) ;SETRL1 DOES AOS (P), SO FORCE ERROR RETURN
UREMA3: POP P,T1 ;POP OFF JUNK & GIVE GOOD RETURN
;FOR UNCHANGED LOW SEG (DISCARD HISEG)
IFN FTMP,<
PUSHJ P,TGVMM## ;GIVE UP THE MM IF OWNED
>
JRST SETRL1 ;REDO PROTECTION-RELOCATION AND GIVE ERROR RETURN
;ROUTINE TO FIND A FREE SEG NUMBER FOR A NEW HIGH SEGMENT FOR CURRENT JOB
;CALLED BY CORE UUO AND REMAP UUO(MUST BE CALLED AT UUO LEVEL ONLY)
;TRIES TO FIND A FREE SEGMENT WITHOUT DORMANT COPY ON DISK OR CORE
;IF NONE, IT FINDS A SEG WHICH IS DORMANT ON DISK AND/OR CORE
; DELETES UNUSED DISK AND CORE AND REUSES THAT HIGH SEG NUMBER
;(A SEGMENT CANNOT BE DORMANT ON DISK AND USED IN CORE OR VICE VERSA)
;NEW HIGH SEG IS FLAGGED AS NON-SHARABLE(SHRSEG=0 IN JBTSTS FOR HIGH SEG)
;IN CORE COUNT IS SET TO 0
;CALL: PUSHJ P,FNDSGN
; RETURN WITH J SET TO FREE SEG NUMBER
;HOWEVER CURENT JOB IS NOT MARKED AS HAVING THIS SEG IN LOGICAL ADR SPACE
; SINCE THER MAY NOT BE ENOUGH CORE FOR SEGMENT. THE CALLER MUST FLAG USER
; AS HAVEING THIS SEG IN ADDRESSING SPACE IF EVERYTHING OK
;THE LH OF J IS SET TO 0(SHRSEG=MEDDLE=UWPOFF=SPYSEG=0)
;THE CALLER MUST ALSO FLAG HIGH SEG AS ASSIGNED(SNA=1) IF EVERYTHING OK
;T1 IS PRESERVED, T2 IS USED
FNDSGN::PUSH P,T1 ;SAVE T1(HIGHEST REL. ADR. DESIRED
;IN CALLS TO CORE AND REMAP)
FND0: MOVE J,SEGPTR## ;SCAN JUST HIGH SEGMENTS(NOT JOBS)
MOVEI T2,OUTMSK## ;MASK FOR DISK IMAGE BYTE POINTER
FND1: SKIPL JBTSTS##(J) ;SEG NUMBER ASSIGNED(SNA=1)?
SKIPE JBTADR##(J) ;NO, DOES HIGH SEG STILL HAVE CORE ANYWAY?
JRST FND1A ;YES, KEEP LOOKING
TDNE T2,JBTIMO##(J) ;NO, DOES IT HAVE DISK SPACE?
FND1A: AOBJN J,FND1 ;YES, KEEP LOOKING, MORE TO GO?
JUMPL J,FNDOK ;NO, WAS A FREE SEG NUMBER FOUND WITH NO CORE ASSIGNED?
MOVEI T2,SEGN## ;NO. OF HIGH SEGMENTS IN SYSTEM
AOS J,SEGPT1## ;START AT SEGMENT AFTER LAST DORMANT SEG
FND2: CAILE J,JBTMAX## ;STILL LESS THAN OR EQUAL TO MAX SEG NO.?
HRRZ J,SEGPTR## ;NO, START OVER AT FIRST HIGH SEG
SKIPL T1,JBTSTS##(J) ;IS THIS HIGH SEG NO. ASSIGNED (SNA=1)?
JRST FNDOK1 ;NO, FOUND A DORMANT SEG?
FND3: ADDI J,1 ;NO, LOOK AT NEXT ONE
SOJG T2,FND2 ;LOOKED AT ALL SEG?
MOVEI T1,1 ;THE ONLY DORMANT SEGMENTS FOUND WERE
; IN THE PROCESS OF BEING SWAPPED OUT.
IFN FTMP,<
PUSHJ P,DIFMM## ;GIVE UP MM IF OWNED
>
PUSHJ P,SLEEPF## ;SO WAIT UNTIL SWAPOUT COMPLETES
IFN FTMP,<
PUSHJ P,UIFMM## ;GET BACK MM IF IT WAS OWNED
>
JRST FND0 ;TRY AGAIN
FNDOK1: TLNE T1,NSHF ;SWAP OUT OF THIS SEGMENT IN PROGRESS?
JRST FND3 ;YES, SKIP IT FOR NOW
MOVEM J,SEGPT1## ;REMEMBER LAST DORMANT SEGMENT FOUND FOR NEXT TIME
; SO WILL THROW AWAY OLDEST DORMANT SEG
FNDOK: TLZ J,777777 ;TURN OFF MEDDLE,SHRSEG,UWPOFF,SPYSEG,CORCNT)
PUSHJ P,CLRNAM ;CLEAR HIGH SEG NAME SO NO LONGER
; SHARABLE TO NEW USERS, DELETE DISK AND CORE(IF ANY)
SETZM JBTSTS##(J) ;CLEAR ALL BITS AND IN CORE COUNTS JUST FOR GOOD
; MEASURE(SHRSEG!SERR COULD BE STILL ON FOR HIGH SEG)
JRST TPOPJ## ;RESTORE T1 AND RETURN
;SUBROUTINE TO FREE UP CORE IN CORE BY DELETING DORMANT OR IDLE
; SEGMENTS WHICH HAVE DISK COPIES
;ENTER WITH T3= NUMBER OF PAGES REQUIRED
;EXIT CPOPJ IF NOT ENOUGH PAGES CAN BE MADE AVAILABLE,
; EXIT CPOPJ1 IF ENOUGH CORE HAS BEEN FREED
;PRESERVES ALL ACS
FRDCR:: CAMG T3,BIGHOL## ;THAT MUCH AVAILABLE ALREADY?
JRST CPOPJ1## ;YES, RETURN GOODNESS
PUSHJ P,FRPCR## ;CAN ENOUGH BE FREED BY ALLOCATING FROM "OUT" QUEUE
CAIA ;NO, TRY DELETING DORMANT SEGMENTS
JRST CPOPJ1## ;YES, GOODNESS
CAMLE T3,CORTAL## ;CAN ENOUGH CORE BE FREED?
POPJ P, ;NO
CAMG T3,BIGHOL## ;THAT MUCH ALREADY AVAILABLE?
JRST CPOPJ1## ;YES, RETURN GOODNESS
IFN FTXMON,<
PUSHJ P,SSEC0## ;MUST RUN IN SECTION 0
>
PUSHJ P,SAVT## ;SAVE T1-T4
PUSH P,J ;SAVE J
MOVNI J,DISQ## ; HEADER FOR DORMANT/IDLE SEGMENTS
HRRE J,JBTDIQ##(J) ; GET FIRST ENTRY IN QUEUE (OLDEST)
FRDCR1: MOVEI T1,ICCMSK ;IN CORE COUNT MASK
HRLI T1,NSHF!NSWP ;LOOK FOR DORMANT OR IDLE UNLOCKED SEGMENTS
MOVE T3,-4(P) ;AMOUNT OF CORE REQUIRED
CAMG T3,BIGHOL## ;IS THAT MUCH AVAILABLE
JRST JPOPJ1## ;YES, RESTORE J AND GIVE CORE AVAILABLE RETURN
FRDCR2: JUMPLE J,JPOPJ## ; ANY MORE SEGS IN QUEUE?
HRRE T2,JBTDIQ##(J) ; YES. GET SUCCESSOR
MOVEM T2,NXTSEG ; SAVE IN CASE DELETE ENTRY
SKIPE JBTADR##(J) ;SEGMENT IN CORE?
TDNE T1,JBTSTS##(J) ;UNLOCKED AND DORMANT OR IDLE?
JRST FRDCR3 ;NO
LDB T2,IMGOUT## ;DOES IT HAVE A DISK COPY?
JUMPE T2,FRDCR3 ;NO, CONTINUE LOOKING
SKIPN T2,FIT## ; FITTING SOMEONE?
MOVE T2,FINISH## ; OR ACTUALLY SWAPPING HIM IN?
JUMPLE T2,FRDCR4 ; NO
CAIG T2,JOBMAX ; YES. A LOW SEG?
SKIPG T2,JBTSGN##(T2) ; YES. HAVE REAL HISEG?
JRST FRDCR4 ; NO
HRRZ T2,T2 ; YES. JUST HIGHSEG NUMBER
CAIN T2,(J) ; THIS THE SEG HE WILL USE?
JRST FRDCR3 ; YES. DON'T DELETE IT
FRDCR4: MOVE T2,UPTIME## ;SYSTEM UPTIME
SUB T2,JBTIDT##(J) ;MINUS TIME WENT IDLE/DORMANT
CAMG T2,SGTLIM## ; LESS THAN LIMIT?
JRST FRDCR3 ;YES. DON'T DELETE IT
PUSH P,NXTSEG ; SAVE THE SUCCESSOR
PUSHJ P,KDORCR ;DELETE THE DORMANT OR IDLE SEGMENT FROM CORE
POP P,J ; RESTORE NEXT QUEUE ENTRY
JRST FRDCR1 ;SEE IF ENOUGH CORE IS AVAILABLE NOW
FRDCR3: SKIPLE J,NXTSEG ; GET NEXT QUEUE ENTRY, IF ANY
JRST FRDCR2 ; THEIR IS, KEEP GOING
JRST JPOPJ## ;SOME OF THE DORMANT SEGMENTS DON'T HAVE A DISK COPY
; RESTORE S AND GIVE CORE NOT AVAILABLE RETURN
;SUBROUTINE TO TRY AND ALLOCATE SUFFICIENT CORE FOR
;A JOB LIKE FRDCR, BUT WILL WAIT TO DUMP THE IN QUEUE
;IF ENOUGH CAN BE ALLOCATED THAT WAY
FRDCRW::
PUSHJ P,FRDCR ;SEE IF CAN GET THE USUAL WAY
CAIA ;NO, WAIT
JRST CPOPJ1## ;RETURN GOODNESS
PUSHJ P,SAVT## ;SAVE TS
PUSH P,U ;AND U
PUSH P,F ;F
FRDCW1: MOVE T1,CORTAL## ;MAX AMOUNT AVAILABLE HERE
ADD T1,PAGOUC## ;# ON OUT QUEUE
ADD T1,PAGIPQ## ;# ON IP QUEUE
ADD T1,PAGSNC## ;# ON SLOW QUEUE
ADD T1,PAGINC## ;AND FAST IN QUEUE
CAIL T3,(T1) ;IS THERE ENOUGH WITH ALL CONSIDERED?
JRST FUPOPJ## ;CAN'T ALLOCATE EVEN IF WE DUMP THE QUEUE
PUSH P,S ;SAVE S (FOR FILSER)
PUSHJ P,PAGQWT ;START I/O AND WAIT UNTIL I/O COMPLETES
POP P,S ;RESTORE S (FOR FILSER)
MOVE T3,-5(P) ;RESTORE T3
PUSHJ P,FRDCR ;NOW IS THERE ENOUGH?
JRST FRDCW1 ;STILL NO, CHECK QUEUES AGAIN
;(IN CASE, EG, PAGIPQ WAS BUSY)
JRST FUPOJ1## ;RETURN GOODNESS
PAGQWT: PUSHJ P,SSEC0## ;DO THIS IN S0
PUSHJ P,SAVJW## ;SAVE J & W
MOVE J,.CPJOB## ;BE SURE J IS RELIABLE
PUSHJ P,BMSLST## ;BUILD THE LIST
IFN FTMP,<
PUSHJ P,REMMM## ;REMEMBER STATE OF MM
>
PUSHJ P,IOWAIT## ;WAIT FOR I/O TO STOP
PUSHJ P,ZERIPT## ;GIVE UP ICPT
MOVEI T1,PQIOQ## ;PUT IN PAGING QUEUE WAIT
DPB T1,PJBSTS## ;PUT THERE
PJRST WSCHED## ;WAIT
$LOW ;
NXTSEG: 0 ; NEXT SEGMENT IN QUEUE
$HIGH ;
;ROUTINE TO INCREMENT HIGH SEG SHARE COUNT (ONCE)
; FOR A JOB WHICH HAS A REAL HIGH SEG
;CALL: MOVE J,XWD JOB HIGH SEG BITS, HIGH SEG NUMBER
; MOVE T1,JOB NUMBER
; PUSHJ P,INCSHR
; ALWAYS RETURN WITH C(J)=JBTSGN(T1)
;SHRCNT IS SET TO 1 TO FLAG THIS JOB AS HAVING INCREMENTED SHARE COUNT
;CALLED FROM SHARE1
INCSHR: TLON J,SHRCNT ;HAS HIGH SEG SHARE COUNT ALREADY BEEN
AOS JBTSHR##(J) ; INCREMENTED FOR THIS JOB?
;NO, INCREMENT HIGH SEG SHARE COUNT
PUSHJ P,COMIT ;COMPARE J WITH JBTSGN(T1)
MOVEM J,JBTSGN##(T1) ;STORE SHRCNT FLAG FOR THIS JOB
POPJ P, ;AND RETURN
;ROUTINE TO DECREMENT HIGH SEG SHARE COUNT (ONCE)
; FOR A JOB WHICH HAS A REAL HIGH SEG
;CALL: MOVE J XWD JOB HIGH SEG BITS, HIGH SEG NUMBER
; MOVE T1, JOB NUMBER
; PUSHJ P,DECSHR
; RET1 SHARE COUNT NOT YET 0 OR SHARE COUNT NOT UP FOR THIS JOB
; RET2 SHARE COUNT WENT TO 0
;CALLED FROM KILHGH
DECSHR: PUSHJ P,COMIT ;COMPARE J WITH JBTSGN(T1)
TLZN J,SHRCNT ;HAS HIGH SEG SHARE COUNT ALREADY BEEN
;DECREMENTED FOR THIS JOB?
POPJ P, ;YES, RETURN
SOS JBTSHR##(J) ;NO, DECREMENT HIGH SEG SHARE COUNT
MOVEM J,JBTSGN##(T1) ;CLEAR SHRCNT FLAG IN MEMORY FOR THIS JOB
DCSERR: HRRE T1,JBTSHR##(J) ;GET HIGH SEG SHARE COUNT
JUMPE T1,DCSDID ;IF WENT TO ZERO, CHECK DORMANT/IDLE AND SKIP RETURN
SKIPL T1 ;NO, NEGATIVE?
POPJ P, ;NO
AOS JBTSHR##(J) ;NO, ERROR ADD BACK TO 0
STOPCD DCSERR,DEBUG,SSCNEG, ;++SEGMENT SHARE COUNT NEGATIVE
DCSDID: SKIPE JBTDIQ##(J) ;IS SEGMENT ALREADY IN QUEUE?
JRST CPOPJ1## ;YES, WE'RE DONE, JUST GIVE SKIP RETURN
PJRST DECDID ;NO, INSERT IT AND THEN SKIP RETURN
;ROUTINE TO INCREMENT HIGH SEG IN CORE COUNT (ONCE)
; FOR A JOB WHICH HAS A REAL HIGH SEG WHICH MUST BE IN CORE
;CALL: MOVE J,XWD JOB HIGH SEG BITS, HIGH SEG NUMBER
; MOVE T1,JOB NUMBER
; PUSHJ P,INCCNT
; ALWAYS RETURN WITH C(J)=JBTSGN(T1)
;CORCNT IS SET TO 1 TO FLAG THIS JOB AS HAVING INCREMENTED IN CORE COUNT
;CALLED FROM SHARES(GET,REMAP,CORE) AND FININ
INCCNT: TLON J,CORCNT ;HAS HIGH SEG IN CORE COUNT ALREADY BEEN
AOS JBTSTS##(J) ; INCREMENTED FOR THIS JOB?
;NO, INCREMENT HIGH SEG IN CORE COUNT
PUSHJ P,COMIT ;COMPARE J WITH JBTSGN(T1)
MOVEM J,JBTSGN##(T1) ;STORE CORCNT FLAG FOR THIS JOB?
PJRST DLDISQ ; NOT DORMANT/IDLE NOW
;ROUTINE TO DECREMENT HIGH SEG IN CORE COUNT (ONCE)
; FOR A JOB WHICH HAS A REAL HIGH SEG WHICH MUST BE IN CORE
;CALL: MOVE J XWD JOB HIGH SEG BITS, HIGH SEG NUMBER
; MOVE T1, JOB NUMBER
; PUSHJ P,DECCNT
; RET1 IN CORE COUNT NOT YET 0 OR IN-CORE COUNT NOT UP FOR THIS JOB
; RET2 IN CORE COUNT WENT TO 0
;CALLED FROM KILHGH,FORHGH,FINOT
DECCNT::PUSHJ P,COMIT ;COMPARE J WITH JBTSGN(T1)
TLZN J,CORCNT ;HAS HIGH SEG IN CORE COUNT ALREADY BEEN
;DECREMENTED FOR THIS JOB?
POPJ P, ;YES, RETURN
SOS JBTSTS##(J) ;NO, DECREMENT HIGH SEG IN CORE COUNT
MOVEM J,JBTSGN##(T1) ;CLEAR CORCNT FLAG IN MEMORY FOR THIS JOB
DECERR: LDB T1,JBYICC## ;GET HIGH SEG IN CORE COUNT
TRCN T1,ICCMSK ;IN CORE COUNT EQUAL ZERO?
JRST DECDID ; YES. MARK DORMANT/IDLE AND SKIP RETURN
TRCE T1,ICCMSK ;GO NEGATIVE?
POPJ P, ;NO
AOS JBTSTS##(J) ;NO, ERROR ADD BACK TO 0
STOPCD DECERR,DEBUG,ICN, ;++INCORE COUNT NEGATIVE
DECDID: PUSHJ P,INDISQ ; INSERT IN QUEUE AND SET TIME
SETZ T1, ;CLEAR COUNT
PJRST CPOPJ1## ; AND SKIP RETURN
;SUBROUTINES TO MAINTAIN QUEUE OF DORMANT/IDLE SEGMENTS
; INSERT SEGMENT IN QUEUE
INDISQ: SKIPE JBTDIQ##(J) ; IS SEGMENT IN QUEUE?
PUSHJ P,DLDISQ ; YES. REMOVE BEFORE REINSERTING
; SKIPN JBTADR##(J) ; IN CORE?
; POPJ P, ; NO. LEAVE OUT OF QUEUE
PUSH P,T1 ; SAVE SPACE TO WORK
MOVSI T1,SHRSEG ; ONLY SHAREABLE SEGS CAN BE
TDNN T1,JBTSTS##(J) ; IDLE/DORMANT
JRST TPOPJ## ; SO DON'T PUT THIS ONE IN QUEUE
MOVNI T1,DISQ## ; QUEUE HEADER
HLL T1,JBTDIQ##(T1) ; OLD LAST IS OUR PREDECESSOR
MOVEM T1,JBTDIQ##(J) ; POINT US TO LAST,,HEAD
HRLM J,JBTDIQ##(T1) ; POINT HEADER AT US
MOVS T1,T1 ; SWAP
HRRM J,JBTDIQ##(T1) ; POINT OLD LAST AT US
MOVE T1,UPTIME## ; RECORD THE TIME
MOVEM T1,JBTIDT##(J) ; SEGMENT WENT IDLE/DORMANT
PJRST TPOPJ## ; AND RETURN
;DELETE SEGMENT FROM QUEUE
DLDISQ: PUSHJ P,SSEC0## ;DO THIS IN S0
PUSH P,T1 ; SAVE SPACE TO WORK
SKIPN T1,JBTDIQ##(J) ; IN QUEUE?
PJRST TPOPJ## ; NO!!
SETZM JBTDIQ##(J) ; CLEAR OUR ENTRY
HLLM T1,JBTDIQ##(T1) ; POINT SUCCESSOR BACK AT US
MOVS T1,T1 ; SWAP
HLRM T1,JBTDIQ##(T1) ; POINT PREDECCESSOR TO US
PJRST TPOPJ## ;
;ROUTINE TO COMPARE RH OF J WITH JBTSGN(T1)
;BEFORE STORES INTO JBTSGN(T1)
;WHERE T1 CONTAINS JOB NUMBER AND J IS HIGH SEG NUMBER
;USED FOR DEBUGGING. MONITOR CANNOT RUN VERY LONG IF THIS ERROR GOES UNDETECTED
COMIT: PUSH P,T1 ;SAVE JOB NUMBER
PUSHJ P,LGLPRC## ;MAKE SURE T1 IS A JOB NUMBER
STOPCD .,STOP,POR, ;++PROCESS OUT OF RANGE
HRRZ T1,JBTSGN##(T1) ;GET JOBS HIGH SEG NUMBER
JUMPE T1,TPOPJ## ;IF NONE, OK TO RESTORE J
CAIE T1,(J) ;MAKE SURE RH OF J SAME AS RH OF JBTSGN(T1)
STOPCD .,STOP,BSN, ;++BAD SEGMENT NO.
JRST TPOPJ## ;RESTORE T1 AND RETURN
;ROUTINE TO CHANGE RELOC INFO IF SEG JUST ASSIGNED IS A HIGH SEG
;WHICH THE CURRENT USER MAY BE USING
;CALL: MOVE J,LOW OR HIGH SEG FOR WHICH CORE WAS JUST ASSIGNED(OR RETURNED)
; PUSHJ P,CURHGH
; ALSWAYS RETURN WITH J PRESERVED
; R RESET TO RELOC FOR HIGH SEG IF J IS HIGH SEG, OTHERWISE R AND
; J UNCHANGED
CURHGH::MOVE T1,.CPJOB## ;CURRENT JOB NUMBER
HRRZ T1,JBTSGN##(T1) ;GET HIGH SEG NUMBER OF CURRENT JOB OR 0
CAIE T1,(J) ;IS HIGH SEG JUST ASSIGNED SAME AS CURRENT JOB'S
POPJ P, ;NO
PUSH P,J ;YES, SAVE HIGH SEG NUMBER
PUSHJ P,SETMAP## ;SET HARD. AND SOFT. RELOC INFO FOR CURRENT JOB
; (EVEN THOUGH THIS CALL TO CURHGH MAY BE FOR SOME
; OTHER JOB) SONCE HIGH SEG MAY BE IN NEW PLACE IN CORE
POP P,J ;RESTORE HIGH SEG NUMBER
MOVE R,JBTADR##(J) ;RESTORE HIGH RELOCATION
POPJ P, ;RETURN
;ROUTINE TO SEE IF SUM OF BOTH SEGMENTS WILL FIT INTO MAXIMUM SIZE
;OF PHYSICAL CORE TOGETHER
;CALL: MOVE T1,REQUESTED LENGTH-1 OF SEG BEING ASSIGNED(LOW OR HIGH)
; T1 IS ASSUMED TO HAVE 1777 ORED IN BEFORE CALL
; MOVE J,JOB OR HIGH SEG NUMBER
; PUSHJ P,SUMSEG
; ERROR RETURN, CAN NEVER FIT
; OK RETURN
;PREVIOUS CONTENTS OF T1 AND J PRESERVED ON BOTH RETURNS
;IF HIGH SEG, MUST BY CALLED AT UUO LEVEL, IF T1 NON-ZERO
;OK TO CALL FOR HIGH SEG AT CLOCK LEVEL, PROVIDED ASKING FOR 0 ONLY.
;SHUFFLER MODIFIED SO IT NEVER CALLS SUMSEG(SINCE IT MIGHT SHUFFLE
;HIGH SEGMENT AT CLOCK LEVEL WHICH IS NOT THE CURRENT USERS)
;THIS WILL BE TRUE AS LONG AS A CORE COMMAND IS NOT IMPLEMENTED WHICH
;ALLOWS USER TO ADJUST HIGH SEG TO ANYTHING BUT 0.
;CALLED FROM CORE UUO(CORE0 AND CORE1 ROUTINES)
SUMSEG::JUMPE T1,CPOPJ1## ;ASKING FOR 0 CORE(IF YES, COULD BE
;HIGH SEG AT CLOCK LEVEL)? HAVE NO IDEA WHAT LOW
; SEG NO. IS HOWEVER, 0 ALWAYS WILL FIT
PUSH P,T1 ;SAVE USER ARG FOR NO. WORDS -1 FOR A SEG
PUSH P,J ;SAVE LOW OR HIGH SEGMENT NUMBER
CAILE J,JOBMAX## ;IS REQUEST FOR A LOW SEG?
MOVE J,.CPJOB## ;NO, ASSUME AT UUO LEVEL - GET CURRENT JOB#
PUSHJ P,CORBND## ;T1 = UPPER BOUND # WORD FOR THIS JOB
MOVE J,(P) ;RESTORE LOW OR HIGH SEG # FOR CORE REQUEST
CAILE J,JOBMAX## ;IS REQUEST FOR A LOW SEG?
SKIPA J,.CPJOB## ;NO, ASSUME AT UUO LEVEL - GET CURRENT JOB #
MOVE J,JBTSGN##(J) ;YES, GET HIGH SEG NUMBER (IF ANY)
MOVEI T2,0 ;ASSUME NO HIGH SEG
JUMPLE J,SUM1 ;IF NEG OR 0 NONE
HRRZS J ;CLEAR JUNK IN CASE IN S1
PUSHJ P,SEGSIZ## ;T2=SIZE OF SEG NOT BEING REQUESTED
CAIG J,JOBMAX## ;HIGH SEGMENT REQUEST?
SUBI T2,UPMPSZ## ;YES, UPMP SIZE ALREADY ACCOUNTED FOR
ASH T2,P2WLSH## ;CONVERT FROM PAGES TO WORDS
SUM1: ADD T2,-1(P) ;DESIRED SIZE=OTHER SEG SIZE (WORDS)+
; REQUEST (ORED 1777) SIZE-1 (OR 0)
POP P,J ;RESTORE REQUESTING SEG NO
CAMLE T2,T1 ;IS DESIRED (LENGTH-1)+OTHER LENGTH .LE. JOB UPPER BOUND?
JRST TPOPJ## ;NO, ERROR
JRST TPOPJ1## ;YES, OK RETURN
;ROUTINE TO COMPARE CORTAL(FREE+DORMANT+IDLE CORE) WITH CORTAB(USE BIT TABLE)
;AND HALT IF INCONSISTENT.
;CALL: PUSHJ P,CHKTAL -AFTER CORTAL ADJUSTED
; RETURN ONLY IF OK-ALL ACS SAVED
CHKTAL::
IFE FTMP,<
SOSLE CHKCNT## ;CHECK ON THIS CALL?
; MONGEN DEFAULT MD.CHK==^D32
POPJ P, ;NO, AVOID OVERHEAD (5 M:S.) MOST OF TIME
>
IFN FTMP,<
SOSG CHKCNT## ;BEEN HERE M.CMCT TIMES?
PUSHJ P,MMOWN## ;YES, OWN THE MM RESOURCE?
POPJ P, ;NO, CAN'T DO THIS NOW
>
SE1ENT ;PAGTAB IS IN A NON-ZERO SECTION
PUSH P,T1 ;YES, SAVE ALL ACS USED
MOVEI T1,M.CMCT## ;CHECK MONITOR CORE MEMORY EVERY M.CMCT CALL
MOVEM T1,CHKCNT## ;SO REDUCE MONITOR CPU OVERHEAD
PUSH P,J
PUSH P,U
MOVEI U,0 ;SET FREE+DORMANT+IDLE COUNT TO 0
MOVEI J,PAGTAB ;START AT BEGINNING
SSX J,MS.MEM ;SET SECTION NUMBER
CHKT1: SKIPGE (J) ;SKIP IF PAGE IS IN USE
ADDI U,1 ;NO, ADD 1 TO FREE COUNT
CAME J,CORLST## ;FINISHED PAGTAB?
AOJA J,CHKT1 ;NO,
MOVE J,SEGPTR## ;YES, SCAN ALL HIGH SEGMENTS
CHKT2:
REPEAT 1,< ;
MOVE T1,JBTSTS##(J) ;
TLNN T1,SHRSEG ; SHARABLE?
JRST CHKT2A ; NO. JBTADR LIES. SHOULD NEVER BE IN QUEUE
TRNN T1,ICCMSK ;
SKIPN JBTADR(J) ;
JRST CHKT2A ;
SKIPN JBTDIQ##(J) ;
AOS WRQONE ; OOPS
JRST CHKT2B ;
CHKT2A: SKIPE JBTDIQ##(J) ;
AOS WRQTWO ;
CHKT2B: ;
$LOW ;
WRQONE: 0 ;
WRQTWO: 0 ;
$HIGH ;
> ;
PUSHJ P,CHKLKH ;CHECK FOR DORMANT OR IDLE (UNLOCKED)
JRST CHKT3 ;NO
LDB T1,IMGIN## ;SEGMENT SIZE
ADD U,T1 ;ADD IT TO TOTAL FREE
CHKT3: AOBJN J,CHKT2 ;SCANNED ALL HIGH SEGS?
SUB U,LOKTAL## ;ACCOUNT FOR PAGES LOKCON IS WAITING FOR
CAME U,CORTAL## ;YES, IS FREE+DORMANT+IDLE = BIT TABLE
STOPCD .+1,DEBUG,CMU, ;++CORE MESSED UP
MOVEM U,CORTAL## ;FIX CORTAL AND ATTEMPT TO CONTINUE
POP P,U ;YES, RESTORE ACS AND RETURN
POP P,J
JRST TPOPJ## ;RETORE T1 AND RETURN
SUBTTL ERRCON - MONITOR DETECTED ERROR ROUTINES
;ILLEGAL MEMORY(ILM) DETERMINE IF WILD TRANSFER OR NOT
;CALL: HRRZ T1,USER PC
; PUSHJ P,SEGILM
; LEGAL PC RETURN(MUST BE ILLEGAL REF)
; ILLEGAL PC RETURN(MUST BE WILD TRANSFER)
SEGILM::MOVE T3,T1 ;SAVE THE PC
PUSHJ P,HSVAD ;GET STARTING AND HIGHEST LEGAL
; HIGH SEGMENT ADDRESSES
CAIL T3,(T2) ;ABOVE THE START OF THE HIGH SEG?
CAILE T3,(T1) ;AND BELOW THE TOP OF HIGH SEG?
AOS (P) ;NO, ILLEGAL PC RETURN
POPJ P, ;YES, PC IN HIGH SEG(MUST BE ILLEGAL REF)
;SUBROUTINE TO PRINT "SWAP OUT CHN MEM PAR ERR" ON ALL JOBS USING HIGH SEG
; CLEAR NAME SO NO NEW USERS WILL GET
;CALL: MOVE J,LOW OR HIGH SEG NO WHICH HAD MEM PAR ERR ON SWAP OUT
; PUSHJ P,HGHSWE
; HERE IF HIGH SEG
; SKIP RET IF LOW SEG
HGHSWE::CAIG J,JOBMAX## ;IS THIS A HIGH SEG?
JRST CPOPJ1## ;NO, SKIP RETURN
PUSHJ P,CLRNAM ;CLEAR HIGH SEG NAME SO NO NEW USERS WILL GET
MOVEI T1,SWOMES## ;ADR OF SUB IN ERRCON WHICH PRINTS
; SWAP OUT MEM PAR ERR
PJRST HGHAPP ;GO APPLY IT TO ALL JOBS USING HIGH SEG
;SUBROUTINE TO HANDLE SPURIOUS PARITY ERROR (MAYBE READ PAUSE WRITE)
;BLAME ALL JOBS SHARING HIGH SEG OF CURRENT JOB IF NO DISK COPY
;ELSE JUST SWAY OTHERS OUT
;CALL: MOVE J,CURRENT JOB NO.
; PUSHJ P,HGHSPE
; ALWAYS RETURN - J - PRESERVED
HGHSPE::PUSH P,J ;SAVE CURRENT JOB NO.
SKIPLE J,JBTSGN##(J) ;DOES CURRENT JOB HAVE A HIGH SEG?
PUSHJ P,HGHPAR ;YES, EITHER FLAG JOBS FOR ERROR OR SWAP OUT
JRST JPOPJ## ;RESTORE CURRENT JOB NO AND RETURN
;SUBROUTINE TO HANDLE MEM PARITY IN A HIGH SEG
;CAUSE ALL JOBS TO BE SWAPPED OUT (SO GOOD DISK COPY GET USED IF ONE)
;IF HIGH SEG DOES NOT HAVE COPY SWAPPED OUT, ALL JOBS GET ERROR MESSAGE
;CALL: MOVE J, HIGH SEG NUMBER
; PUSHJ P,HGHPAR
; ALWAYS RETURN
HGHPAR::MOVEI T1,HGHPR1 ;APPLY SUB TO SWAP OUT ALL JOBS USING HIGH SEG
; UNLESS LOCKED OR NO DISK COPY
LDB T2,IMGOUT## ;ALLOCATION DISK
PJUMPN T2,HGHAPP ;IF A COPY THERE, JUST SWAP OUT ALL JOBS USING IT
; GIVE ERROR MESSAGES TO LOCKED JOBS
IFN FTMP,<
PUSHJ P,GETMM## ;GET MM RESOURCE AT CLOCK LEVEL
JRST .-1 ;MUST HAVE IT BEFORE PROCEDING
>
PUSHJ P,CLRNAM ;CLEAR SEGNAME SO NO ONE NEW WILL USE
; (RETURN DISK AND CORE SPACE IF DORMANT)
IFN FTMP,<
PUSHJ P,GIVMM## ;RETURN MM RESOURCE
>
MOVEI T1,PARJB1## ;SUB TO FLAG JOB TO GET MESSAGE AND STOP
;FALL INTO SUB TO APPLY PARJOB TO ALL JOBS
;ROUTINE TO APPLY A SUB TO EACH JOB WITH THIS HIGH SEG
;CALL: MOVEI T1,ADR OF SUB. TO BE APPLIED
; MOVE J,HIGH SEG NUMBER
; PUSHJ P,HGHAPP
; ALWAYS RETURN -J CLOBBERRED
HGHAPP::PUSHJ P,SAVE1## ;SAVE P1
PUSH P,T1 ;PUT SUB ADR ON STACK
HRRZ P1,J ;REMEMBER BAD HIGH SEG
MOVE J,HIGHJB## ;SCAN ALL JOBS FROM HIGHEST DOWN
;LOOP TO SCAN FOR ALL JOBS USING BAD HIGH SEG
HGHPLP: SKIPG T1,JBTSGN##(J) ;THIS JOB HAVE A HIGH SEG?
HGHPL1: SOJG J,HGHPLP ;NO, RUN OUT OF JOBS?
JUMPLE J,TPOPJ## ;YES, FINISHED?
CAIN P1,(T1) ;NO, IS THIS HIGH SEG THE BAD ONE?
PUSHJ P,@(P) ;YES, CALL SUB AS SPECIFIED BY CALLER
JRST HGHPL1 ;GO BACK FOR MORE JOBS
;SUBROUTINE TO CHECK IF A JOB IS LOCKED (LOW OR HIGH SEG)
; OR IF HIGH SEG HAS NO DISK COPY - SET ERROR BIT TO STOP JOB
;ALWAYS SWAP JOB (LOW & HIGH SEG) OUT (UNLESS LOCKED)
; TO TRY TO FIX ERROR IF HIGH SEG HAS DISK COPY
;CALL: MOVE J,JOB NO.
; PUSHJ P,HGHPR1
; ALWAYS RETURN
HGHPR1:
IFN FTLOCK,< ;LOCK UUO FEATURE?
PUSHJ P,LOKCHK## ;IS THIS JOB'S LOW OR HI SEG LOCKED?
PJRST PARJB1## ;YES, STOP JOB GIVE ERROR MESSAGE
>
PJRST XPANDH## ;NO, SWAP HIM OUT AND ALL OTHER JOBS
; IF THIS IS A HIGH SEG.
SUBTTL SAVGET - SAVE, GET, R, AND RUN COMMANDS
;THE LOWER CORE LOCATION 0-17 IN USER AREA ARE USED FOR TEMP STORAGE FOR SAVE-GET
;THEY ARE DEFINED IN BEGINNING OF SAVGET ROUTINE
;ROUTINE TO SET EXTENSION OF HIGH SEG
;SAME CALL AS SETEXT EXCEPT S NOT SETUP
;CALLED FROM GETARG(RUN, GET SEG UUO)
SETEX1::TLZ S,NSRBIT ;TRY SHARABLE SEG FIRST(.SHR) THEN .HGH
;FALL INTO SETEXT
;ROUTINE TO SET EXTENSION OF HIGH SEGMENT TO SHR(SSAVE,GET,R) OR HGH(SAVE)
;CALL: HRLI S,0(GET,SSAVE,RUN) OR NSRBIT(SAVE)
; MOVE R,XWD PROTECT,RELOC FOR LOW SEG
; MOVEI T2, LOW FILE EXTENSION OR 0 IF NONE TYPED IN
; PUSHJ P,SETEXT
; RETURN T1 PRESERVED(TTY INPUT BYTE POINTER)
; CALLED FROM COMMAND DECODER ROUTINE SGSET, T1 PRESERVED (INPUT BYTE POINTER)
SETEXT::HRLZM T2,.JDAT+SGALOW## ;SAVE EXTENSION USER TYPED FOR LOW SEG
MOVE T2,[SIXBIT /SHRHGH/] ;ASSUME SSAVE COMMAND(OR GET)
TLNE S,NSRBIT ;WAS IT?
MOVSS T2 ;NO, EXCHANGE ROLES OF EXTENSIONS, MUST
; BY SAVE
MOVEM T2,.JDAT+SGAHGH## ;SAVE FOR ENTER AND RENAME OF HIGH SEGMENT
POPJ P,
;SUBROUTINE TO SETUP JOBHRL
;CALL: MOVE J,HI SEG NUMBER
; PUSHJ P,SETHRL
SETHRL::HLRZ T2,JBTADR##(J) ;LENGTH-1 OF HIGH SEG
ADDI T2,1 ;LENGTH
HLRZ T1,.JDAT+JOBHRL## ;RELATIVE FIRST FREE LOC IN HIGH SEG (SET BY LOADER)
JUMPE T1,SETHR1 ;GO FILL IT IN IF ZERO
CAMG T1,T2 ;SIZE OKAY?
SKIPE USRDDT## ;YES, IS USER USING DDT
SETHR1: HRLM T2,.JDAT+JOBHRL## ;YES, SET FIRST FREE TO BE FIRST WORD BEYOND END
POPJ P, ;RETURN
;ROUTINE TO SAVE HIGH SEG IF IT EXISTS (AS.SHR(SSAVE) OR .HGH(SAVE))
;AND DETERMINE IF LOW SEG HAS DATA TO BE SAVED, OR NOT(IF YES IT WILL BE WRITTEN
;AS LOW UNLESS USER SPECIFIED DIFFERENTLY RATHER THAN.SAV)
;ALWAYS SAVE LOW SEG IF MAGTAPE OR IF NO HIGH SEG
;CALL: MOVE J, JOB NUMBER (R,R,F SET UP)
; PUSHJ P,SAVHGH
; RETURN1 NO DATA IN LOW SEGMENT
; RETURN2 SAVE LOW SEGMENT
; J DESTROYED,SGAEXT RESTORED TO SAV OR USERS TYPED EXTENSION
; SGALLEN RESTORED TO IOWD FOR LOW SEG IF DTA,PROJ R IF DSK
; DEVICE INITED ON EITHER RETURN
SAVHGH::SKIPG J,JBTSGN##(J) ;DOES CURRENT JOB HAVE A REAL HIGH SEGMENT?
JRST SAVLOW ;NO, RESTORE SGAEXT,SGALEN AND SKIP
;RETURN SO LOW SEG WILL BE SAVED
; USER HAS NO CHOICE(MAY BE HAD SPY SEG
PUSHJ P,SGH ;SET EXTENSION IN E+1 OF ENTER BLOCK
PUSHJ P,SETHRL ;SETUP JOBHRL
HLRZ T1,.JDAT+JOBHRL## ;GET CORRECT FIRST REL FREE LOC IN HIGH SEG
MOVNS T1 ;SET RH=-NO. OF WORDS TO WRITE, LH=-1
PUSHJ P,SG4## ;SETUP E+3
PUSH P,.JDAT+JOBVER## ;SAVE LOWSEG VERSION
SKIPE T1,.VJDT+JOBHVR## ;HISEG VERSION NUMBER
MOVEM T1,.JDAT+JOBVER## ;STORE FOR FILSER
MOVNI T1,4 ;INDICATE HIGH SEGMENT SAVE IN PROGRESS
HRLM T1,USRHCU## ;SET LH OF HIGEST CHANNEL USED AS A FLAGE THAT
; A SAVE IS IN PROGRESS FOR HIGH SEG
ENTER 0,SGANAM## ;ENTER NAME IN DIRECTORY(SHR OR HGH)
JRST [POP P,.JDAT+JOBVER## ;RESTORE LOWSEG VERSION
JRST SAVERR##] ; PRINT ERROR MESSAGE
POP P,.JDAT+JOBVER## ;RESTORE VERSION
PUSHJ P,COPVJD ;COPY LOW SEGMENT JOB DATA AREA NUMBERS TO
; VESTIGUAL JOBDAT
PUSHJ P,OUTHGH
PUSHJ P,SGIOCK## ;CHECK FOR TRANSMISSION ERRORS(RETURN IF OK)
CLOSE 0, ;CLOSE OUTPUT(BEFORE LOOKUP FOR DELETE)
; SO SHARABLE SEG WILL BE SUPERCEDE BY NEW FILE
; IF SAME NAME
HRLZ T1,.JDAT+SGAHGH## ;DELETE HGH IF SHR WRITTEN OR VICE VERSA
PUSHJ P,DELET ;DEPENDING IF THIS WAS A SSAVE OR SAVE COM.
MOVSI T1,'SAV' ;DELETE OLD .SAV
PUSHJ P,DELET ; FILE, IF ANY.
SETZ T3, ;SET FLAG THAT WE CAME FROM "SAVE"
PUSHJ P,LOWCHK ;CHANGE EXTENSION FOR LOW FILE TO .LOW
; UNLESS USER SUPPLIED HIS OWN ARG
JRST .+2 ;DO NOT NEED LOW FILE WRITTEN
; SO DELETE POSSIBLE PREVIOUS VERSION
; SO USER WILL NOT BE CONFUSED
JRST CPOPJ1## ;LOW FILE NEEDED, DO NOT BOTHER TO DELETE
; GIVE SKIP RETURN TO CALLER
MOVE T1,DEVMOD(F)
TLNE T1,DVMTA ;DEVICE A MAGTAPE?
PUSHJ P,SAVNUL ;YES, WRITE A NULL LOW SEGMENT.
SKIPN T1,.JDAT+SGALOW## ;OBTAIN LOW SEGMENT NAME
MOVSI T1,(SIXBIT /LOW/) ;FILL IN DEFAULT IF NULL
JRST DELET ;DELETE FILE AND GIVE NO SKIP RETURN TO CALLER
SAVNUL: HRROS USRHCU## ;SET SAVE IN PROGRESS FLAG
MOVNI T1,JOBHRN##+1 ;NEGATIVE SIZE OF RECORD TO OUTPUT
HRLI T1,JOBNSV##-1 ;ADDRESS IN JOBDAT TO WRITE OUT NULL SAVE FILE
MOVSM T1,.JDAT+SGALEN## ;SET UP OUTPUT IOWD
SETZM .JDAT+JOBHRN##+JOBNSV## ;CLEAR WORD TO INDICATE NULL FILE.
OUTPUT 0,SGALEN## ;WRITE THE NULL SEGMENT
HRRZS USRHCU## ;CLEAR SAVE IN PROGRESS FLAG
PUSHJ P,SGIOCK## ;CHECK FOR ERRORS (RETURN IF OK)
CLOSE 0, ;WRITE EOF
POPJ P,
;SUBROUTINE TO SETUP THE VESTIGUAL JOB DATA AREA FROM THE JOB DATA
; AREA ON A SAVE IF NECESSARY
;CALLING SEQUENCE:
; PUSHJ P,SETVJD
;ALWAYS RETURNS CPOPJ
COPVJD::MOVE J,.CPJOB## ;RESTORE JOB NUMBER
SKIPLE J,JBTSGN##(J) ;GET SEGMENT NUMBER FROM JOB NUMBER
TLNE J,SHRSEG ;IS HIGH SEG SHARABLE?
POPJ P, ;YES, DO NOT INITIALIZE VESTIGIAL JOB DATA AREA
; SINCE IT MUST HAVE BEEN DONE WHEN HIGH FILE CREATED
; AND USER CANNOT MODIFY NOW
LDB T1,JBYHSO## ;PAGE WHERE HIGH SEGMENT ORIGINS
PUSHJ P,YANKIZ## ;MAKE SURE THE PAGE IS IN CORE
JRST [PUSHJ P,CRPAGE## ;ABZ, CREATE THE PAGE
JRST NEED1P ;CAN'T
JRST .+1] ;CONTINUE
MOVE J,.CPJOB## ;RESTORE JOB NUMBER
MOVE J,JBTSGN##(J) ; AND HIGH SEGMENT NUMBER
MOVE T1,JBTADR##(J) ;NO, INITIALIZE VESTIGIAL JOB DATA AREA IN HIGH SEG
SUBI T1,1 ;FROM LOW SEG JOB DATA AREA
PUSH T1,.JDAT+JOBSA## ;SAVE JOB STARTING ADDRESS (RH)
; AND INITIAL FIRST FREE LOC (LH)
PUSH T1,.JDAT+JOB41## ;SAVE USER LOC 41(USER UUO HANDLER JSR)
PUSH T1,.JDAT+JOBCOR## ;SAVE USER TYPED THIRD (CORE) ARG (RH) AND
; HIGHEST DATA LOC LOADED IN LOW SEG (LH
HRR T2,.JDAT+JOBREN## ;SAVE REENTER COMMAND STARTING ADDRESS
HLL T2,.JDAT+JOBHRL## ;AND FIRST (REL) FREE LOCATION SET BY LOADER
PUSH T1,T2
PUSH T1,.JDAT+JOBVER## ;SAVE BOTH HALVES OF PROGRAM VERSION NUMBER
; LH IS USED FOR PROGRAMMER NUMBER LAST MODIFYING
PUSH T1,.JDAT+SGANAM## ;SAVE NAME OF SEGMENT FOR DDT
AOBJN T1,.+1 ;SKIP DDT SYMBOL TABLE POINTER
PUSH T1,[EXP 0] ;CLEAR 10 (OCTAL) FOR FUTURE
LDB T2,JBYHSO## ;PAGE NUMBER WHERE HIGH SEGMENT ORIGINS
DPB T2,[POINT 9,(T1),17]
POPJ P, ;RETURN
;SUBROUTINE TO OUTPUT THE HIGH SEGMENT
;CALL:
; PUSHJ P,OUTHGH
; RETURN HERE (I/O ERRORS NOT CHECKED FOR)
;
OUTHGH::HLLZ T1,.JDAT+JOBHRL## ;GET CORRECT FIRST REL FREE LOC IN HIGH SEG
MOVNM T1,.JDAT+SGALEN## ;SET LH=-NO. WORDS TO WRITE, RH=0
; SET AGAIN SINCE ENTER CHANGED E+3
LDB T1,JBYHSO## ;STARTING PAGE OF HIGH SEG
LSH T1,P2WLSH## ;START ADR
SUBI T1,1
HRRM T1,.JDAT+SGALEN## ;START ADR OF IOWD
OUTPUT 0,SGALEN## ;WRITE ALL OF ORIGINAL HIGH SEG
MOVE J,.CPJOB## ;RESTORE JOB NUMBER OF CURRENT JOB
HRRZS USRHCU## ;NOW CLEAR SAVE IN PROGRESS FLAG
POPJ P, ;RETURN
;UUO TO GET JUST HIGH SEGMENT, USER CHANNELS 1 THRU 17 UNTOUCHED
;CALL: MOVEI AC,D ;WHERE D IS LOCATION OF 5 ARG(SEE RUN UUO)
; ;THE 6TH(CORE ARG IS IGNORED) BUT MUST BE IN LEGAL MEMORY
; CALL AC,[SIXBIT /GETSEG/] OR CALLI AC,40
; ERROR RETURN UNLESS LH=HALT
; OK RETURN
UGETHI::PUSHJ P,SAVE1## ;SAVE P1
PUSHJ P,GETARG## ;YES,GET 6 ARGS FROM USER
SKIPN T1,.JDAT+SGANEW## ;EXTENDED ARGUMENT SPECIFIED?
JRST UGETH1 ;NO, SO DON'T CHECK ITS LEGALITY
JUMPG T1,UGETH0 ;INVALID CORE ARG POINTER IF POSITIVE
; (1022 IS KNOWN TO LEAVE A SMALL
; POSITIVE INTEGER HERE)
HLRE T1,T1 ;GET LENGTH OF ARGUMENT LIST
AOJE T1,UGETH1 ;MUST BE EXACTLY 1 WORD
; (ALGOL IS KNOWN TO LEAVE SIXBIT/DSK/,
; I.E., A LARGE NEGATIVE NUMBER)
UGETH0: SETZM .JDAT+SGANEW## ;MAKE OLD .EXE FILES WORK - IGNORE GARBAGE
UGETH1: PUSHJ P,UGTSSL## ;GET EXTENDED CORE/SECTION ARG
MOVEI T1,JS.XOR ;CLEAR EXECUTE STATUS
ANDCAM T1,JBTSTS##(J)
MOVSI T1,(JS.IGS) ;INDICATE IN GETSEG
IORM T1,JBTST2##(J)
MOVSI T1,GTHGH## ;JUST GET THE HIGH SEG
PUSHJ P,GETSEG ;TRY TO SHARE HIGH SEG OR READ IN HIGH FILE
JRST [MOVSI T1,(JS.IGS)
ANDCAM T1,JBTST2##(J)
JRST NOFILE##]
;NO FILE FOUND, PRINT MESSAGE OR ERROR RETURN
JFCL ;HIGH FILE IN, EVERYTHING OK
PUSHJ P,CHKMED ;CHECK TO SEE IF THIS IS SHARABLE SEG(EXT=SHR)
; IF YES, SET MEDDLE BIT FOR THIS USER
; SO HE CANNOT TURN OFF UWP OR CHANGE CORE ASSIGNMENT
MOVSI T1,(JS.IGS)
ANDCAM T1,JBTST2##(J) ;CLEAR "IN GETSEG"
MOVSI T1,(UP.GET)
ANDCAM T1,.USBTS ;GET NO LONGER IN PROGRESS
PUSHJ P,VERWAT## ;SEE IF WATCHING
JRST GETHI1 ;NO--RETURN
PUSHJ P,VERHGH## ;YES - PRINT HIGH VERSION
PUSHJ P,PGMFIL## ;PRINT FILE SPEC
PUSHJ P,PRRBKC## ;PRINT RIGHT BRACKET <CRLF>
GETHI1: PUSHJ P,SGREL## ;RELEASE JUST CHANNEL 0 IF WAS INIT
JRST TPOPJ1## ;OK(SKIP RETURN TO USER AFTER REMOVING USER ARG+AC
;FROM PD LIST WHICH GETARG PUT ON
;ROUTINE TO ADD CURRENT USER TO A SHARED SEGMENT IF IT EXISTS OR
;TRY TO INITIALIZE A HIGH SEGMENT FROM A FILE AND MAKE IT SHARABLE(-SHR) OR NOT(.HGH)
;DEPENDING ON THE EXTENSION OF THE FILE
;CALL: MOVE J, CURRENT JOB NUMBER
; ACS F,R,R,P,SETUP
; MOVE T2,DEVMOD(F)
; PUSHJ P,GETHGH
; RETURN1-HIGH SEG NOW IN ADDRESSING SPACE AND NO LOW FILE NEED BE GOTTEN
; RETURN2 - HIGH SEG NOW IN ADDRESSING SPACE, AND LOW FILE NEEDED
; OR NO HIGH FILES FOUND, TRY LOW FILE
;IFN FTEXE, <RETURNS - BOTH SEGS IN AND READY TO GO>
; J RESTORED TO CURRENT JOB NUMBER
; USER MODE FLAG CLEARED IN UUO PD LIST IR RUN UUO FROM HIGH SEG
; WHICH IS NO LONGER SAME(SO NO ATTEMPT TO ERROR RETURN IF ERROR)
GETHGH::MOVSI T1,(JS.EXE) ;CLEAR EXE BIT
ANDCAM T1,JBTST2##(J)
MOVSI T1,GTBTH## ;GET BOTH SEGMENTS
PUSHJ P,GETSEG ;YES, TRY TO ATTACH TO HIGH SEG OR READ
; IN HIGH FILE IF IT EXISTS, HIGH SEG OK?
JRST NOHIGH ;NO, TRY TO READ IN LOW FILE OLD HIGH
; SEG STILL IN ADR SPACE(IF ANY)
SKIPA ;HIGH FILE OK, GO READ LOW FILE
JRST CPOPJ2## ;BOTH FILES IN, RETURN TO CALL+3
MOVSI T1,.JDAT+JOBUAL##+10 ;ALSO CLEAR DDT STARTING ADDRESS
HRRI T1,.JDAT+JOBUAL##+11
SETZM -1(T1) ;CLEAR JOB DATA AREA
BLT T1,.JDAT+JOBDA##-1 ; IN CASE THERE IS NO LOW FILE
SETZM .JDAT+JOBDDT##
SETZM USRDDT## ;IN MONITOR PROTECTED AREA AS WELL AS JOBDAT
; IN CASE RETURN TO USER WITHOUT RESCHEDULING
PUSHJ P,ADJCOR ;COMPUTE AMOUNT OF CORE FOR BOTH LO & HI SEGS
; FROM USER'S CORE ARG.(IF ANY)
; RETURNS WITH HI SEG # IN T1
HRRO T1,JBTADR##(T1) ;ABSOLUTE ADDRESS OF HIGH SEG(LH=-1 FOR
; POPS SO NO PDL UNDERFLOW)
ADDI T1,JOBPOP## ;ADD POP OFFSET
POP T1,.JDAT+JOBVER## ;RESTORE BOTH HALVES OF PROG. VERSION NO.
POP T1,T2 ;RESTORE
HLLM T2,.JDAT+JOBHRL## ;RELATIVE FIRST FREE LOC IN HIGH SEG
HRRZM T2,.JDAT+JOBREN## ;PROGRAM REENTER ADR, LH=0
; SAVED FOR FUTURE USE
POP T1,.JDAT+JOBCOR## ;HIGHEST DATA LOC IN LOW SEG(LH)
; AMOUNT OF CORE IN RH TO BE ASSIGNED(#J-1)
POP T1,.JDAT+JOB41## ;USER UUO HANDLER JSR
POP T1,.JDAT+JOBSA## ;FIRST FREE LOC IN LOW SEG(LH), START COMMAND
; STARTING ADDRESS(RH)
;HERE FROM SAVE TOO
SETO T3, ;FLAG THAT THIS IS "GET"
LOWCHK: HRRZ T1,.JDAT+JOBPD1## ;IS CALL FROM HIGH SEGMENT?
CAMLE T1,.CPREL## ;COMPARE PC WITH LOW SEG PROTECTION
HRRZS .JDAT+JOBPD1## ;YES,(OR EXEC) SO CLEAR USRMOD PC FLAG IN LH
; SO ERROR MESSAGES WILL NOT ATTEMPT TO ERROR
; RETURN TO HIGH SEG WHICH IS NO LONGER
; THE ORIGINAL ONE
HLRZ T1,.JDAT+JOBCOR## ;DOES THIS JOB NEED A LOW SEG INPUT OR OUTPUT
CAIGE T1,JOBDA## ;I.E. IT THERE ANY DATA LOADED ABOVE JOB DATA AREA
JRST SG3## ;NO, RETURN AND DO NOT READ IN LOW FILE
JUMPE T3,LOWCK2 ;JUMP IF CAME FROM "SAVE"
MOVSI T1,(JS.EXE) ;WAS LOOKUP DONE?
TDZE T1,JBTST2##(J)
JRST LOWCK2 ;YES
MOVSI T2,'EXE' ;SET UP TO CHECK FOR .EXE FILE
MOVEM T2,.JDAT+SGAEXT## ;STORE IN LOOKUP BLOCK
SKIPL F ;DEVICE INITED?
PUSHJ P,SGOPEN ;NO, DO IT
TLNE F,LOOKB ;IS THE FILE ALREADY OPEN?
JRST [USETI 0,1 ;YES, THEN GO TO BLOCK1
JRST .+3] ;AND SKIP THE SECOND LOOKUP
PUSHJ P,LUKFIL## ;LOOKUP .EXE FILE
JRST LOWCK2 ;NO FOUND--CHECK FOR .LOW
MOVSI P1,GTLOW## ;GET ONLY THE LOW SEGMENT
PUSHJ P,GETNEW ;READ IN THE .EXE FILE
JRST GETH2B ;LOW SEG LOCKED
JRST CPOPJ2##
LOWCK2: MOVSI T2,(SIXBIT /LOW/) ;YES, READ OR WRITE LOW FILE WITH EXTENSION .LOW
JRST SETLOW
NOHIGH: HRRZ T1,.JDAT+JOBPD1##+1 ;(HERE ON GET COM. OR RUN UUO - NO NEW HIGH SEG
; BUT NOT ON GETSEG UUO)
CAMLE T1,.CPREL## ;COMPARE PC WITH LOW SEG PROT.
HRRZS .JDAT+JOBPD1## ;YES - CLEAR USRMOD BIT SO ERRORS WON'T
;RETURN TO HI SEG WHICH IS NO LONGER
;THE ORIGINAL ONE
IFE FTMP,<
PUSHJ P,KILHSH ;REMOVE PREVIOUS HI SEG (IF ANY)
; BOTH SOFTWARE AND HARDWARE-WISE
>
IFN FTMP,<
PUSHJ P,[PUSHJ P,GGVMM## ;UP MM
PJRST KILHSH] ;THEN REMOVE THE HI SEG
>
TRYLOW: MOVE T2,.JDAT+SGALOW## ;(HERE ON SAVE)
; LOW FILE EXTENSION USER TYPED OR 0 IF HE DIDN'T
SETLOW: MOVE J,.CPJOB## ;IN CASE FROM SAVHGH WHICH CLOBBERED J
MOVSI T1,(JS.EXE) ;CLEAR EXE BIT
ANDCAM T1,JBTST2##(J)
MOVEM T2,.JDAT+SGAEXT## ;SET IN E+1 FOR LOOKUP
AOS (P) ;SET FOR NEED LOW READ OR WRITE RETURN
; (HERE FROM SAVE IF NO HIGH SEG)
JUMPL F,SG3## ;HAS DEVICE ALREADY BEEN INITED?
; INITB=1(BIT 0) IF YES
SGOPEN::OPEN 0,SGAMOD## ;NO, INIT DEVICE IN SAVMOD
JRST SGERRA## ;ERROR, NOT AVAILABLE
JRST SG3## ;OK RESTORE SGALEN TO IOWD IF DTA,PP IF DSK AND RET
SAVLOW: MOVE T2,DEVMOD(F)
TLNE T2,DVMTA ;DEVICE MAGTAPE?
PUSHJ P,SAVNUL ;YES, WRITE A NULL HIGH SEGMENT
JRST TRYLOW ;RESTORE SGAEXT ETC,
;ROUTINE TO CREATE A NEW HIGH SEG AND READ IN HIGH FILE OR
;PLACE THE DESIRED SHARABLE HIGH SEGMENT IN CURRENT USER'S LOGICAL ADDRESSING SPACE
;CALL: MOVE R,LOW SEG RELOC
; MOVE F,ADR. OF DEVICE DATA BLOCK
; MOVE J,JOB NUMBER
;IFN FTEXE,<MOVSI T1,FLAGS>
; PUSHJ P,GETSEG
; RETURN 1 - HIGH SEG OR FILE NOT FOUND
; RETURN 2 - HIGH SEG FOUND AND IN LOG ADR. SPACE(IN FACT ALSO IN CORE)
;IFN FTEXE,<RETURN 3 - BOTH SEGS IN AND READY TO GO>
GETSEG::MOVEM T1,.JDAT+SGAEND##
PUSHJ P,SGH ;SET E+3 TO 0 IF DTA,PPN IF DSK
PUSH P,F ;SAVE POINTER TO DDB
SKIPE USRJDA##+0 ;CHANNEL 0 OPEN?
RELEAS 0, ;YES, RELEASE IT
POP P,F ;RESTORE IT
MOVE T2,.JDAT+SGANAM## ;GET PROGRAM NAME
IFN FTMP,<
PUSHJ P,UPMM## ;MUST HAVE THE MM TO SEARCH THE TABLES
>
HLRZ T1,.JDAT+SGAEXT## ;GET USER PROVIDED EXTENSION
CAIE T1,'EXE' ;SHARABLE EXTENSION?
CAIN T1,'SHR'
CAIA
JUMPN T1,GETH0 ;NO, IF SPECIFIED, DO OPEN,LOOKUP
MOVS T1,.JDAT+SGADEV## ;USER SUPPLIED DEVICE NAME
CAIE T1,'SYS' ;UNQUALIFIED?
JRST GETH5 ;NO
MOVSI T1,SYSSEG## ;SEGMENT FROM SYS BIT
JUMPE T1,GETH5 ;AVOID SEARCH IF DEFINED EQUAL TO ZERO
PUSHJ P,SYSNM## ;GET THE PPN OF USER'S SYS
JRST GETH0 ;A LOGICAL NAME
MOVE J,SEGPTR## ;YES, SEARCH FOR A KNOWN SEGMENT
GETH3: CAME T2,JBTNAM##(J) ;NAME MATCH?
GETH4: AOBJN J,GETH3 ;NO, TRY THE NEXT ONE
JUMPGE J,GETH5 ;IF NO MORE, QUIT
CAMN T3,JBTPPN##(J) ;FROM THIS USER'S SYS?
TDNN T1,JBTSTS##(J) ;NAME MATCHES, FROM SYS?
JRST GETH4 ;NO, LOOK FOR ANOTHER MATCH
HRLI J,SHRSEG ;YES, FLAG AS SHARABLE
TLO F,SYSDEV ;AND FROM SYS
JRST GETH0A ;SKIP OPEN, LOOKUP, AND CLOSE UUOS
GETH5: MOVE T2,DEVMOD(F) ;EXTENSION 'SHR' OR ZERO, SEARCH KNOWN SEGS,
TLNE T2,DVDSK ;SKIP IF NOT A DISK
SKIPA T1,.JDAT+SGAPPN## ;USE PROVIDED PPN
MOVEI T1,0 ;IF NON-DISK, PPN ARG=0
TLNE T2,DVDSK ;A DSK?
JUMPE T1,GETH0 ;YES, IF E+3=0 DO THE LOOKUP SINCE THE DEFAULT
; PATH MAY BE DIFFERENT FROM LOGGED-IN PPN
IFN FTMP,<
PUSHJ P,DWNMM## ;GIVE UP THE MM, SRCSEG WILL GET IT BACK
>
MOVEI T2,DSKDDB##
CAIN T2,(F) ;LOOKING AT PROTOTYPE DDB?
SKIPA U,.JDAT+SGADEV## ;YES, USE USER PROVIDED DEVICE
SKIPE U,DEVNAM(F) ;NO, USE PHYSICAL NAME FROM DDB
SKIPE T2,.JDAT+SGANAM## ;SEG NAME
PUSHJ P,SRCSEG ;SEARCH KNOWN SEGMENT TABLE
JRST GETH0 ;NOT FOUND, GO DO OPEN AND LOOKUP IN CASE ON TAPE
GETH0A:
IFN FTFDAE,<
LDB T1,[POINT HSASIZ,JBTSTS##(J),HSAPOS]
TRNN T1,400 ;SIGN BIT OF OWNER PROTECTION FIELD ON?
;YES, DO THE LOOKUP SO FILE DAEMON WILL GET
; CALLED IF IT SHOULD BE
>
JRST GETH1 ;FOUND, CHECK ACCESS PRIVILEGES
IFN FTFDAE,<
MOVEI P1,PR.RED ;CHECK READ ACCESS FOR CURRENT JOB
MOVE P2,.CPJOB## ;SINCE WE DON'T NEED TO CALL FILDAE
PUSHJ P,CHKHSA ;UNLESS WE GET A PROTECION FAILURE
JRST GETH0 ;ACCESS FAILURE, DO THE LOOKUP
JRST GETH2C ;CAN READ WITHOUT FILDAE, SKIP THE LOOKUP
>
GETH0:
IFN FTMP,<
PUSHJ P,TGVMM## ;GIVE UP MM BEFORE OPEN
>
OPEN 0,SGAMOD## ;NO, TRY TO ASSIGN DEVICE
JRST SGERRA## ;CAN'T, GO PRINT ERROR OR RETURN TO USER.
MOVE T1,DEVMOD(F) ;GET DEVICE BITS
TLNE T1,DVDTA ;DTA?
JRST GETH5A ;YES, SKIP LOOKUP
MOVSI T1,'EXE' ;GET EXTENSION OF EXE
EXCH T1,.JDAT+SGAEXT## ;PUT IT IN LOOKUP BLOCK AND SAVE OLD EXT
PUSH P,T1 ;SAVE OLD EXTENSION
HLRZ T1,.JDAT+SGALOW## ;GET USER EXTEN.
SKIPE T1 ;IS THERE ONE?
CAIN T1,'EXE' ;OR IS IT "EXE"?
PUSHJ P,LUPFIL ;IS THERE AN .EXE FILE?
SKIPA T1,.JDAT+SGAEXT## ;NO
JRST [POP P,(P) ;YES, GO READ IT IN
JRST GETH6]
HRRZS T1 ;ERROR CODE
JUMPN T1,NOFILE## ;REPORT ERROR IF NOT FILE NOT FOUND
POP P,.JDAT+SGAEXT## ;RESTORE EXTENSION
GETH5A: SETZM .JDAT+SGAEND## ;CLEAR FLAGS, WE'RE THRU WITH THEM
MOVSI T1,(JS.EXE) ;SET EXE BIT
IORM T1,JBTST2##(J) ;IN JOB STATUS TO INDICATE LOOKUP FAILED
MOVE T1,DEVMOD(F) ;IS THIS MAG TAPE? (MAG TAPE CAN NEVER BE SHARABLE)
TLNN T1,DVMTA ;(MAG TAPE PUSHJS ALWAYS SUCCEED)
PUSHJ P,LUPFIL ;NO, LOOKUP ON HIGH FILE WITH EXT .SHR
JRST TRYHGH ;NOT FOUND, TRY EXTENSION OF .HGH
GETH6: PUSHJ P,FNDSMS ;DOES SEGMENT ALREADY EXIST?
JRST [HLRZ T1,.JDAT+SGAEXT## ;GET LOOKUP'D EXTENSION
CAIN T1,'EXE' ;EXE?
JRST EXEFND ;YES
JRST GETH2] ;GO READ IN HIGH FILE
JRST GETH2C ;PROTECTION WAS CHECKED BY THE LOOKUP
GETH1: MOVEI P1,PR.RED## ;YES, CHECK EXECUTE ONLY PROTECTION
MOVE P2,.CPJOB## ;FOR CURRENT JOB
PUSHJ P,CHKHSA ;WITH FILE WHICH INITIALIZED HIGH SEG
IFE FTMP,<
POPJ P, ;CAN'T READ-DTA,MTA NOT AVAIL OR DSK ACCESS RIGHTS
; NOT PROPER, GIVE HIGH SEG RETURN TO GETSEG
>
IFN FTMP,<
PJRST TGVMM## ;RETURN MM IF OWNED
>
JRST GETH2C ;GO SHARE THE HIGH SEGMENT
;COME HERE IF THERE IS AN .EXE FILE TO BE READ IN
;
EXEFND: MOVE P1,.JDAT+SGAEND## ;GET SAVED FLAGS
PUSHJ P,GETNEW ;READ IN NEW SAVE FILE
JRST GETH2B ;ERROR, FLUSH THIS USER
TLNE P1,GTLOW## ;WAS IT A GETSEG?
JRST SETVJD ;NO, SET UP VEST JOB DAT
TLNE P1,GT%GTH## ;WAS IT SUCCESSFUL?
JRST FIXVJD ;YES, DON'T SET UP VEST JOB DATA AREA
HLLZS .JDAT+SGAEXT## ;NO HI SEG IN THE FILE, SO FNFERR
POPJ P, ;EXIT
SETVJD: TLNN P1,GT%GTH## ;IS THERE A HI SEG?
JRST NOVJD ;NO, DONT SET IT UP
PUSHJ P,ADJCOR ;SUBTRACT HIGH SEG SIZE FROM USER'S
; CORE ARGUMENT
MOVE J,JBTSGN##(J) ;HISEG START
LDB T1,JBYHSO## ;GET HISEG START
MOVE J,.CPJOB## ;RESTORE JOB #
TLNN P1,SV%SHR ;SHARABLE
PUSHJ P,YANKIZ## ;BRING PAGE IN, IF OUT
JFCL ;SHOULDN'T BE ABLE
MOVE T2,JBTSGN##(J) ;GET HIGH SEGMENT NUMBER
EXCH T2,J ;PRESERVE J
LDB T3,JBYHSO## ;GET HISEG ORIGIN PAGE
EXCH T2,J ;RESTORE J
MOVE T2,JBTADR##(T2) ;GET ITS STARTING ADDRESS
SKIPN T1,.USREL ;IS JOB HOLEY?
JRST SETVJ1 ;NO, SKIP JOBCOR FUDGERY
LSH T3,P2WLSH## ;GET HISEG ADDRESS
HRRZ T1,.JDAT+JOBCOR## ;GET BUILT-IN CORE ARG
CAML T1,T3 ;LINK BUG (OVERLAP ERROR)?
MOVE T1,.USREL ;YES, GET A GOOD JOBCOR
HRRM T1,.JDAT+JOBCOR## ;MAKE SURE OF JOBCOR
HLRZ T1,.JDAT+JOBSA##;GET INITIAL JOBFF
CAMG T1,T3 ;GOOD VALUE THERE?
JRST SETVJ1 ;YES, WE'RE DONE
MOVE T1,.USREL ;GET REAL JOBREL
ADDI T1,1 ;MAKE INTO A JOBFF
HRLM T1,.JDAT+JOBSA##;GIVE IT A GOOD JOBFF
SETVJ1: MOVE T1,.JDAT+JOBSA## ;SET UP VESTIGIAL JOB DATA AREA
MOVEM T1,JOBHSA##(T2) ;SET UP JOBSA
MOVE T1,.JDAT+JOB41## ; AND JOB 41
MOVEM T1,JOBH41##(T2)
MOVE T1,.JDAT+JOBCOR## ; AND JOBCOR
MOVEM T1,JOBHCR##(T2)
MOVE T1,.JDAT+JOBHRL## ; AND JOBHRL
HRR T1,.JDAT+JOBREN##
MOVEM T1,JOBHRN##(T2)
MOVE T1,.JDAT+JOBVER## ; AND JOBVER
MOVEM T1,JOBHVR##(T2)
JRST NOVJD ;GO ENTER SEGMENT NAME
;HERE TO CHECK CONSISTANCY OF VESTIGIAL JOBDAT AFTER GETSEG
FIXVJD: MOVE J,JBTSGN##(J) ;GET HISEG NUMBER
MOVE T2,JBTADR##(J) ;GET MONITOR ADDRESS OF SEGMENT
LDB T3,JBYHSO## ;GET ITS STARTING PAGE
HRLM T3,.JBHGA##(T2) ;SAVE ORIGIN PAGE IN SEGMENT
LSH T3,P2WLSH## ;GET ITS STARTING ADDRESS
HRRZ T1,JOBHCR##(T2) ;GET CORE SIZE SPECIFIED IN SEGMENT
CAIGE T1,(T3) ;LINK BUG (PAGE OVERLAP)?
JRST NOVJD ;NO, NOTHING TO FIX
HRRZI T1,-1(T3) ;YES, GET BETTER VALUE
HRRM T1,JOBHCR##(T2) ;FIX IN SEGMENT
HLRZ T1,JOBHSA##(T2) ;GET INITIAL JOBFF FROM SEGMENT
CAILE T1,(T3) ;REASONABLE?
HRLM T3,JOBHSA##(T2) ;NO, MAKE BETTER
;HERE TO UPDATE THE KNOWN SEGMENT TABLE (IF NEEDED)
NOVJD: AOS (P) ;BUMP RETURN ADDRESS TO CALL+1
MOVE J,.CPJOB## ;RESTORE JOB NUMBER
TLNN P1,SV%SHR ;DID WE FIND A SHARABLE HIGH SEG?
JRST CPOPJ1## ;NO, THEN, EXIT TO CALL+3
PUSHJ P,FNDSMM ;IS THIS AN ACTIVE SEGMENT?
JRST STONAM ;NO, GO STORE NAME OF SHARABLE HIGH SEG
; AND EXIT TO CALL+3
SOS (P) ;YES, WE MUST UNDO THE AOS SO THAT WE
; WILL RETURN TO CALL+2
JRST GETH2C ;GO SET UP ITS PARAMETERS
GETH2: PUSHJ P,INPSEG ;FOUND, GO READ IN HIGH FILE
GETH2B:
IFN FTLOCK,<
JRST NOCORE ;LOW SEGMENT IS LOCKED
>
IFE FTLOCK,<
STOPCD .+1,DEBUG,SCR, ;++SEGMENT COULDN'T BE READ
>
PUSHJ P,FNDSMM ;SEE IF FILE NAME SNUCK INTO SEGMENT TABLE
; FOR OTHER USER WHILE IO GOING ON(UNLIKELY)
JRST STONAM ;USUALLY NOT FOUND
GETH2C: PUSH P,J ;FOUND, SAVE SHARABLE+NAMED HIGH SEG NO. TO BE
; SHARED BY THIS USER
;HERE TO CONNECT JOB TO KNOWN HIGH (SHARABLE) SEG (SEG # ON PD LIST)
SHARE: EXCH J,(P) ;GET SEG #, SAVE JOB #
PUSHJ P,VALSEG ;VALIDATE DORMANT SEGMENT
JRST [POP P,(P) ;NOT VALID
MOVE T1,.JDAT+SGAPPN## ;PPN SPECIFIED BY USER
MOVEM T1,.JDAT+SGALEN## ;STORE FOR LOOKUP
JRST GETH0] ;DO THE LOOKUP
EXCH J,(P) ;SAVE SEG#, GET JOB #BACK
PUSHJ P,KILHGC ;REMOVE PRESENT HIGH SEG FROM LOGICAL ADR.
; SPACE(DELETE CORE SPACE IF JUST ASSIGNED BY
; INPSEG SINCE NOT NAMED YET)
;HERE TO SEE IF THE HIGH SEGMENT WILL OVERLAP THE LOW SEGMENT
MOVE J,(P) ;NEW HIGH SEGMENT NUMBER
LDB T2,JBYHSO## ;PAGE NUMBER OF ORIGIN OF HIGH SEGMENT
LDB T1,IMGIN## ;CURRENT SIZE OF THE HIGH SEGMENT
ADD T1,T2 ;TOP PAGE OF THE HIGH SEGMENT
PUSHJ P,CKNZP## ;WILL HIGH AND LOW SEGMENTS OVERLAP?
JRST SHROVL ;YES, LOSE
POP P,J ;RESTORE NEW HIGH SEG. NUMBER
PUSHJ P,SEGSIZ## ;YES, T2=SIZE IN K OF HIGH SEGMENT
SKIPL JBTSTS##(J) ;DORMANT SEGMENT
CAMG T2,VIRTAL## ;YES, WILL ALLOWING IT TO BECOME ACTIVE MAKE VIRTAL
; NEGATIVE
PUSHJ P,GSZSG## ;NO, SEE IF LOW + NEW HIGH WILL STILL FIT
JRST SHRNRM ;TOO BIG
PUSHJ P,[IFN FTMP,<PUSHJ P,DWNMM##> ;GIVE UP THE MM FOR PAGING
PUSH P,T2
PUSH P,J
PUSHJ P,PAGLOW##
POP P,J
SETZB T2,T3 ;NO INCREASE
PUSHJ P,GSIZD## ;WILL IT FIT NOW?
JRST SHRNRM ;NO
JFCL ;YES, IF VIRTUAL
IFN FTMP,<PUSHJ P,UPMM##> ;GET THE MM BACK
SKIPGE JBTSTS##(J) ;DORMANT?
JRST T2POPJ## ;NO
PUSHJ P,VALSEG ;BE SURE IT'S
SKIPA ;STILL THERE
;NO
JRST T2POPJ## ;YES
POP P,T2 ;NOT THERE
POP P,(P) ;DO LOOKUP
JRST GETH0] ;OUT LOW SEG
MOVNS T2 ;NO,-NO. OF K IN DORMANT SEG
SKIPL JBTSTS##(J) ;IS THIS HIGH SEG ALREADY ACTIVE (SNA-1)?
ADDM T2,VIRTAL## ;NO, DECREASE COUNT OF VIRTUAL CORE AVAILABLE
MOVEI T1,JS.SFE ;SEGMENT IS FROM AN EXE FILE BIT
MOVSI T2,'EXE' ;ASSUME IT WAS
TDNE T1,JBTSTS##(J) ;WAS IT?
MOVEM T2,.JDAT+SGAEXT## ;YES, STORE EXTENSION FOR THE PROGRAM
PUSH P,J ;SAVE CURRENT HIGH SEGMENT NUMBER
MOVE J,.CPJOB## ;GET CURRENT JOB NUMBER
IFN FTMP,<
PUSHJ P,DWNMM## ;GIVE UP THE MM
>
PUSHJ P,CRESP0 ;CREATE THE CURRENT SECTION AND PUT PAGE 0 SECTION 0 IN IT
IFN FTMP,<
PUSHJ P,UPMM## ;GET THE MM BACK
>
MOVEI T2,0 ;ASSUME SECTION 0
PUSHJ P,GETSSN ;GET SECTION NUMBER
MOVE T2,T1 ;NOT 0 OR 1
DPB T2,JBYSG2## ;STORE IT FOR THIS USER
POP P,J ;RESTORE SEGMENT NUMBER
MOVEI T3,0 ;FLAG CALL IS GETSEG OR RUN UUO
; (SO THAT CONNECTING TO AN IDLE SEG
; WILL BE CHECKED).
;HERE FROM CORE AND REMAP UUOS - WITH T3 NON-ZERO AS A FLAG
; NOT TO CHECK FOR CONNECTING TO AN IDLE HI-SEG (SINCE IT LOOKS LIKE
; ONE BUT CANNOT BE)
SHARE1::MOVE T1,.USJOB ;CURRENT JOB NUMBER
PUSHJ P,INCSHR ;BUMP SHARE COUNT FOR SEGMENT AND UPDATE JBTSGN
MOVSI T2,SNA ;MAKE SURE THIS HIGH SEG IS FLAGGED AS IN USE
; IE SEG IN SOME USER'S LOG. ADR. SPACE
IORB T2,JBTSTS##(J) ;MAY HAVE BEEN JUST ASSIGNED OR DORMANT
MOVE U,JBTSTS##(T1) ;JOB STATUS WORD
TLNN T2,JXPN!SWP ;IS HIGH SEG IN CORE AND NOT EXPANDING?
JRST SHARE3 ;YES, GO INCREMENT IN CORE COUNT FOR JOB
TLNN U,JXPN ;JOB WAITING TO EXPAND LOW OR HIGH SEG?
TLNE T2,JXPN ;NO, IS HIGH SEG WAITING TO EXPAND?
JRST SETRL0 ;YES, WAIT TILL HIGH SEG IN CORE TOO
MOVSI U,SWP ;NO, SET SWP BIT SO JOB CANNOT BE RUN
IORM U,JBTSTS##(T1) ;UNTIL HIGH SEG IS SWAPPED IN
MOVSI U,(JS.NNQ) ;ICPT IGNORED WITH SWP SET, DONT ASSIGN
IORM U,JBTST2##(T1) ; IF JUST HIGH SEG COMES IN
JRST SETRL2 ;GO CALL SCHEDULER
;HERE IF HIGH SEG ALREADY IN-CORE (CORE, REMAP, RUN, GET SEG UUOS)
SHARE3: SKIPN T3 ;CORE OR REMAP (HI-SEG LOOKS IDLE BUT ISN'T)?
PUSHJ P,CHKIDL ;NO, CHECK TO SEE IF HI-SEG IS IDLE IN CORE
; IE IN-CORE COUNT 0 BUT IN SOME USER'S
; ADR SPACE WHO IS SWAPPED OUT OR DORMANT IN CORE
; (IE IN NO ONE'S LOGICAL ADR. SPACE)
;IF YES, DECREASE COUNT OF FREE CORE (CORTAL)
MOVE T1,.USJOB ;CURENT JOB NO. (FOR INCCNT)
PUSHJ P,INCCNT ;NO, INCREMENT HIGH SEG IN-CORE COUNT FOR THIS
; JOB(T1) IF NOT ALREADY INCREMENTED, RETURN
; WITH J = HIGH SEG NO.
PUSHJ P,CHKTAL ;CHECK CORTAL WITH CORTAB, HALT IF DIFF.
TLNE U,JXPN ;IS JOB (LOW SEG) EXPANDING?
JRST SETRL0 ;YES, SWAP JOB OUT
; (CAN HAPPEN IF CORE UUO WHICH
; ASSIGNS HIGH SEG AND EXPANDS LOW SEG)
IFN FTMP,<
PUSHJ P,INTLVL## ;DON'T RETURN MM AT INTERRUPT LEVEL (VIRCHK)
PUSHJ P,TGVMM## ;GIVE UP MM IF OWNED
>
JRST SETRL1 ;NO, SET HARD AND SOFT RELOC AND RETURN
;HERE WHEN NOT ENOUGH ROOM IN SYSTEM TO ALLOW USER TO USE SEG
;T1=NO. WORDS-1=SUM OF BOTH SEGS-1
SHROVL: SKIPA T3,[EXP LOHERR] ;HIGH AND LOW SEGMENTS OVERLAP
SHRNRM: MOVEI T3,NECERR ;NOT ENOUGH CORE
HRRZ T2,.JDAT+JOBPD1## ;GET RETURN PC IN CASE THIS IS RUN UUO
CAMLE T2,.CPREL## ;IS IT IN THE HIGH SEG WHICH IS NOW GONE ?
HRRZS .JDAT+JOBPD1## ;YES, TURN OFF USER MODE FLAG, SO ERROR
; WILL NOT LOOK FOR HALT AFTER UUO
PUSH P,T1 ;SAVE NO. OF WORDS-1 NEEDED FOR MESSAGE IN NROOM
PUSH P,T3 ;SAVE ERROR CODE
IFN FTMP,<
PUSHJ P,TGVMM## ;GIVE UP THE MM IF OWNED
>
PUSHJ P,SETMAP## ;GO SET HARDWARE RELOC. SO JOB
; CANNOT REFERENCE HIGH SEG
POP P,T1 ;T1 = ERROR CODE
JRST NROOM## ;GO PRINT MONITOR MESSAGE AND STOP JOB
; OR ERROR RETURN TO LOW SEGMENT - 0(P)
; HAS #WORDS-1
; (UNLESS UUO HAS A HALT FOLLOWING IT)
STONAM: MOVE T3,.CPJOB## ;CURRENT JOB NUMBER
MOVSI J,SHRSEG ;FLAG THIS USER AS USING A SHARABLE HIGH SEG
IORB J,JBTSGN##(T3) ;AND SETUP HIGH SEG NUMBER
PUSH P,T1 ;SAVE PPN
PUSH P,T2 ;SAVE FILE NAME
SKIPE T1,.JDAT+SGAPPN## ;PPN OR POINTER TO PATH USER TYPED
TLNE T1,-1 ;A PATH POINTER?
JRST STON0 ;NO, STORE INFO AND EXIT
SKIPE .JDAT+JOBUAL## ;IS THERE A PATH? I.E., DEVICE WAS DSK
SKIPN .JDAT+JOBUAL##+3 ;YES, SFD'S INCLUDED IN THE PATH?
JRST STON0 ;NO
MOVEI T2,MAXLVL##+2 ;ROOM FOR THE FULL PATH TERMINATED BY A 0
PUSHJ P,GETWDS## ;GET THAT MUCH FREE CORE
STOPCD TTPOPJ##,JOB,CSP, ;++CANNOT STORE PATH
MOVEM T1,-1(P) ;SAVE ADDRESS OF THE FULL PATH
SETZM MAXLVL##+1(T1) ;INSURE PATH BLOCK IS TERMINATED BY A 0
HRLI T1,.JDAT+JOBUAL##+2 ;ADDRESS OF DATA RETURNED BY THE PATH UUO
MOVEI T2,MAXLVL##(T1) ;NUMBER OF WORDS TO BLT
BLT T1,(T2) ;COPY THE FULL PATH TO FREE CORE
STON0: POP P,JBTNAM##(J) ;STORE THE HIGH SEGMENT NAME
POP P,JBTPPN##(J) ; AND THE DIRECTORY OR POINTER TO THE PATH.
MOVEM U,JBTDEV##(J) ;STORE DEVICE NAME(STR) FOR HIGH SEG
MOVSI T1,SHRSEG ;ALSO FLAG HIGH SEG ASSIGNED
IORM T1,JBTSTS##(J) ;BY INPSEG AS SHARABLE FOR OTHER USERS
MOVE T1,.JDAT+SGADAT## ;GET E+2
LDB T1,[POINT 9,T1,8] ;GET ACCESS RIGHTS FROM LOOKUP E+2
DPB T1,[POINT 9,JBTSTS##(J),HSAPOS] ;AND STORE IN MONITOR WITH HIGH
; SEG STATUS
HLRZ T1,.JDAT+SGAEXT## ;EXTENSION
MOVEI T2,JS.SFE ;SEGMENT FROM AN EXE FILE BIT
CAIN T1,'EXE' ;DID THE SEGMENT COME FROM AN EXE FILE?
IORM T2,JBTSTS##(J) ;YES, REMEMBER THAT
MOVSI T1,SYSSEG## ;YES, FLAG AS GOTTEN FROM SYS
TLNE F,SYSDEV ;FROM SYS
IORM T1,JBTSTS##(J)
SETRL0: MOVE J,.USJOB ;CURRENT JOB NUMBER TO BE EXPANDED
; (NOT HIGH SEG)
PUSHJ P,XPANDH## ;FLAG THIS USER AS TRYING TO EXPAND(SWP=1)
; SO THAT THIS NEW HIGH SEG WILL BE SWAPPED IN
SETRL2:
IFN FTMP,<
PUSHJ P,DWNMM## ;ALL DONE, RETURN THE MM
>
PUSHJ P,WSCHED## ;WAIT TILL IT IS SWAPPED IN(CALL SCHEDULER)
SETRL1:
IFN FTMP&FTKL10,<
PUSHJ P,CHKSWS## ;SEE IF ATTACHING TO A SHARABLE
; WRITEABLE HI SEG. IF SO, MAKE
; SURE ITS UNCACHED IN THIS JOBS MAP
>
MOVE J,.USJOB ;CURRENT JOB
MOVEI T1,JS.XOR
MOVSI T2,(JS.IGS) ;YES, GETSEG IN PROGRESS BIT
TDNE T1,JBTSTS##(J) ;EXECUTE ONLY FILE?
TDNN T2,JBTST2##(J) ;GETSEG IN PROGRESS ?
JRST SETRL3 ;NO
MOVSI T1,GTSSEG ;SEGMENT WAS GETSEGED BUT
IORM T1,JBTSGN##(J) ;YES, LIGHT GETSEGED BIT
SETRL3: PUSHJ P,EXONLY## ;IF EXECUTE ONLY PROTECT THE CORE IMAGE
AOS (P) ;SKIP RETURN (GETSEG,UCORHI,UREMAP)
PUSHJ P,SXOPFH## ;MAKE PFH CONCEALED IF GETSEG OF XO HI-SEG
PUSHJ P,STVSIZ## ;STORE CURRENT VIRTUAL SIZE OF BOTH SEGMENTS
MOVE J,.USJOB ;
PUSHJ P,HSVAD ;HI SEG LIMITS
DMOVEM T1,.USHSE ;SAVE FOR ADDRESS CHECKING
SKIPLE T1,JBTSGN##(J) ;IS THERE A REAL HIGH SEGMENT?
TLNE T1,SHRSEG ;YES-IS IT NON-SHARABLE?
JRST SETRLH## ;NO, REDO THE MAP
PJRST MAPHGH##
; FOR CURENT JOB AND RESTORE R AND J
;ROUTINE TO ADJUST USER'S CORE ARG. IN GET,R,RUN OR SAVE COMMANDS SO THAT
; THE ARG. SUPPLIED IS THE TOTAL OF BOTH THE LO & HI SEGS. IF THERE IS NO
; HI SEG THEN ARG. IS THE LO SEG SIZE AS IN NON-REENTRANT SYSTEMS.
; IF THERE ARE BOTH LO & HI SEGS AND THE ARG. IS LESS THAN THE HI SEG + 1K
; MANDATORY LO SEG SIZE THEN THE CORE ALLOCATION IS UNCHANGED.
;CALL MOVE J,JOB NO.
; PUSHJ P,ADJCOR
; ALWAYS RETURN WITH T1=HI SEG #,T2 & U DESTROYED
ADJCOR::SKIPG T1,JBTSGN##(J) ;IS THERE A HI SEG ?
POPJ P, ;EVIDENTLY NOT
HLRZ T2,JBTADR##(T1) ;GET ITS SIZE
SKIPE U,.JDAT+SGANEW## ;WAS AN ARG. TYPED OF 0 OR NOT AT ALL ?
SUBI U,1(T2) ;NO - COMPUTE LO SEG SIZE
SKIPG U ;MUST BE 1K OR GREATER!
POPJ P,
MOVEM U,.JDAT+SGANEW## ;STORE IT
POPJ P, ;RETURN
; TO LOW SEG RELOC AND JOB NUMBER
;TRY TO READ IN NON-SHARABLE FILE WITH EXTENSION .HGH
TRYHGH: MOVE T1,DEVMOD(F) ;LOOKUP FAILURE, SEE IF OTHER THAN NOT FOUND
TLNN T1,DVDSK ;WAS LOOKUP ON DISK?
JRST TRYHG2 ;NO, MUST BE A NOT FOUND
HRRZ T1,.JDAT+SGAEXT## ;PICK UP POSSIBLE ERROR CODE
CAILE T1,IPPERR ;FILE NOT FOUND OR NO UFD?
CAIN T1,SNFERR ;NO--NON-EXISTANT SFD?
JRST TRYHG2 ;YES--TRY .HGH
JRST NOFILE## ;REPORT ERROR
TRYHG1: MOVE J,.CPJOB## ;RESTORE J WHICH MAY HAVE BEEN CLOBBERED BY FILSER
; AND IS NEEDED BY COMCON FOR ERRORS
MOVE T1,DEVMOD(F) ;FAILURE FOR EXTENSTION .HGH
TLNN T1,DVDSK ;SAME AS BEFORE?
POPJ P, ;JUST NOT FOUND!
HRRZ T1,.JDAT+SGAEXT## ;ERROR CODE
CAILE T1,IPPERR ;NO FILE OR NO UFD?
CAIN T1,SNFERR ;NO--NON-EXISTANT SFD?
POPJ P, ;FILE NOT FOUND!
JRST NOFILE## ;NO--GIVE ERROR
TRYHG2: MOVSS T1,.JDAT+SGAHGH## ;TRY LOOKUP WITH EXTENSION .HGH
PUSHJ P,SGH1 ;SET EXT AND E+3 OF LOOKUP BLOCK
; FOR DTA OR DSK
PUSHJ P,LUPFIL ;LOOKUP WITH EXT .HGH
JRST TRYHG1 ;NOT FOUND, NO HIGH SEG RETURN FROM GETSEG
IFN FTLOCK,<
PUSHJ P,INPSEG ;TRY TO READ IN THE HIGH SEGMENT
JRST NOCORE ;ERROR, LOW SEGMENT IS LOCKED SO CAN'T
; ASSIGN CORE FOR THE HIGH SEGMENT
JRST CPOPJ1## ;HIGH SEGMENT READ IN, GIVE OK RETURN
NOCORE: HRRZ T2,.JDAT+JOBCOR## ;AMOUNT OF CORE
PUSH P,T2 ;ERROR REPORTER EXPECTS ARG. ON STACK
JRST NOROOM## ;REPORT THE ERROR
> ;END IFN FTLOCK CONDITIONAL
;ROUTINE TO READ IN A HIGH FILE INTO TOP OF LOW SEG AND REMAP
;LOOKUP MUST HAVE BEEN ALREADY BEEN DONE
;CALL: MOVE R,XWD PROTECTION, RELOCATION FOR LOW SET
; PUSHJ P,INPSEG
; RETURN1 - NO HIGH FILE,
; RETURN2 - HIGH FILE READ IN
; C(J)=JOB NUMBER
;CALLED FROM TRYHGH AND GETH1
INPSEG: MOVE J,.CPJOB## ;GET JOB NUMBER (IT MAY HAVE BEEN CLOBBERED BY FILSER)
IFN FTLOCK,<
MOVSI T2,NSHF!NSWP ;CANNOT ASSIGN CORE IF THE JOB IS LOCKED
TDNE T2,JBTSTS##(J) ;IS IT LOCKED?
JRST [MOVEI T1,SNSERR ;SEGMENT NOT ON SWAPPING SPACE ERROR
POPJ P,] ;ERROR RETURN
> ;END IFN FTLOCK CONDITIONAL
SKIPN T1,.USREL ;HIGHEST RELATIVE ADDRESS IN THE LOW SEGMENT
MOVE T1,.CPREL## ;HIGHEST REL(USER) ADR IN LOW SEG FOR CURRENT USER
TRO T1,PG.BDY## ;MAKE EVEN 1K-1(SHOULD BE 140) SO CAN USE REMAP UUO
; OR USER'S LOW SEG IF RUN OR GETSEG UUO
HRRM T1,.JDAT+SGALEN## ;STORE ADR-1 OF IOWD FOR READING IN
; HIGH FILE JUST ABOVE END OF CURRENT LOW SEG
MOVE T3,DEVMOD(F) ;DEVICE CHARACTERISTICS
TLNE T3,DVMTA ;MTA?
JRST INPMAG ;YES, GO DO SOME SPECIAL STUFF
HLRE T2,.JDAT+SGALEN## ;-FILE LENGTH FROM DIRECTORY LOOKUP
JUMPL T2,INPSE2 ;GO IF NEGATIVE WORD COUNT
JUMPE T2,GETERR## ;ERROR IF ZERO LENGTH
LSH T2,BLKLSH## ;CONVERT BLOCKS TO WORDS
MOVNS T2 ;NEGATIVE WORD COUNT
HRLM T2,.JDAT+SGALEN## ;STORE WORD COUNT IN IOWD
INPSE2: SUB T1,T2 ;FIRST ADR-1 PLUS(-MINUS) LENGTH YIELDS:
; LAST USER LOC TO BE READ INTO
PUSHJ P,GETCOR## ;ASSIGN ENOUGH CORE FOR LAST WORD OF HIGH FILE
; RETURN ONLY IF OK
INPUT 0,SGALEN## ;READIN HIGH FILE
PUSHJ P,SGIOCK## ;ANY ERRORS?
MOVE T3,DEVMOD(F) ;DEVICE CHARACTERISTICS
TLNE T3,DVMTA ;MTA?
JRST INPMG2 ;YES, DO STUFF WHICH IS DONE ON LOOKUP FOR
;DIRECTORY DEVICES
;INSPE3 IS CALLED AS A SUBROUTINE
;FROM GETEXE IN SEGCON IF EXE FILES
;ARE SUPPORTED
INPSE3: HRRZ T1,.JDAT+SGALEN## ;GET HIGHEST USER ADR IN ORIGINAL LOW SEG
EXCTUX <LDB T2,[POINT 9,.JBHDA##(T1),17]>
LSH T2,P2WLSH##
HRL T1,T2
MOVE J,.CPJOB## ;INPUT CLOBBERS J
PUSHJ P,UREMA0 ;DO REMAP UUO
JRST [MOVEI T1,LOHERR ;LOW SEGMENT OVERLAPS HIGH SEGMENT
POPJ P, ;ERROR RETURN
]
JRST CPOPJ1## ;RETURN, CALLI UUO SETS JOB NO IN J
INPMAG: MOVNI T2,MTSIZ## ;LENGTH OF A MAGTAPE RECORD
HRLM T2,.JDAT+SGALEN## ;SET TO READ 1ST RECORD OF FILE
JRST INPSE2 ;GO READ IT
INPMG2: TRNE S,IODEND ;EOF?
IFE FTLOCK,<
POPJ P,
>
IFN FTLOCK,<
JRST TPOPJ## ;YES, THERE IS NO HIGH SEGMENT
>
MOVE T1,.JDAT+SGALEN## ;NO, THERE IS A HIGH SEGMENT
PUSH P,T1 ;SAVE ORIGINAL IOWD
MOVEI T1,JOBHRN##+1(T1) ;LENGTH OF HIGH SEG
EXCTUX <HLRZ T1,@T1>
JUMPE T1,INPMG4 ;JUMP IF NULL HIGH SEGMENT
CAIG T1,MTSIZ##
JRST INPMG3 ;WHOLE FILE WAS 1 RECORD
MOVNM T1,T2 ;-WORD COUNT
HRL T2,(P) ;ADDRESS OF START OF 1ST RECORD
ADD T2,[XWD MTSIZ##,MTSIZ] ;INCREMENT OVER 1ST RECORD
MOVSM T2,.JDAT+SGALEN## ;NEW IOWD
HRRZ T2,0(P) ;GET ADDRESS OF FIRST RECORD OF HIGH SEG
ADD T1,T2 ;HIGHEST ADDRESS NEEDED
PUSHJ P,FNDPDS## ;TAPSER WIPES W
PUSHJ P,GETCOR## ;GET THE CORE
INPUT SGALEN## ;READ THE REST OF THE FILE
PUSHJ P,SGIOCK## ;ANY ERRORS?
INPMG3: STATO IOTEND+IODEND ;MAGTAPE AT END OF TAPE OR END OF FILE?
MTAPE 16 ;NO, SKIP OVER THE EOF
SETSTS DR ;RESET THE EOF BIT
POP P,.JDAT+SGALEN## ;RESTORE THE ORIGINAL IOWD
JRST INPSE3 ;AND CONTINUE
INPMG4: MTAPE 16 ;SKIP TO EOF
POP P,T1
IFE FTLOCK,<
POPJ P,
>
IFN FTLOCK,<
PJRST TPOPJ##
>
;ROUTINE TO CHECK IF HIGH SEG ABOUT TO BE SHARED WAS IDLE OR DORMANT
;IF YES, THE COUNT OF FREE+DORMANT+IDLE CORE IS DECREASED
;CALL: MOVE J,HIGH SEG NUMBER
; PUSHJ P,CHKIDL
;CALLED FROM GETSEG AND FININ
CHKIDL: PUSHJ P,CHKLKH ;CHECK FOR DORMANT OR IDLE (UNLOCKED)
POPJ P, ;NO, CORTAL ALREADY ADJUSTED
LDB T1,IMGIN## ;SIZE IN PAGES
MOVNS T1 ;-NO. OF PAGES IN CORE
ADDM T1,CORTAL## ;YES, THEN DECREASE COUNT OF FREE+DORMANT+IDLE
; CORE SINCE THIS HIGH SEG WILL NOT BE IDLE
POPJ P, ; ANY MORE
;SUBROUTINE TO CHECK FOR CORE ASSIGNED TO A DORMANT OR UNLOCKED
; IDLE SEGMENT SO THAT CORTAL MAY BE ADJUSTED PROPERLY
CHKLKH: MOVE T1,JBTSTS##(J) ;GET HIGH SEGMENT STATUS
TRNN T1,ICCMSK ;DORMANT OR IDLE?
SKIPN JBTADR##(J) ;AND IN CORE?
POPJ P, ;NO
TLNN T1,NSWP ;NO, IDLE - LOCKED?
AOS (P) ;YES, SKIP RETURN
POPJ P, ;NO
;ROUTINE TO SETUP LOWER CORE FOR LOOKUP OR ENTER FOR HIGH FILE
;CALL: LH OF SGAHGH(R) SET TO FILE EXT FOR HIGH SEG
; PUSHJ P,SGH
; SETUP SGALEN TO -1 IF DTA OR MTA, PROJ R IF DSK
SGH: MOVE T1,.JDAT+SGAHGH## ;SETUP EXTENSION(FOR HIGH FILE SHR OR HGH)
SGH1: HLLZM T1,.JDAT+SGAEXT## ;STORE EXTENSION FOR LOOKUP ORENTER
MOVEI T1,-1 ;SET SGALEN TO -1 IF DEVICE NOT DISK
; (FIRST REL LOC-1 DUMPED FROR HIGH SEG)
JRST SG4## ;OTHERWISE SET TO PROJ,R NO.
;ROUTINE TO DELETE A FILE, SO SUBSEQUENT GET WILL NOT BE CONFUSED
;USED BY SAVE AND SSAVE (NOT BY GET)
;CALL: HRLI T1, EXTENSION (.LOW,.SHR,.HGH, OR USER TYPED ARG)
; PUSHJ P,DELET
; ALWAYS RETURN
DELET: PUSHJ P,SGH1 ;SETUP EXTENSION, AND E+3 IN DIRECTORY BLOCK
PUSH P,DEVPPN(F)
LOOKUP 0,SGANAM## ;LOOKUP FILE
JRST TPOPJ## ;NOT FOUND
CLOSE 0, ;CLOSE SO RENAME WILL WORK
POP P,T1
CAMN T1,DEVPPN(F) ;DON'T DELETE IF NOT SAME PPN
RENAME 0,SGAREN## ;DELETE FILE
JFCL ;IGNORE IF CAN'T, WE TRIED
POPJ P, ;RETURN
;ROUTINE CALLED AFTER A HIGH OR LOW SEG SWAP IN READ ERROR
;CLEAR HIGH SEG NAME, SO NO NEW USERS WILL SHARE
;CALL: MOVE J,HGIH OR LOW SEG NO.
; PUSHJ P,SEGERR
; ALWAYS RETURN WITH J=JOB NUMBER
SEGERR::CAIG J,JOBMAX## ;LOW SEG?
POPJ P, ;YES
MOVE T1,JBTSTS##(J) ;NO, HAS THE ERROR BEEN DETECTED FOR THIS HIGH SEG
TLNN T1,SERR ; ON A PREVIOUS SWAPPING?
PUSHJ P,SWPREC## ;NO, RECORD ERROR AND DECREASE OF VIRTUAL CORE
MOVSI T1,SERR ;SET HIGH SEG ERROR BIT
IORM T1,JBTSTS##(J) ;SO SPACE WILL NEVER BE RETURNED BY SERSWP
SETZM JBTNAM##(J) ;CLEAR HI SEG NAME SO NO NEW USER WILL SHARE
MOVE J,JBTSWI##(J) ;RETURN JOB NUMBER ASSOCIATED WITH HIGH SEG
POPJ P,
;SUBROUTINE TO CALCULATE THE STARTING VIRTUAL
; ADDRESS IN A HIGH SEGMENT AND THE HIGHEST
; LEGAL ADDRESS IN THE SEGMENT
;CALLING SEQUENCE:
; MOVE J,JOB NUMBER
; PUSHJ P,HSVAD
;RETURNS HERE, T1=HIGHEST LEGAL ADDRESS, T2=
; STARTING VIRTUAL ADDRESS
HSVAD:: PUSHJ P,SAVE2## ;SAVE P1-P2
PUSH P,J ;SAVE JOB NUMBER
HRRZ P1,.USREL
SKIPN P1 ;HIGHEST ADR. IN LOW SEG
HLRZ P1,JBTADR##(J) ;LOW SEG PROTECTION
MOVE J,JBTSGN##(J) ;HIGH SEGMENT #
MOVEI P2,377777 ;ASSUME AT 400000
TRNE P1,400000 ;IS IT?
MOVE P2,P1 ;NO, ABOVE LOW SEG
AOS T2,P2 ;T2 = STARTING V.A.
JUMPLE J,HSVAD1 ;SPY SEG. (ALWAYS STARTS AT 400000)
HRRZS J ;CLEAR LEFT HALF JUNK (MAY BE IN SECTION 1)
LDB T2,JBYHSO## ;PAGE NUMBER WHERE HIGH SEGMENT ORIGINS
LSH T2,P2WLSH## ;CONVERT TO STARTING ADDRESS
HSVAD1: SKIPL T1,J ;SPY SEG?
TLOA J,(1B0) ;NO, MAKE A USABLE INDEX OUT OF J
JRST HSVAD4 ;DON'T GO AFTER JBTADR WHEN SPYSEG
HLRZ T1,JBTADR##(J) ;NO, SIZE OF HI. SEG.
TRNE J,-1 ;ANY HIGH SEG?
SKIPE T1 ;YES, JBTADR NON-ZERO?
JRST HSVAD4 ;YES PROCEED.
TLNN J,SHRSEG ;SWAPPED OUT, IS IT SHARABLE?
JRST HSVAD3 ;NO
LDB T1,IMGIN## ;YES, USE IMGIN.
LSH T1,P2WLSH## ;(CAN'T BE VIRTUAL)
SOJA T1,HSVAD4 ;..
HSVAD3: MOVE T1,.USHSE ;NON-SHARABLE
JRST JPOPJ## ;GET FROM UPMP
HSVAD4: HRRZS T1 ;CLEAR POSSIBLE SPYSEG BIT
SKIPE T1 ;SKIP IF NO HI. SEG.
ADDI T1,(T2) ;T1 = HIGHEST ADR.
JRST JPOPJ## ;RETURN
;ROUTINE TO GET A NEW-STYLE SAVE FILE:
;
;
;AC USAGE:
;
; AC CONTENTS
;
; P1 LH = FLAGS
; RH= POINTER TO CURRENT DIRECTORY
;
; P2 LH = CURRENT FILE PAGE # FOR INPUT FILE
; RH = DIRECTORY LENGTH COUNTER
;
; P3 1ST WORD OF CURRENT DIRECTORY ENTRY
;
; P4 2ND WORD OF CURRENT DIRECTORY ENTRY
;
;
;IT IS POSSIBLE (THOUGH UNLIKELY) THAT THERE ARE MORE THAN ONE
; DIRECTORY PAGE WHICH HAS TO BE READ. IN THAT CASE, ALL OF THEM
; (THERE MUST BE NO MORE THAN THREE) ARE READ IN INITIALLY BEFORE
; ANY PROCESSING OF THE SAVE FILE BEGINS. THE POINTER TO
; THE 2ND DIRECTORY PAGE IS KEPT IN SGANAM, THE POINTER TO THE 3RD
; PAGE IS IN SGAEXT. WHEN THE PROCESSING OF THE 1ST DIRECTORY PAGE
; IS COMPLETED, THE PAGE IN P1 IS DESTROYED, THE ONE IN
; SGANAM IS MOVED TO P1, AND SGAEXT IS MOVED TO SGANAM.
;
;
;IT ALSO MAY OCCUR THAT A PAGE WHICH IS ABOUT TO BE READ
; IN FROM THE SAVE FILE IS GOING TO OVERLAP ONE OF THE
; DIRECTORY PAGES. IN THAT CASE, THE DIRECTORY PAGE IS MOVED
; TO A FREE PAGE, AND THE NEW PAGE IS READ IN WHERE THE DIRECTORY
; PAGE USED TO BE.
;
;
;THE BASIC ALGORITHM IS AS FOLLOWS:
;
; 1 ) READ IN DIRECTORY PAGE(S) AND STORE POINTER(S) TO IT
; 2 ) COMPUTE # OF PAGES IN CORE IMAGE, AND RANGE OF HIGH SEG
; 3 ) (NON-VM) ALLOCATE CORE FOR ENTIRE FILE AND MOVE DIRECTORY TO TOP OF CORE
; 4 ) GET A DIRECTORY ENTRY
; 5 ) (VM) MOVE DIRECTORY PAGE IF NEW ENTRY WILL OVERLAP IT.
; 6 ) (VM) ALLOCATE CORE FOR PAGES.
; 7 ) INPUT PAGES FROM FILE
; 8 ) (VM) IF FILE GREATER THEN PHYSICAL LIMIT, PAGE OUT PAGES
; 9 ) IF MORE ENTRIES IN DIRECTORY, GO TO STEP 3.
;10 ) (NON-VM) GET RID OF EXTRA CORE, IF NECESSARY, AND CLEAR DIRECTORY (KA ONLY).
;11 ) PERFORM REMAP IF HIGH SEG WAS READ IN
REPEAT 0,<
***** EXPLANATION OF "GET" FOR EXE FILES *****
The algorithm to get an EXE file is straightforward in the
simple case, and quite complicated in some rare cases. The
primary problem is obviously the placement and manipulation
of the directory.
For VM systems, the directory can be longer than one page;
for non-VM systems, we have restricted this length to one
page (however, this restriction can be changed in the future
if customer reaction demands it).
For non-VM systems, the directory is initially read into
page 1 on a GET. On a GETSEG, it is read into the next page
above the existing low seg (on a KA, this means that two
extra pages must be allocated).
For VM-systems, the entire directory is read into as many
pages as is necessary (pointers to the directory pages are
kept in P1, and the first two words of the user's shadow
AC's). As the file pages are read into core later, these
directory pages are shuffled around if necessary, in order
to avoid being destroyed by the incoming pages. As each
directory page is scanned, it is removed from the page map
to make room for the file pages. The only exception to this
rule is when the file fits precisely into available core, in
which case the last file page is read in over the last
directory page.
For non-VM systems, the core allocation algorithm is quite
different from that on VM-systems. The technique chosen was
to allocate all required core before any part of the file is
read in, and then to BLT the directory to the top of that
core. There were two other algorithms which were considered
but rejected for the following reasons:
1 ) Keep directory in user AC's
-eliminates possibility of zero-compression
because directory must be kept very short
-eliminates full file transportability
between systems
2 ) Allocate core on a per-directory-entry basis,
get one extra page of core each time, and move
directory to free core above each core block
-requires excessive memory management
overhead
-requires (possibly) many useless BLT's
-eliminates possibility of files as large as
CORMAX
The core allocation algorithm is complicated by the
difference between units of allocation of the KA/KI, and the
possibility that the operation being performed may be a
GETSEG. Also, for very small files (e.g. those which only
contain page zero), extra pages must be allocated for page
zero (because input cannot be done directory into page zero)
and for the directory. The core allocation algorithm then
becomes:
1 ) On a GETSEG, allocate # of pages in high seg
minus one (minus two on KA). However, on KA's if
the high seg is less than three pages long, no
extra core must be allocated.
2 ) On a GET, allocate total # of pages in file
minus two (for directory and page zero). However,
allocate at least one page (for a grand total of
three pages) to allow for moving of page zero and
the directory. These extra pages are later
flushed.
The basic processing of the file pages is almost identical
for non-VM and VM systems with the following exceptions:
1 ) page 0 is read into page 1 and BLTed down
for non-VM, and into a random free page for VM.
Only those locations above JOBDDT## are moved down
into physical page zero.
2 ) VM must be able to read a page from the file
immediately after creating it in order to page it
out if a user's physical limit is to be exceeded
by the file. In most cases, though, all core
pages for a given directory descriptor are created
before any of the corresponding file pages are
read in.
3 ) VM systems read the high seg directly into
the process page number specified in the file
directory. Non-VM systems maintain a moving
pointer (in the left half of SGAHGH) which points
to the next low seg page into which the high seg
is to be read. This pointer is contually updated
as each block of the high seg is read in (the high
seg may have more than one directory descriptor
because of allocated-but-zero pages). Therefore,
the process page number is essentially ignored.
4 ) VM systems must delete the directory after
processing unless the last page was read in over
it. On non-VM KI systems, the directory is
guaranteed to be overwritten by the last page read
in. On non-VM KA systems, this also occurs if the
number of pages in the file was even. If it was
odd, the directory remains intact and must be
cleared to zeroes.
Please notE that EXE files are not supported on
DECtape at all. This is due to the inherent
difficulties in doing so and the fact that EXE
files are not transportable between certain
devices anyway. Also, EXE files which reflect
"virtual" core images are not supported on
Magtape.
>;END OF REPEAT 0
;ROUTINE TO READ IN PART OR ALL OF AN "EXE" SAVE FILE
;
;CALL:
; MOVSI P1,FLAGS
; PUSHJ P,GETEXE
; HERE
;
;
;FLAGS: (THESE ARE DEFINED IN COMCON)
;GTLOW GET THE LOW SEGMENT
;GTHGH ;GET THE HIGH SEGMENT
;GTBTH ;GET BOTH SEGMENTS
;FIRST, WE WILL READ IN ALL THE DIRECTORY PAGES FOR THE SAVE FILE.
;WHEN THIS PAGE OF CODE IS THRU, THE DIRECTORIES WILL BE IN CORE
; AND THE POINTERS TO THEM (OR "IT") WILL BE IN P1,P2,P3.
GETEXE::PUSH P,.JDAT+JOBUAL##+3 ;THE OUTSIDE WORLD IS SENSITIVE TO THESE
PUSH P,.JDAT+JOBUAL##+4 ; LOCATIONS
PUSH P,.JDAT+JOBUAL##+5 ; ..
PUSH P,.JDAT+JOBUAL##+6 ; ..
SETZB P2,.JDAT+SGAEND## ;CLEAR IOWD
SETZB P3,DEVISN(F) ;CLEAR AC'S WHERE DIRECTORY POINTERS WILL GO
DMOVEM P2,.JDAT+SGANAM## ;DIDN'T HAVE TO READ OVER THE DIRECTORY PAGE
PUSHJ P,GTFREP## ;GET A FREE PAGE FOR DIRECTORY
JRST NEED1P ;CAN'T--REPORT ERROR
PUSHJ P,CRPAGE## ;CREATE THIS PAGE
CAIA
JRST MORDR2
MOVE T1,.USUAC+4 ;CHECK WHAT IT IS
MOVSI T2,(UP.MPF)
TDNN T2,.USBTS
CAMN T1,['GETSEG'] ;A GETSEG?
CAIA
JRST NEED1P ;NO--ABORT USER
PUSHJ P,PAGLOW## ;YES--PAGE OUT THE LOW SEG
PUSHJ P,CRPAGE## ;TRY TO CREATE PAGE AGAIN
JRST NEED1P ;COULN'T--ABORT USER
MORDR2: LSH T1,P2WLSH## ;MAKE INTO AN ADDRESS
HRRM T1,P1 ;PRESERVE IT
PUSHJ P,F1IOWD ;SET UP AN IOWD FOR THIS PAGE
PUSHJ P,RDSTUF ;READ 1ST PGE FROM FILE INTO THIS PAGE
HRR M,P1 ;GET ADDRESS OF DIRECTORY
PUSHJ P,GETWDU## ;GET WORD FROM DIRECTORY
HLRZ T2,T1 ;GET CODE
CAIE T2,SV.DIR ;IS THIS THE DIRECTORY?
JRST NOTEXE ;NO, REPORT ERROR
HRRZ T3,T1 ;GET # OF WORDS IN DIRECTORY
LSH T3,WXPLSH ;=# OF DIRECTORY PAGES -1
TRNN T1,1 ;LENGTH MUST BE ODD
JRST BADDIR ;EVEN LENGTH
CAILE T3,^D64
JRST EXEBIG ;IT ISN'T, FLUSH USER
PUSHJ P,GTDIRW ;GET 1ST WORD FROM DIRECTORY
MOVEI P2,-1(T1) ;SAVE LENGTH FOR LATER
JUMPE P2,BADDIR ;DON'T ALLOW NULL DIRECTORIES
;FALL THRU TO NEXT PAGE...
;STILL IN IFN FTEXE CONDITIONAL...
;WE MUST NOW COMPUTE HOW MUCH CORE WE ARE GOING TO NEED FOR THESE
; SEGMENTS, AND THE UPPER AND LOWER LIMITS OF THE HIGH SEG.
;WE WILL DO THIS BY CYCLING THRU THE DIRECTORY AND ADDING UP
; THE NUMBER OF PAGES THAT WE WILL NEED TO ALLOCATE FOR
; THIS FILE.
;
;P1 HAS A POINTER TO THE 1ST DIRECTORY PAGE IN ITS RH
;SGANAM HAS POINTER TO 2ND PAGE (IF ANY)
;SGAEXT HAS POINTER TO 3RD PAGE (IF ANY)
;
;
;THIS ROUTINE ASSUMES THAT ALL ENTRIES FOR THE HIGH SEG
; WILL APPEAR SEQUENTIALLY IN THE DIRECTORY IN INCREASING PAGE
; ADDRESSES. THAT IS, IF WE FIND A HIGH SEG ENTRY, THEN IF WE FIND
; ANOTHER HIGH SEG ENTRY LATER ON, THE SECOND SET OF HIGH SEG PAGES
; MUST BE CONTIGUOUS TO THE FIRST SET OF HIGH SEG PAGES.
;
;WE WILL USE T3 TO HOLD THE TOTAL # OF PAGES NEEDED
; AND T4 = START OF HISEG,,END OF HISEG
SETZB T3,T4 ;CLEAR OUT THESE AC'S
CKSIZ0: PUSHJ P,GTDIRE ;GET THE NEXT DIR ENTRY IN P3,P4
JRST CKSIZ3 ;NO MORE LEFT, WE ARE THRU
PUSHJ P,WANTIT ;BUT DO WE WANT THIS SEGMENT?
JRST CKSIZ0 ;NO, IGNORE IT
LDB T2,[POINT 9,P4,8] ;GET REPEAT COUNT
ADDI T3,1(T2) ;BUMP TOTAL PAGE COUNT
JUMPGE P3,CKSIZ0 ;DON'T CHECK LIMITS IF NOT HIGH SEG
ADDI T2,(P4) ;COMPUTE LAST PAGE # IN THIS ENTRY
JUMPE T4,[HRL T4,P4 ;IF THIS IS THE 1ST HISEG ENTRY,
JRST CKSIZ1];SAVE START ADDR AND GO ON
MOVEI T1,1(T4) ;# OF NEXT CONTIGUOUS PAGE IN HIGH SEG
CAIE T1,(P4) ;IS THIS ENTRY CONTIGOUS WITH PREVIOUS
; HIGH SEG ENTRY?
JRST BADDIR ;NO, BAD FORMAT FOR DIRECTORY
CKSIZ1: HRR T4,T2 ;RESET HIGH SEG END PAGE #
JRST CKSIZ0 ;IT'S OK
;COME HERE WHEN WE HAVE FINISHED SCANNING
; THE DIRECTORIES. WE MUST NOW ROTATE THE DIRECTORY
; POINTERS UNTIL THEY ARE BACK IN THEIR ORIGINAL POSITION.
CKSIZ3: TRZ P1,EXESIZ-1 ;POINT CURRENT DIR POINTER TO START OF PAGE
TLZE P1,SV%DWO## ;MORE THAN ONE PAGE DIRECTORY?
PUSHJ P,[PUSHJ P,SAVT## ;IMPORTANT NUMBERS
PUSH P,P1 ; ..
USETI 1 ;BACK TO THE BEGINNING OF THE FILE
PUSHJ P,SGIOCK## ;MAKE SURE THERE WERE NO I/O ERRORS
HRRZ T1,(P) ;FOR IOWD
PUSHJ P,F1IOWD ;BUILD AND STORE THE IOWD
PUSHJ P,RDSTUF ;READ THE FIRST PAGE OF THE EXE DIRECTORY
MOVEI T1,1 ;NOW INDICATE NOT READING THE FILE SEQUENCIALLY (GTDIRW)
MOVEM T1,.JDAT+SGAEXT## ;CURRENT DIRECTORY POSITION
JRST P1POPJ##] ;CONTINUE
;FOR NON-VM SYSTEMS, WE MUST NOW ALLOCATE ENOUGH CORE FOR
; THE ENTIRE EXE FILE, AND MOVE THE DIRECTORY TO THE TOP OF THAT CORE.
; THE DIRECTORY WILL THEN BE OVER-WRITTEN BY THE LAST PAGE
; WHICH IS READ IN FROM THE FILE. HOWEVER, IF A LOW SEGMENT
; MUST BE GOTTEN, AND THE TOTAL # OF PAGES IN THE FILE IS LESS
; THAN 3, WE MUST ALLOCATE SOME EXTRA CORE BECAUSE PAGE ZERO MUST
; BE READ INTO PAGE 1 AND BLT'ED DOWN WITHOUT CLOBBERING THE
; DIRECTORY.
;
;FOR VM-SYSTEMS, WE MUST NOW DETERMINE IF THIS FILE WILL EXCEED
; THE USER'S PHYSICAL LIMIT AND SET SOME FLAGS APPROPRIATELY.
; ALSO, WE MAY HAVE TO PAGE OUT HIS LOW SEG ON A "VIRTUAL" GETSEG.
;
;WE WILL FIRST COMPUTE SOME VALUES WHICH WE WILL SAVE UNTIL THE
; REMAP WHEN THEY WILL BE NEEDED. THESE ARE AS FOLLOWS:
; SGAHGH = 1ST PAGE OF HIGH SEG,,LENGTH (IN PAGES) OF HIGH SEG
; SGALOW = # OF PAGES REQUIRED FOR ENTIRE FILE
;
;FOR VM SYSTEMS, THE STARTING ADDRESS OF THE HIGH SEG WILL
; BE THE ACTUAL USER VIRTUAL PAGE NUMBER FOR THE START
; OF THE HIGH SEG. FOR NON-VM SYSTEMS, THIS PAGE NUMBER WILL BE
; THE LOW SEG PAGE INTO WHICH THE HIGH SEG WILL BE READ,
; AND THEN REMAPPED TO ITS ACTUAL ADDRESS.
;
;
CKSIZ4: HLRZ T1,T4 ;GET 1ST PAGE OF HIGH SEG
SKIPE T1 ;IF NO HIGH SEG, DON'T SUBTRACT
SUBI T4,-1(T1) ;LAST-FIRST-1 YIELDS # OF PAGES IN HIGH SEG
MOVEM T4,.JDAT+SGAHGH## ;SAVE START,,LENGTH OF HIGH SEG
MOVEM T3,.JDAT+SGALOW## ; AND TOTAL PAGES IN CORE IMAGE
PUSHJ P,GTDIRW ;GET HEADER WORD FROM DIRECTORY
MOVEI P2,-1(T1) ;PUT LENGTH OF DIRECTORY ENTRIES IN P2
HRLI P2,1 ;SO THAT SKPBLK WILL SKIP THE DIRECTORY
MOVE J,.CPJOB## ;SET UP JOB NUMBER
PUSHJ P,FNDPDS## ;GET THIS GUY'S PDB
MOVE T3,.JDAT+SGALOW## ;CHECK # PAGES
PUSHJ P,GSIZI## ;IS THERE ROOM?
JFCL ;NO
TLO P1,GT%PLE## ;SET BIT TO INDICATE THAT THE
; PHYSICAL LIMIT IS EXCEEDED, SO WE
; WILL PAGE OUT ALL LOW SEG PAGES
; AS WE READ THEM IN LATER.
HLRZ T1,.PDCVL##(W) ;GET CURRENT VIRTUAL LIMIT
TLNE P1,GT%PLE## ;ANY ROOM PHYSICALLY?
JUMPE T1,NEEDNP ;NO, PUNT IF NO VIRTUAL AVAILABLE
CAMGE T1,.JDAT+SGALOW## ;IS THAT LESS THAN SIZE OF FILE?
JUMPN T1,NEEDNP ;NO, CAN'T POSSIBLY FIT FILE IN
MOVE J,.CPJOB## ;GET JOB NUMBER
PUSHJ P,SEGSIZ## ;GET LOWSEG SIZE
TLNE P1,GTMRG## ;THIS A MERGE?
JRST CKSIZ5 ;YES, DON'T SUBTRACT OUT PAGE 0
TLNN P1,GTLOW## ;IS THIS A GETSEG?
TLNN P1,GTHGH## ;(LOW OFF AND HGH ON)
SOS T2 ;NO, PAGE 0 WILL BE OVERWRITTEN
CKSIZ5: SUBI T2,UPMPSZ## ;SUBTRACT UPMP OUT ALWAYS
TLNN P1,SV%FUL## ;IF DIDN'T PAGE OUT DIRECTORY PAGE
SOS T2 ;DON'T INCLUDE IT EITHER
ADD T2,.JDAT+SGALOW## ;ADD TO NEW HIGH SEG SIZE
CAMGE T1,T2 ;SEE IF THERE'S ENOUGH ROOM
JUMPN T1,NTROOM ;NO
TLNN P1,GT%PLE##
SKIPE .USVRT ;IS THIS A VIRTUAL GUY?
MOVE T1,.USUAC+4 ;YES, CHECK WHAT THIS IS
MOVSI T2,(UP.MPF+UP.GET) ;GETTING GET OR PFH?
TDNE T2,.USBTS ;IF SO, PAGE OUT THE LOW SEG
TLZN P1,GT%PLE## ;BUT NOT PFH
CAMN T1,['GETSEG'] ;IS THIS A GETSEG?
PUSHJ P,PAGLOW## ;YES, PAGE OUT THE LOW SEGMENT
;THIS IS THE MAIN LOOP FOR DIRECTORY PROCESSING
;THIS LOOP FETCHES ONE DIRECTORY ENTRY AND PROCESSES ALL PAGES
; CONTAINED IN THAT ENTRY.
GTLOOP: PUSHJ P,GTDIRE ;GET NEXT DIRECTORY ENTRY
JRST GETFIN ;NO MORE, WE ARE THRU
PUSHJ P,WANTIT ;DO WE WANT THIS ENTRY?
JRST GTLOOP ;NO, IGNORE THIS DIRECTORY ENTRY
HRRZ T1,P1 ;GET CURRENT DIRECTORY POINTER
TLZ P1,GT%DAF## ;ASSUME PAGES DESCRIBED IN THIS POINTER WON'T
;OVERLAP DIR
PUSHJ P,CKRADR ;WILL IT BE OVERWRITTEN BY THESE PAGES?
PUSHJ P,MOVDIR ;YES, WE MUST MOVE IT
MOVE T1,DEVMOD(F) ;DEVICE CHARACTERISTICS
TLNN T1,DVDSK ;AS DISK?
TLO P1,GT%DAF ;NO, MUST DO ONE PAGE AT A TIME (NO RANDOM ACCESS)
;FALL THRU TO NEXT PAGE...
;STILL IN IFN FTEXE CONDITIONAL...
;COME HERE IF NO DIRECTORY PAGES ARE ABOUT TO BE OVER-WRITTEN
;WE CAN NOW READ IN THE SAVE FILE.
;IF THIS ENTRY CONTAINS PAGE ZERO, WE MUST DO SOME SPECIAL
; PROCESSING WHICH IS ON THIS PAGE. IF PAGE ZERO IS NOT
; WITHIN THIS ENTRY, WE SKIP TO THE MAIN LOOP AT "NOTP0".
;
;
TRNE P4,-1 ;IS THIS PAGE 0?
JRST NOTP0 ;NO
PUSHJ P,GTFREP## ;YES, WE CAN'T READ DIRECTLY
; INTO PAGE 0, SO WE MUST CREATE A
; DUMMY PAGE INTO WHICH WE WILL READ
; THIS DATA PAGE. THEN WE WILL MOVE
; THIS PAGE TO PAGE 0 AND EVERYTHING
; WILL BE OK.
JRST NEED1P ;COULDN'T GET FREE PAGE
PUSHJ P,CRPAGE## ;CREATE IT
JRST NEED1P ;COULDN'T
LSH T1,P2WLSH## ;PAGE ADDRESS
PUSH P,T1 ;SAVE PAGE ADDRESS FOR A SEC...
PUSHJ P,SKPBLK ;MAKE SURE WE'RE AT THE RIGHT PLACE
MOVE T1,(P) ;RESTORE ADDRESS
PUSHJ P,F1IOWD ;STORE THE IOWD
PUSHJ P,RDSTUF ;READ PAGE FROM SAVE FILE
HRLZ T1,0(P) ;PAGE ADDRESS IN LEFT HALF, 0 IN RH
ADD T1,[JOBUAL##+.JBLUL##,,JOBUAL##+.JBLUL##] ;SET UP BLT AC
TLNN P1,GTMRG## ;DON'T WIPE PAGE 0 ON A MERGE
EXCTUU <BLT T1,EXESIZ-1>
POP P,T1
TLNE P1,GTMRG## ;MERGING?
SKIPE .JDAT+.JBPFH## ;YES, ALREADY HAVE A PFH?
SKIPA T2,.JDAT+.JBPFH## ;NOT MERGE OR ALREADY HAVE A PFH
UMOVE T2,.JBPFH##(T1) ;MERGING PFH, GET ITS ADDRESS
MOVEM T2,.JDAT+.JBPFH## ;STORE ADDRESS OF PFH
TLNE P1,GTMRG## ;MERGE UUO?
SKIPN .JDAT+.JBDDT## ;YES, DDT ALREADY AROUND?
EXCTUX <SKIPA T2,.JBDDT##(T1)> ;NO, SET DDT'S ADDRESS
JRST HAVDR6 ;YES, ALL DONE
MOVEM T2,.JDAT+.JBDDT##
MOVEM T2,USRDDT## ;SAVE IT OVER CONTEXT SWITCH
UMOVE T2,.JBBPT##(T1) ;GET DDT'S UNSOLICITED BREAKPOINT ENTRY
MOVEM T2,.JDAT+.JBBPT## ;AND SET IT UP TOO
TLNE P1,GTMRG## ;MERGING?
JRST HAVDR6 ;ALL DONE WITH THE MERGE
SETZM .JDAT+.JBHSO## ;INITIALLY CLEAR JOBHSO
UMOVE T2,JOB41##(T1) ;RESTORE JOB41
MOVEM T2,.JDAT+JOB41##;
HAVDR6: PUSH P,T1 ;SAVE T1
TLNN P1,GTMRG## ;MERGING?
PUSHJ P,CRESP0 ;NO, CREATE THE SECTION AND COPY PAGE 0 TO IT
POP P,T1 ;RESTORE T1
PUSHJ P,ZAPPAG## ;DESTROY IT
JRST GTABRT## ;COULDN'T DO IT FOR SOME REASON
ADD P2,[1,,0] ;CURRENT LOCATION ON DEVICE
AOS P3 ;BUMP FILE PAGE #
ADD P4,[777000,,1] ;INCR. PROCESS PAGE NO, DECR COUNT
TLC P4,777000 ;IF ONLY PAGE 0, GO BACK FOR MORE
TLCN P4,777000
JRST GTLOOP
;IF MORE IN THIS DIRECTORY ENTRY, FALL THRU TO NEXT PAGE...
;COME HERE IF THE GROUP OF PAGES THAT WE ARE ABOUT TO FETCH
; FROM THE SAVE FILE DO NOT INCLUDE ANY OF THE DIRECTORY PAGES,
; OR PAGE ZERO.
NOTP0: PUSHJ P,SKPBLK ;POSITION OURSELVES ON THE DEVICE
LDB T3,[POINT 9,P4,8] ;GET REPEAT COUNT
PUSHJ P,GETSSN ;GET USE SECTION
JRST [REPEAT 0,<SKIPGE .USUSN ;COMMAND OR UUO?
JRST [DPB T1,[POINT 9,P4,26] ;UUO, DON'T RELOCATE
JRST NOTP00]> ;CONTINUE
LSH T1,S2PLSH##;SECTION NUMBER IN SECTION FIELD
ADD P4,T1 ;RELOCATE
JRST .+1] ;CONTINUE
NOTP00: HRRZ T1,P4 ;..AND PROCESS PAGE #
PUSH P,T3 ;SAVE REPEAT COUNT
NOTP01: PUSH P,T1 ;AND PAGE #
MOVE T2,.JDAT+SGANAM## ;THIS COULD BE THE DIRECTORY PAGE
CAIN T1,(T2) ;IS IT?
JRST NOTP02 ;YES, JUST SKIP IT - GETFIN WILL FIX IT UP
TLNE P3,SV%SHR ;YES, SHARABLE?
JRST .+3 ;NO, DON'T CREATE THIS PAGE ON DISK
TLNE P1,GT%PLE## ;PHYS. LIMIT EXCEEDED?
TLO T1,(1B1) ;YES, CREATE THIS PAGE ON DISK
TLNN P1,GT%DAF## ;PAGES IN THIS ENTRY OVERLAP THE EXE DIRECTORY?
JRST NOTP03 ;NO, CREATE ALL THE PAGES IN ONE FELL SWOOP
PUSHJ P,CRPAGE## ;CREATE THIS PAGE
JRST [MOVE T2,.JDAT+SGASAV## ;ERROR CODE
CAIE T2,PAGCE% ;IS THIS AN OVERLAP ERROR?
JRST NEED1P ;NO,SOME OTHER TYPE OF ERROR
JRST OVRERR] ;NO, REPORT THE ERROR
TRNE P3,-1 ;SKIP IF ALLOCATED-BUT-ZERO PAGE
TLNN P1,GT%DAF## ;ARE WE READING 1 PAGE AT A TIME?
JRST NOTP02 ;NO, GO ON
LSH T1,P2WLSH## ;RETURN WITH T1=PAGE #, FIND ADDRESS
PUSHJ P,F1IOWD ;MAKE AND STORE AN IOWD
PUSHJ P,RDSTUF ;NO, MUST READ PAGES IN AS WE CREATE THEM
MOVE T1,(P) ;GET SAVED PAGE #
MOVE J,.CPJOB## ;MAKE SURE WE HAVE THE RIGHT JOB
TLNE P1,GT%PLE## ;PHYS. LIMIT EXCEEDED?
TLNE P3,SV%SHR ;AND NON-SHARABLE HIGH SEG?
SKIPA ;NO
PUSHJ P,PAGOUT## ;YES, PAGE IT OUT
JFCL ;SHARABLE OR COULDN'T PAGE OUT
NOTP02: POP P,T1 ;RESTORE PAGE # JUST CREATED
SOSL (P) ;MORE PAGES TO CREATE?
AOJA T1,NOTP01 ;YES, GO DO NEXT PAGE
POP P,(P) ;POP OFF JUNK
JRST NTRYLP ;FINISHED THIS EXE ENTRY
NOTP03: MOVE T2,(P) ;STARTING PAGE NUMBER
HLL T2,T1 ;BITS FOR CREATE AS COMPUTED ABOVE
MOVE T3,-1(P) ;NUMBER OF PAGES REPRESENTED BY THIS ENTRY - 1
MOVSI T1,.PAGCD ;PAGE UUO FUNCTION
MOVNI T3,1(T3) ;NEGATIVE NUMBER OF PAGES TO CREATE
PUSHJ P,PAGUUN## ;CREATE THE NECESSARY NUMBER OF PAGES
JRST [MOVE T2,.JDAT+SGASAV## ;ERROR CODE
CAIE T2,PAGCE% ;IS THIS AN OVERLAP ERROR?
JRST NEED1P ;NO,SOME OTHER TYPE OF ERROR
JRST OVRERR] ;NO, REPORT THE ERROR
LDB T2,[POINT 9,P4,8] ;NO, GET REPEAT COUNT AGAIN
AOS T2 ;=# OF PAGES IN GROUP
HRRZ T1,P4 ;GET 1ST PAGE #
LSH T1,PXWLSH ;=START ADDRESS OF GROUP
LSH T2,PXWLSH ;=LENGTH OF SEGMENT
PUSHJ P,FSIOWD ;SETUP THE IOWD
TRNE P3,-1 ;UNLESS PAGES ARE ALLOCATED-BUT-ZERO...
PUSHJ P,RDSTUF ;READ IN ENTIRE GROUP OF PAGES
POP P,T2 ;STARTING PAGE NUMBER
POP P,T3 ;NUMBER OF PAGES REPRESENTED BY THIS ENTRY - 1
TRNN P3,-1 ;IF ABZ,
JRST NTRYLP ; DONE WITH ENTRY
MOVSI T1,.PAGIO ;SETUP TO PAGE OUT THE PAGES
TLO T2,(PG.GAF+PG.IDC) ;PAGE OUT AND DON'T CARE IF NOT IN
MOVNI T3,1(T3) ;NUMBER OF PAGES
MOVE J,.CPJOB## ;SUPERSTITION PERHAPS?
TLNE P1,GT%PLE## ;DON'T PAGE THEM OUT IF NO NEED TO GO VIRTUAL
TLNE P3,SV%SHR ;ALSO, DON'T PAGE THEM OUT IF IN A SHARABLE HI SEG
CAIA ; ..
PUSHJ P,PAGUUN## ;OUT THEY GO IN ONE FELL SWOOP
JFCL ;OH WELL, WE TRIED
;HERE AFTER PROCESSING OF EACH DIRECTORY ENTRY
NTRYLP: LDB T1,[POINT 9,P4,8] ;GET REPEAT COUNT AGAIN
MOVSI T1,1(T1) ;# OF PAGES,,0
TRNE P3,-1 ;IF THESE PAGES WERE ABZ, DON'T...
ADD P2,T1 ;BUMP CURRENT LOCATION POINTER
TLNE P3,SV%SHR ;DID WE SEE A SHARABLE HIGH SEG?
TLO P1,SV%SHR ;YES, REMEMBER THAT FACT
JRST GTLOOP ;GO BACK FOR MORE
;COME HERE WHEN THE ENTIRE SAVE FILE HAS BEEN READ IN...
;
GETFIN: LDB T1,[POINT 6,.USUSA,5] ;GET LENGTH OF OLD ENTRY VECTOR
CAIE T1,40 ;SET BY /START SWITCH?
SETZM .USUSA ;NO, FORGET ABOUT THE OLD VALUE
PUSHJ P,GTDIRW ;THERE MIGHT BE AN ENTRY VECTOR
HLRZS T1 ;CODE
CAIE T1,SV.STA ;ENTRY VECTOR CODE?
JRST GETFI1 ;NO
PUSHJ P,GTDIRW ;GET NEXT WORD
MOVE T2,T1 ;SAVE IT FOR THE MOMENT
PUSHJ P,GTDIRW ;GET STARTING ADDRESS OR ENTRY VECTOR ADDRESS
SKIPE T2 ;HAVE A LENGTH?
CAIN T2,(JRST) ;IF "JRST" TYPE ENTRY VECTOR,
JRST GETFI0 ; JUST STORE START ADDRESS
SKIPL T2 ;MUST BE POSITIVE
CAILE T2,37 ;AND WITHIN OUR RANGE
JRST GETFI1 ;PRETEND WE NEVER SAW IT
TRO T2,40 ;TURN ON SIGN BIT TO INDICATE REAL ENTRY VECTOR
DPB T2,[POINT 6,T1,5] ;SAVE LENGTH OF THE ENTRY VECTOR
GETFI0: LDB T2,[POINT 6,.USUSA,5] ;GET LENGTH SPECIFIER FROM ENTRY VECTOR
CAIE T2,40 ;WAS THIS SET BY THE USER'S COMMAND?
MOVEM T1,.USUSA ;NO, STORE THE FILE'S FOR STARTING THE PROGRAM
JUMPGE T1,GETFI1 ;GO IF NO "REAL ENTRY" VECTOR
LDB T2,[POINT 6,T1,5] ;GET LENGTH OF NEW ONE AGAIN
CAIGE T2,42 ;ENTRY VECTOR CONTAIN A REENTER ADDRESS?
SETZM .JDAT+.JBREN## ;NO, DON'T CONFUSE HUMANS
SETZM .JDAT+.JBVER## ;CLEAR THIS IN CASE NOT IN VECTOR
CAIGE T2,43 ;ENTRY VECTOR CONTAIN A VERSION NUMBER?
JRST GETFI1 ;NO
PUSH P,M ;DON'T KNOW WHETHER IT MATTERS BUT BE SAFE
MOVE M,T1 ;ADDRESS OF THE ENTRY VECTOR
ADDI M,2 ;ADDRESS OF THE VERSION NUMBER
TLZ M,770000 ;CLEAR OUT THE JUNK
PUSHJ P,PFHMWD## ;GET THE VERSION NUMBER
CAIA ;IGNORE ADDRESS CHECK
MOVEM T1,.JDAT+.JBVER## ;STORE IT WHERE HUMANS LOOK
POP P,M ;RESTORE M
GETFI1: SKIPN T1,.JDAT+SGANAM## ;FILE PAGE OVERLAP THE DIRECTORY PAGE?
JRST GETFI3 ;NO, JUST GO ZAP THE DIRECTORY PAGE
TLNE T1,-1 ;WAS THE PAGE FROM THE FILE ABZ?
JRST GETFI2 ;NO, GO READ THE PAGE
TLNE P1,GT%PLE## ;PAGE LIMIT EXECEEDED?
JRST [PUSHJ P,MAKABZ## ;YES, MAKE AN ABZ PAGE ON THE DISK
JFCL ;TRIED
JRST GETFI4] ;PROCEED
PUSHJ P,YANKIZ## ;MAKE SURE PAGE IS IN CORE
JFCL ;IF IT DIDN'T WORK, THIS WILL RESULT IN AN IME
MOVE T1,.JDAT+SGANAM## ;PAGE NUMBER OF DIRECTORY PAGE
S1PSHJ ZERPAG## ;JUST CAUSE THE PAGE TO CONTAIN ZEROES
JRST GETFI4 ;AND CONTINUE
GETFI2: HLRZ T1,.JDAT+SGANAM## ;FILE POSITION OF THE PAGE
LSH T1,2 ;BLOCK NUMBER
PUSH P,P1 ;USETI CLOBBERS P1
USETI 1(T1) ;POSITION THE FILE TO THE PAGE THAT WAS SKIPPED
POP P,P1 ;RESTORE P1
PUSHJ P,SGIOCK## ;CHECK FOR ERRORS
HRRZ T1,.JDAT+SGANAM## ;NOW GET PROCESS PAGE NUMBER
LSH T1,P2WLSH## ;CONVERT TO ADDRESS
PUSHJ P,F1IOWD ;MAKE AND STORE AN IOWD
PUSHJ P,RDSTUF ;NOW THE CORE IMAGE IS COMPLETE
JRST GETFI4 ;AND CONTINUE
GETFI3: HRRZ T1,P1 ;GET CURRENT DIRECTORY POINTER
PUSHJ P,ZAPPAG## ;FLUSH THE DIRECTORY PAGE
JFCL
GETFI4: POP P,.JDAT+JOBUAL##+6 ;RESTORE PATH BLOCK
POP P,.JDAT+JOBUAL##+5 ; ..
POP P,.JDAT+JOBUAL##+4 ; ..
POP P,.JDAT+JOBUAL##+3 ; ..
HLRZ T2,.JDAT+SGAHGH## ;GET 1ST PAGE OF HIGH SEG
JUMPE T2,CPOPJ## ;IF NO HIGH SEG, EXIT NOW
PUSHJ P,GETSSN ;GET SECTION NUMBER
DPB T1,[POINT 5,T2,26] ;STORE SECTION NUMBER
MOVE T1,T2 ;IT IS ALSO THE NEW STARTING VIRT PAGE #
HRRZ T3,.JDAT+SGAHGH## ;GET # OF PAGES IN HIGH SEG
TLNE P1,SV%SHR ;DID WE SEE A SHARABLE HIGH SEG?
TDZA T4,T4 ;YES, T4=0
MOVSI T4,(1B0) ;NO, INDICATE IT TO NREMAP
;COME HERE TO REMAP HIGH SEG
PUSH P,.JDAT+JOBSA## ;REMAP CLEARS THESE JOB DATA LOCS
PUSH P,.JDAT+JOBREN## ;...
PUSH P,.JDAT+JOBHRL## ;...
IFN FTMP,<
PUSHJ P,UPMM## ;MUST HAVE THE MM TO DO THE REMAP
>
PUSHJ P,NREMAP## ;DO THE REMAP
STOPCD .,STOP,RDS, ;++REMAP DIDN'T SKIP
POP P,.JDAT+JOBHRL## ;RESTORE JOB DATA LOCS
POP P,.JDAT+JOBREN## ;...
POP P,.JDAT+JOBSA## ;...
SOS (P) ;SINCE SHARE1 WILL EXIT TO CPOPJ1,
; WE MUST BACK UP THE RETURN ADDR SO RETURN
; TO CPOPJ
JSP T3,SHARE1 ;GO SET UP JBTSGN, ETC...
;SUBROUTINE TO CHECK TO SEE IF THE CURRENT ENTRY IS WHAT
; WE WANT
;
;CALL:
; DMOVE P3,DIRECTORY-ENTRY
; PUSHJ P,WANTIT
; HERE IF NO
; HERE IF YES
;
WANTIT: TLNE P1,GTMRG## ;MERGING?
SKIPN T2,.JDAT+SGANEW## ;WAS A RANGE OF PAGES SPECIFIED?
CAIA ;NO, DO THE NORMAL THING
JRST WANTI1 ;YES, SEE IF PAGES ARE WITHIN THE RANGE
MOVSI T2,GTHGH## ;ASSUME HIGH SEG
TLNN P3,SV%HIS ;IS THIS THE HISEG?
MOVSI T2,GTLOW## ;NO, SET UP LOW SEG BIT
TDNN P1,T2 ;YES, DID WE WANT THIS SEGMENT?
POPJ P, ;NO
WANTI1: HRRZ T1,P4 ;GET PROCESS PAGE #
CAIL T1,<MXSECN*PAGSIZ##>+HLGPNO+1 ;CHECK UPPER LIMIT
JRST BADDIR ;TOO HIGH
TLNE P1,GTMRG## ;MERGING?
TRNN T2,-1 ;AND A RANGE SPECIFIED?
JRST WANTI3 ;NOT MERGING A SPECIFIED RANGE
PUSHJ P,SAVT## ;NEED LOTS OF ACS, EVEN THO A SIX CHAR NAME, MUST SAVE T3
HLRZ T3,T2 ;LOWER BOUND
LDB T4,[POINT 9,P4,8] ;REPEAT COUNT
ADDI T4,(T1) ;HIGHEST PAGE DESCRIBED IN THIS POINTER
CAIG T1,(T2) ;PROCESS PAGE GREATER THAN HIGHEST PAGE IN RANGE?
CAIGE T4,(T3) ;HIGHEST PAGE IN POINTER LESS THAN START OF THE RANGE?
POPJ P, ;YES TO EITHER, DON'T WANT THE PAGES
TLO P3,SV%WRT ;ALWAYS MERGE AS A LOW SEGMENT PAGE
TLZ P3,SV%CON+SV%SHR+SV%HIS
CAILE T3,(T1) ;IF THE RANGE DESCRIBED BY THE ENTRY,
JRST WANTI2 ; IS COMPLETELY ENCOMPASSED BY THE USER
CAIG T4,(T2) ; SPECIFIED RANGE, GO GET ALL THE PAGES
JRST CPOPJ1## ; REPRESENTED IN THE ENTRY
WANTI2: HLR P4,T2 ;ADJUST ENTRY TO REPRESENT USER SPECIFIED RANGE
SUBI T2,(T3) ;NUMBER OF PAGES TO USER UPPER BOUND
SUBI T4,(T3) ;NUMBER OF PAGES TO ENTRY UPPER BOUND
CAILE T4,(T2) ;LESSER OF THE TWO
HRRZ T4,T2 ;NUMBER OF PAGES TO GET
DPB T4,[POINT 9,P4,8] ;STORE ADJUSTED REPEAT COUNT
HLRZS T2 ;USER LOWER BOUND
SUBI T2,(T1) ;OFFSET TO FILE PAGE
ADDI P3,(T2) ;FIRST FILE PAGE
JRST CPOPJ1## ;AND GIVE WANTIT IT RETURN
WANTI3: JUMPL P3,WANTI4 ;GO IF A HI SEG
TLC P3,SV%WRT+SV%SHR;TOPS-20 TURNS BOTH ON TO MEAN COPY-ON-WRITE
TLCN P3,SV%WRT+SV%SHR; WHICH IS REALLY EQUIVALENT TO A LOW SEG PAGE
TLC P3,SV%SHR ;SO TREAT IT THAT WAY FOR COMPATABILITY
TLNE P3,SV%WRT ;LOW SEG MUST BE WRITABLE
TLNE P3,SV%CON+SV%SHR;AND NOT CONC OR SHARABLE
JRST BADDIR ;ERROR IF SO
JRST CPOPJ1## ;YES
WANTI4: TLNE P3,SV%SHR ;THIS PAGE SHARABLE?
TLON P1,GT%S1S## ;YES, SAW 1 SHARABLE PAGE
TLNN P1,GT%S1S## ;1ST SHARABLE PAGE, OR NOT SHARABLE
TLOA P1,GT%GTH## ;THIS PAGE IS OK, SAW A HI-SEG PAGE
TLON P1,GT%GTH## ;MODE CHANGE (HI TO SHR OR VICE VERSA). 1ST HI PAGE?
TRNN P4,-1 ;PAGE OK, PAGE 0 CANT BE IN HI-SEG
JRST BADDIR ;PAGE 0 OR MIXTURE OF SHR AND NON-SHR PAGES
JRST CPOPJ1## ;PAGE IS OK, TAKE GOOD RETURN
;SUBROUTINE TO READ IN A PAGE FROM THE SAVE FILE
; AND PERFORM SOME MISCELLANEOUS HOUSE-KEEPING
;
;CALL:
; PUSHJ P,FSIOWD ;SETUP AN IOWD
; PUSHJ P,RDSTUF ;OR,
; PUSHJ P,WRSTUF
; RETURN HERE ONLY IF OK
;
WRSTUF::MOVEI T1,35 ;FILOP. FUNCTION CODE FOR EXTENDED WRITE
MOVEM T1,.JDAT+SGALEN## ;STORE THAT FOR THE FILOP. AND FALL INTO COMMON CODE
RDSTUF: MOVE T1,DEVIOS(F) ;GET STATUS
TRNE T1,IODEND ;EOF?
JRST SHTDIR ;YES, FILE TOO SHORT
TLNE P1,GTLOW## ;DON'T SET USRHCU ON A GETSEG BECAUSE
; THE BLT TO RESTORE USER CHANNELS WILL FAIL
HRROS USRHCU## ;SET SAVE/GET FLAG
PUSH P,P1 ;AN INPUT KILLS THESE AC'S
PUSH P,P4 ;...
.CREF SGASAV ;SINCE CAN'T HAVE AN EXTERNAL AC
FILOP. 14, ;(FILOP. SGASAV,)READ SOME STUFF
JFCL ;SGIOCK AND THE TEST AT THE BEGINNING OF RDSTUF
; WILL TAKE CARE OF ERRORS
PUSHJ P,SGIOCK## ;CHECK FOR ERRORS
HRRZS USRHCU## ;CLEAR FLAG
PP4P1: POP P,P4 ;RESTORE AC'S
POP P,P1 ;...
POPJ P, ;RETURN
;SUBROUTINE TO MOVE A DIRECTORY PAGE
;
;CALL:
; MOVE T1,PAGE # TO MOVE
; PUSHJ P,MOVDIR
; RETURN WITH PAGE MOVED AND DIRECTORY POINTERS UPDATED
;
;COME HERE IF ONE OF THE DIRECTORY PAGES IS ABOUT TO BE
; OVER-WRITTEN BY THE CURRENT DIRECTORY ENTRY. THE DIRECTORY PAGE
; IS MOVED TO ANOTHER FREE PAGE.
MOVDIR: HRRZ T2,P3 ;FILE PAGE NUMBER
JUMPE T2,MOVDR1 ;EASY IF ABZ PAGE
HRRZ T3,P4 ;PROCESS PAGE NUMBER
SUBM T1,T3 ;OFFSET INTO POINTER
ADD T2,T3 ;FILE PAGE NUMBER TO REMEMBER
MOVDR1: HRRM T1,.JDAT+SGANAM## ;REMEMBER PROCESS PAGE NUMBER TO SKIP
HRLM T2,.JDAT+SGANAM## ; AND FILE PAGE NUMBER THAT HAS TO BE PUT THERE WHEN DONE
TLO P1,GT%DAF## ;INDICATE SOME PAGE IN THIS ENTRY OVERLAPS DIRECTORY
POPJ P, ;AND RETURN
;SUBROUTINE TO SETUP IOWD TO DO AN EXTENDED FILIO IN UUO (ACTUALLY NEVER
; DOES MORE THAT A SECTION OR CROSSES A SECTION BOUNDARY, BUT COULD DO A
; WHOLE SECTION IN ONE OPERATION)
;CALLING SEQUENCE:
; MOVE T1,SECTION NUMBER,,ADDRESS WITHIN SECTION
; MOVE T2,POSITIVE WORD COUNT
; PUSHJ P,FSIOWD
; ALWAYS RETURN HERE, IOWD SETUP FOR RDSTUF
;CALL F1IOWD TO SETUP TO READ JUST ONE PAGE
F1IOWD: MOVEI T2,PAGSIZ## ;WORD COUNT TO READ ONE PAGE
FSIOWD::MOVEM T1,.JDAT+JOBUAL##+4 ;ADDRESS (OUT OF OTHERS WAY) IN PATH PART OF JOBUAL
MOVEM T2,.JDAT+JOBUAL##+3 ;WORD COUNT
SETZM .JDAT+JOBUAL##+5;TERMINATE LIST
SETZM .JDAT+JOBUAL##+6; IT TAKE TWO WORDS OF ZEROS
MOVEI T1,34 ;FILOP FUNCTION FO.XIN
MOVEI T2,JOBUAL##+3 ;ADDRESS OF ARGUMENT LIST
DMOVEM T1,.JDAT+SGALEN## ;STORE ARG POINTER IN SHADOW ACS
MOVE T1,[2,,SGALEN##];LENGTH,,ADDRESS OF ARG LIST
MOVEM T1,.JDAT+SGASAV## ;STORE THAT FOR THE FILOP
POPJ P, ;AND RETURN
;STILL IN IFN FTEXE CONDITIONAL...
;ERROR ROUTINES FOR NEW SAVE FILES
;
;HERE IF 1 MORE PAGE IS NEEDED FOR VARIOUS REASONS
NEED1P::PUSH P,[0] ;WILL BE INCREMENTED TO 1P
JRST NOROOM## ;PRINT ERROR MESSAGE
;HERE IF ATTEMPTING TO EXCEED VIRTUAL LIMIT WITH LIMIT IN T1
NEEDNP: MOVE T2,.JDAT+SGALOW## ;GET SIZE OF SEG
NTROOM: SUB T2,T1 ;GET WHAT IS NEEDED
LSH T2,P2WLSH ;CONVERT TO WORDS FOR NOROOM
PUSH P,T2 ;SAVE WHERE NOROOM EXPECTS TO FIND IT
JRST NOROOM## ;AND GO GIVE THE ERROR
;OVERLAY ERROR
OVRERR::MOVEI T1,LOHERR ;OVERLAP ERROR
PUSHJ P,SGRELE## ;RESET DEVICE
JSP T1,PHOLD## ;START TTY AND STOP JOB
ASCIZ /Page overlap error/
;DIRECTORY FORMAT ERROR
SHTDIR: MOVEI T1,BEDERR
PUSHJ P,SGRELE##
JSP T1,PHOLD##
ASCIZ /File short in EXE file directory/
BADDIR: MOVEI T1,BEDERR ;BAD EXE DIRECTORY ERROR
PUSHJ P,SGRELE## ;RESET DEVICE
JSP T1,PHOLD##
ASCIZ /Bad format for EXE file directory/
;NOT AN .EXE FILE (1ST WORD DID NOT HAVE PROPER DIRECTORY CODE IN IT)
NOTEXE: MOVEI T1,BEEERR ;ERROR CODE IN CASE THIS IS A RUN UUO
PUSHJ P,SGRELE## ;RELEASE DEVICE AND ERROR RETURN TO
; USER IF RUN UUO OR FIND TTY AND
; PRINT ?CRLF
JSP T1,PHOLD## ;START TTY AND STOP JOB
ASCIZ /Not an EXE file/
EXESAV::MOVEI T1,BEEERR ;ERROR CODE FOR RUN/GETSEG UUO
PUSHJ P,SGRELE## ;AN EXE FILE DID NOT HAVE EXE
JSP T1,PHOLD## ; EXTENSION
ASCIZ /Must have "EXE" extension/
EXEBIG: MOVEI T1,DTBERR ;ERROR CODE FOR RUN/GETSEG UUO
PUSHJ P,SGRELE## ;EXE DIRECTORY WAS TOO BIG
JSP T1,PHOLD##
ASCIZ /File directory is too large/
;STILL IN IFN FTEXE CONDITIONAL...
IUUAGL::MOVEI T1,ILUERR ;ERROR CODE FOR RUN/GETSEG UUO
PUSHJ P,SGRELE## ;REPORT ERROR
JSP T1,PHOLD##
ASCIZ \Illegal section/core argument\
;SUBROUTINE TO CHECK CURRENT LOCATION ON THE DEVICE
;THIS ROUTINE IS USED ONLY IN THE CASE WHERE THE
; DIRECTORY DATA PAGES ARE NOT CONTIGUOUS.
;
;CALL:
; MOVSI P2,CURRENT-PAGE-IN-SAVE-FILE
; HRR P3,FILE-PAGE-#-OF -THIS-ENTRY
; PUSHJ P,SKPBLK
; RETURN HERE WITH THE DEVICE PROPERLY POSITIONED
;
SKPBLK: TRNN P3,-1 ;IF PAGES ARE ABZ, WE DON'T NEED
POPJ P, ; TO CHECK LOCATION ON DEVICE
PUSH P,P1 ;USETI KILLS THESE AC'S
PUSH P,P4 ;SO, WE SAVE THEM FIRST
SKPBK2: HLRZ T3,P2 ;GET CURRENT FILE PAGE #
SUBI T3,(P3) ;FIND DIFFERENCE IN WHERE WE ARE ON
; THE DEVICE, AND WHERE WE WANT TO GO
JUMPE T3,PP4P1 ;IF WE ARE THERE, RESTORE P4,P1 AND EXIT
JUMPG T3,BADDIR ;IF WE ARE PAST WHERE WE WANT TO BE,
; IT CAN ONLY BE A BAD FORMAT FILE
MOVE T4,DEVMOD(F) ;WE ARE NOT THERE YET (CAN ONLY HAPPEN IF THERE
; ARE "HOLES" IN THE
; SAVE FILE, IMPOSSIBLE UNLESS
; THE DEFINED STRUCTURE OF THE
; SAVE FILE CHANGES IN THE
; FUTURE, OR IF WE ARE SKIPPING 1 SEGMENT.
TLNE T4,DVDSK ;IS IT A DISK?
JRST [HRL P2,P3 ;YES, RESET COUNTER OF CURRENT FILE PAGE #
HRRZ T3,P3 ;FETCH FILE PAGE # FOR THIS ENTRY
LSH T3,2 ;FIND BLOCK NUMBER
USETI 1(T3) ;MOVE TO CORRECT FILE PAGE #
JRST PP4P1] ; AND CONTINUE
PUSHJ P,RDSTUF ;NO, READ PAGE OF DATA FROM DEVICE
ADD P2,[1,,0] ;BUMP CURRENT FILE PAGE #
JRST SKPBK2 ;AND CHECK AGAIN
;ROUTINE TO GET THE NEXT DIRECTORY ENTRY FROM THE SAVE FILE
;
;CALL:
; MOVE P1,ADDRESS-OF-ENTRY
; MOVE P2,CURRENT-LENGTH-OF-DIRECTORY
; PUSHJ P,GTDIRE
; HERE IF DIRECTORY IS FINISHED
; HERE IF MORE IN DIRECTORY (ENTRY IS IN P3,P4)
;
GTDIRE::TRNN P2,-1 ;IS THERE ANY MORE?
POPJ P, ;NO
SUBI P2,NTRYSZ ;DECREMENT LENGTH OF ENTRY
PUSHJ P,GTDIRW ;GET 1ST WORD
MOVE P3,T1 ;STORE IT IN P3
PUSHJ P,GTDIRW ;GET NEXT WORD
MOVE P4,T1 ;STORE IT IN P4
JRST CPOPJ1## ;SKIP RETURN
;ROUTINE TO GET ONE WORD FROM THE DIRECTORY
;
;CALL:
; MOVE P1,ADDRESS-OF-WORD
; PUSHJ P,GTDIRW
;
;ON EXIT, T1 WILL CONTAIN THE WORD FETCHED FROM THE DIRECTORY
;
;IF THE PAGE IS FINISHED, THE PAGE POINTED TO BY P1 IS
; REMOVED FROM THE LOGICAL ADDRESSING SPACE AND A NEW
; DIRECTORY PAGE IS FETCHED FROM SGANAM.
GTDIRW::HRR M,P1 ;GET POINTER TO DIRECTORY
PUSHJ P,PFHGWD## ;GET WORD FROM USER SPACE
JRST UADERR## ; MUST USE PFH'S GETWRD ROUTINE SINCE PFH MAY
; HAVE PAGED OUT THE DIRECTORY PAGE
AOS P1 ;BUMP POINTER
TRNE P1,EXESIZ-1 ;OVERLAP TO NEW PAGE?
POPJ P, ;NO
SUBI P1,EXESIZ ;YES, MOVE POINTER BACK TO LAST PAGE
PUSH P,T1 ;SAVE CURRENT DIRECTORY ENTRY
PUSH P,T3 ;THESE ARE THE CURRENT DIRECTORY ENTRIES,
PUSH P,T4 ; SO, WE MUST SAVE THEM
SKIPN T1,.JDAT+SGAEXT## ;READING DIRECTORY SEQUENTIALLY?
JRST GTDIR1 ;YES
LSH T1,2 ;CONVERT TO BLOCK NUMBER OF DIRECTORY PAGE
PUSH P,P1 ;USETI CLOBBERS P1
USETI 1(T1) ;POSITION TO DIRECTORY PAGE
PUSHJ P,SGIOCK## ;CHECK FOR ERRORS
POP P,P1 ;RESTORE P1
GTDIR1: HRRZ T1,P1 ;ADDRESS FOR I/O
PUSHJ P,F1IOWD ;MAKE AND STORE AN IOWD
PUSHJ P,RDSTUF ;READ THE NEXT DIRECTORY PAGE
PUSHJ P,SGIOCK## ;CHECK FOR I/O ERRORS
TLO P1,SV%DWO ;REMEMBER MULTIPLE PAGE EXE DIRECTORY READ
SKIPN .JDAT+SGAEXT## ;SEQUENTIAL I/O?
JRST GTDIR2 ;YES, ALL DONE
HLRZ T1,P2 ;NO, MUST PUT THE FILE BACK WHERE IT WAS
LSH T1,2 ;CONVERT TO BLOCK NUMBER
PUSH P,P1 ;SAVE THIS VERY IMPORTANT AC
USETI 1(T1) ;POSITION THE FILE
PUSHJ P,SGIOCK## ;ERRORS?
POP P,P1 ;RESTORE P1
AOS .JDAT+SGAEXT## ;WHERE THE NEXT PAGE OF THE DIRECTORY IS
GTDIR2: POP P,T4 ;RESTORE AC'S
POP P,T3
JRST TPOPJ## ;RESTORE DIRECTORY ENTRY AND RETURN
;STILL IN IFN FTEXE CONDITIONAL...
;ROUTINE TO SET UP FOR A NEW STYLE SAVE FILE GET
;
;CALL:
; MOVSI P1,FLAGS
; PUSHJ P,GETNEW
; HERE IF ERROR
; HERE OTHERWISE
;
GETNEW: MOVE J,.CPJOB## ;RESTORE JOB NUMBER
IFN FTLOCK,<
MOVSI T2,NSHF!NSWP ;CAN'T ASSIGN CORE IF JOB IS LOCKED
TDNE T2,JBTSTS##(J) ;LOCKED?
JRST [MOVEI T1,SNSERR ;SEGMENT NOT ON SWAPPING SPACE
POPJ P,]
>;END OF FTLOCK
PUSH P,.JDAT+JOBUAL##+2
PUSH P,.JDAT+JOBUAL##+3 ;THE OUTSIDE WORLD IS SENSITIVE TO THESE
PUSH P,.JDAT+JOBUAL##+4 ; LOCATIONS
PUSH P,.JDAT+JOBUAL##+5 ; ..
PUSH P,.JDAT+JOBUAL##+6 ; ..
TLNE P1,GTHGH## ;DOES HE WANT THE HIGH SEG?
IFE FTMP,<
PUSHJ P,KILHGC ;YES, REMOVE PRESENT HISEG FROM LOG.
; ADR. SPACE
>
IFN FTMP,<
PUSHJ P,[PUSHJ P,GGVMM## ;GET THE MM RESOURCE
PJRST KILHGC];AND THEN REMOVE THE CURRENT HIGH SEGMENT
>
TLNN P1,GTLOW## ;DOES HE WANT THE LOW SEGS?
JRST GTHILO ;NO
MOVEI T1,EXESIZ-1 ;SET UP FOR A CORE 0
PUSH P,P1 ;SAVE FLAGS
PUSHJ P,GET1PG## ;GET CORE MIGHT CALL GETSEG
POP P,P1 ;RESTORE FLAGS
GTHILO: POP P,.JDAT+JOBUAL##+6 ; ..
POP P,.JDAT+JOBUAL##+5 ; ..
POP P,.JDAT+JOBUAL##+4 ; LOCATIONS
POP P,.JDAT+JOBUAL##+3 ;THE OUTSIDE WORLD IS SENSITIVE TO THESE
POP P,.JDAT+JOBUAL##+2
PUSH P,.JDAT+SGANAM## ;SAVE THIS STUFF
PUSH P,.JDAT+SGAEXT## ;...
PUSH P,.JDAT+SGALOW## ;SAVE EXTENSION
PUSH P,.JDAT+SGANEW## ;SAVE USER CORE ARG
PUSHJ P,GETEXE ;READ THE EXE FILE
POP P,.JDAT+SGANEW## ;RESTORE USER CORE ARG
POP P,.JDAT+SGALOW## ;RESTORE EXTENSION
POP P,.JDAT+SGAEXT## ;RESTORE GOOD STUFF
POP P,.JDAT+SGANAM##
MOVE J,.CPJOB## ;MAKE SURE J IS SET UP WHEN WE LEAVE
JRST CPOPJ1## ;RETURN TO CALL+2
;ROUTINE TO CHECK TO SEE IF A GIVEN PAGE IS WITHIN THE RANGE
; OF THE CURRENT DIRECTORY ENTRY. THIS ROUTINE IS NECESSARY
; TO MAKE SURE THAT A DIRECTORY PAGE IS NOT OVERWRITTEN,
; AND TO DO SOME OPTIMIZATION ON THE CHOICE OF A NEW PAGE
; IF A DIRECTORY PAGE MUST BE MOVED.
;
;CALL:
; MOVE T1,PAGE ADDRESS/PAGE #
; DMOVE P3,DIRECTORY-ENTRY
; PUSHJ P,CKRADR/CKRANG
; HERE IF THERE IS AN OVERLAP
; HERE IF OK
;
CKRADR: LSH T1,W2PLSH## ;MAKE INTO A PAGE NUMBER
CKRANG: LDB T2,[POINT 9,P4,8] ;GET REPEAT COUNT
ADD P4,.USUSN ;REFLECT THE SECTION THE GET IS BEING DONE INTO
ADDI T2,(P4) ;FIND LAST PAGE OF THIS ENTRY
CAIL T1,(P4) ;CHECK IF NEW PAGE IS LESS THAN 1ST PAGE
CAILE T1,(T2) ;OR GREATER THAN LAST PAGE
AOS (P) ;YES, NO CONFLICT
SUB P4,.USUSN ;RESTORE TO ORIGIONAL VALUE
POPJ P, ;OVERLAP, MUST FIND NEW PAGE
;SUBROUTINE TO DETERMINE SECTION NUMBER
;CALLING SEQUENCE:
; PUSHJ P,GETSSN
; ... ;SECTION NUMBER IN T1
; NORMAL RETURN ;NO NEED TO ADJUST SECTION NUMBER
GETSSN::
REPEAT 0,<
SKIPE T1,.USUSN ;GET SECTION NUMBER FOR CURRENT OP
CAIN T1,1000 ;***HACK TO ALLOW SCETION 0-1 MAPPING
JRST CPOPJ1## ;INDICATE NO ADJUSTMENT NEEDED
TLZ T1,400000 ;CLEAR SET BY UUO BIT
>
SKIPN T1,.USUSN ;GET SECTION NUMBER FOR CURRENT OP
JRST CPOPJ1## ;NO ADJUSTMENT NEEDED
LSH T1,P2SLSH## ;CONVERT TO SECTION NUMBER
POPJ P, ;RETURN
;SUBROUTINE TO CREATE A SECTION, CREATE PAGE 0 IN THAT SECTION, AND BLT
; PAGE ZERO OF SECTION 0 TO IT
;CALLING SEQUENCE:
; PUSHJ P,CRESPG0 ;CREATE .USUSN SECTION
; ALWAYS RETURN HERE
CRESP0: PUSHJ P,GETSSN ;GET SECTION NUMBER
SKIPE .UPMP+SECTAB(T1);NON-ZERO SECTION, GO AWAY IF IT ALREADY EXISTS
POPJ P, ;SETCTION 0 OR 1
PUSHJ P,CRESSN## ;CREATE THE SECTION (FASTER THAN PAGE CREATE)
JRST NEED1P ;COULDN'T
MOVE T1,.USUSN ;PAGE ZERO IN THE SECTION
REPEAT 0,<
TLZ T1,400000 ;CLEAR SET BY UUO BIT
>
PUSHJ P,CRPAGE ;CREATE THAT
JRST NEED1P ;COP OUT
MOVEI T1,PAGSIZ## ;ONE PAGE
MOVEI T2,.JDAT ;SECTION ZERO PAGE 0
MOVE T3,.USUSN ;USE SECTION
LSH T3,S2PLSH## ;PAGE 0 OF USE SECTION
XBLTXU T1 ;MOVE THE PAGE
POPJ P, ;RETURN
;SUBROUTINE TO VALIDATE WHETHER SWAPPER COPY OF SEGMENT IS
;VALID OR NOT
;RETURNS CPOPJ1 IF SO, CPOPJ IF NOT.
;CALL:
; MOVE J,SEGMENT#
; PUSHJ P,VALSEG
;IF THE DISK COPY WAS BAD BUT AN IN CORE COPY WAS GOOD, THEN WE WILL
;RETURN CPOPJ1 WITH THE DISK COPY DELETED.
VALSEG: LDB T1,IMGOUT## ;GET OUTCORE SIZE
JUMPE T1,CPOPJ1## ;IF NO DISK COPY
MOVE T2,JBTSWP##(J) ;GET DISK OR FRAGMENT ADDR
SKIPL T1,T2 ;COPY TO T1 FRAGMENTED?
JRST VALSG2 ;NOT FRAGMENETED
VALSG1: SKIPN T1,(T2) ;GET ENTRY IF THERE IS ONE
JRST CPOPJ1## ;SEGMENT IS CLEAN IF NO MORE
JUMPLE T1,[MOVEI T2,(T1)
JRST VALSG1]
TRO T2,400000 ;REMEMBER IT'S FRAGMENTED
VALSG2: PUSH P,T2 ;SAVE POINTER
LDB T2,FRGUT1## ;GET UNIT FROM T1
SKIPLE T2,SWPTAB(T2) ;IS IT IN SWPTAB?
SKIPGE UNIFKS(T2) ;IS THERE SPACE ON IT?
JRST VALSG5 ;NO
POP P,T2 ;RESTORE POINTER
TRZN T2,400000 ;FRAGMENTED?
JRST CPOPJ1## ;NO
AOJA T2,VALSG1 ;FRAGMENTED, CHECK NEXT PIECE
;HERE IF SOME FRAGMENT (OR THE WHOLE ENTRY) IS ON THE BAD UNIT
VALSG5: POP P,(P) ;CLEAR JUNK OFF OF STACK
IFN FTMP,<
CPLOCK (SCD) ;DON'T LET SWPLST CHANGE ON US
> ;END IFN FTMP
MOVSI T1,SWP!JXPN ;IS THIS HIGH SEGMENT SWAPPED?
TDNN T1,JBTSTS(J) ;??
JRST VALSG6 ;NO, OK TO DELETE COPY OF IT
SETZM JBTPRG##(J) ;MAKE NOT SHARABLE (CLRNAM DOES TOO MUCH)
IFN FTMP,<
PJRST ULKSCD## ;RELEASE INTERLOCK AND DO LOOKUP
>
IFE FTMP,<
POPJ P,
>
;HERE IF THE SEGMENT ISN'T SWAPPED, WE CAN JUST DELETE THE DISK COPY
VALSG6: PUSHJ P,ZERSWP## ;DELETE DISK COPY
IFN FTMP,<
AOS (P) ;SKIP RETURN
PJRST ULKSCD##
> ;END IFN FTMP
IFE FTMP,<
JRST CPOPJ1##
>
SUBTTL SWAP - USER PROGRAM SWAPPING ROUTINES
;ROUTINE CALLED AFTER A HIGH OR LOW SEG JUST SWAPPED IN
;IT SEES IF A HIGH SEG IS STILL TO BE SWAPPED IN
;DOES POST PROCESSING AFTER HIGH SEG SWAPPEN IN
;CALL: MOVE J,JOB NUMBER
; PUSHJ P,FININ
; RETURN0 (VM SYSTEMS ONLY) IF THE HIGH SEG CURRENTLY
; HAS SWAPPING I/O IN PROGRESS
; RETURN1 IF HIGH SEG TO BE SWAPPEN IN(HIGH SEG NO. IN AC J)
; RETURN2 IF NO HIGH SEG, OR HIGH SEG ALREADY IN, OR THIS WAS HIGH SEG
; AC J RETURNED WITH JOB NUMBER(IE LOW SEG NO.)
;IF CALLED AT FINCHK, NO SWPLST ENTRY WILL BE DELETED
;J CONTAINS JOB OR HIGH SEG NUMBER(SAME AC AS SWAP USES)
FINCHK::
TDZA T2,T2 ;SET ENTRY AT FINCHK
FININ:: MOVSI T2,(1B0) ;SET ENTRY AT FININ
CAILE J,JOBMAX## ;WAS A LOW SEG JUST SWAPPED IN?
JRST FINHGH ;NO, HIGH SEG JUST SWAPPED IN, GO FINISH
IFN FTLOCK,<
MOVE T1,J ;IF LOCKING THE LOW SEGMENT,
; FORGET ABOUT SWAPPING IN THE HIGH SEGMENT.
; IF THE HIGH SEGMENT IS SWAPPED WHEN LOCKING
; COMPLETES, THE LOCK UUO WILL SET THE SWP
; BIT FOR THE LOW SEGMENT. THE LOK BIT
; WILL KEEP THE JOB FROM RUNNING.
>
MOVE J,JBTSGN##(J) ;HIGH SEGMENT NUMBER IF JOB HAS ONE
JUMPLE J,[MOVE J,T1 ;JUMP IF JOB DOESN'T HAVE A REAL HIGH SEGMENT
JRST CPOPJ2##] ;GIVE NOTHING TO DO RETURN(MAYBE SPYSEG)
HRR T2,JBTSWI##(J) ;SAVE SWPIN IN CASE SWAPPING I/O IN PROGRESS FOR
; THIS JOBS HIGH SEGMENT
HRRZM T1,JBTSWI##(J) ;YES, SAVE JOB NUMBER(FOR FINHGH AND RETURN)
SKIPE JBTADR##(J) ;YES, IS HIGH SEG ALREADY IN CORE?
;(NOT POSSIBLE TO BE IN MIDDLE OF SWAPPING)
JRST FIN0
IFN FTLOCK,<
CAMN T1,LOCK##
JRST BOTHIN
>
JRST CPOPJ1##
FIN0: MOVSI T1,SWP+JXPN ;SWP ON FOR THE HI SEG?
TDNE T1,JBTSTS##(J) ; ONLY IF SWAPPING I/O IS IN PROGRESS
JRST [HRRZS T2 ;CLEAR SIGN OF T2
EXCH T2,JBTSWI##(J) ;RETURN DOING NOTHING UNTIL HI-SEG I/O IS DONE
MOVEI J,(T2) ;RETURN JOB #
POPJ P,] ;RESTORE ORIGIONAL VALUE OF SWPIN
PUSHJ P,CHKIDL ;YES, CHECK IF THIS HIGH SEG IS IDLE(IF YES,
; DECREASE CORTAL=FREE+DORMANT+IDLE CORE
; BY SIZE IN K OF HIGH SEG SINCE IT WILL
; NO LONGER BE IDLE(IN CORE COUNT NON-ZERO)
MOVE T1,JBTSWI##(J) ;RESTORE JOB NUMBER
PUSHJ P,INCCNT ;INCREMENT HIGH SEG IN CORE COUNT
; FOR THIS JOB
PUSHJ P,CHKTAL ;CHECK CORTAL WITH CORTAB, HALT IF DIFFER
TLO J,1
JRST FINHG1
FINHGH: MOVE T1,JBTSWI##(J) ;JOB WHICH HISEG WAS SWAPPED IN FOR
HLL J,JBTSGN##(T1) ;GET THE STATE OF UWP
FINHG1: JUMPGE T2,BOTHIN ;DON'T DO THIS IF CALLED AT FINCHK
MOVSI T2,SWP ;CLEAR SWAPPED OUT OR ON WAY FLAG FOR HIGH SEG
ANDCAM T2,JBTSTS##(J) ;AND CLEAR SUPPRESS IN-CORE COUNT INCREMENT FLAG
HRRZ T2,MIGRAT## ;MIGRATING JOB
CAME T1,T2 ;IF WE'RE GETTING RID OF A SWAP UNIT
CAIN T2,(J)
SKIPA
; MAKE THE HIGH SEG DISAPPEAR
TLNE J,UWPOFF ;IS USER MODE WRITE PROTECT(UWP) OFF
; FOR THIS USER?
JRST [PUSHJ P,ZERSWP## ;YES, CHANGE SWAPPING SPACE TO 0 FOR HIGH SEG
;0 TO JBTIMO,JBTIMI, AND SWP IN JBTSTS(HIGH SEG)
;NO, KEEP COPY OF SEG ON DISK(USUAL CASE)
; WHETHER SHARABLE OR NOT
JRST BOTHIN]
TLZN J,1
PUSHJ P,DLTSLX## ;DELETE ENTRY FROM SWPLST
BOTHIN: TLZ J,-1 ;SAVE ONLY SEGMENT NUMBER
HRRZ T1,MIGRAT##
CAME J,T1 ;IF WE'RE REMEMBERING THIS HIGH SEG, DON'T DO THIS
MOVE J,JBTSWI##(J) ;RESTORE JOB NUMBER(LOW SEG NUMBER)
JRST CPOPJ2## ;SWAPPING I/O DONE RETURN
;ROUTINE TO CHECK FOR EXPANDING HIGH SEGMENT ON SWAP IN
;IF A JOB IS USING A SHARABLE HIGH SEGMENT WHICH HAS BEEN
;EXPANDED BY ANOTHER JOB, NONE OF THE SHARERS CAN BE
;SWAPPED IN UNTIL ALL HAVE BEEN SWAPPED OUT (JXPN=0)
;CALL: MOVE J,JOB NUMBER (OR HI SEG) TO BE SWAPPED IN
; PUSHJ P,CKXPN
; RETURN1 IF HIGH SEG IS EXPANDING (J=SAME)
; RETURN2 ON ALL OTHER CONDITIONS (J=SAME)
;NOTE: T1 AND T2 ARE PRESERVED (HENCE SHORT NAME FOR ROUTINE)
CKXPN:: CAIG J,JOBMAX## ;IS THIS A LOW SEG (JOB #)?
SKIPG T3,JBTSGN##(J) ;YES, DOES JOB HAVE A HIGH SEG?
JRST CPOPJ1## ;NO, RETURN IMMEDIATELY AND TRY TO FIT
HRRZS T3
MOVE T3,JBTSTS##(T3) ;YES, GET HIGH SEG STATUS WORD
TLNN T3,JXPN ;IS THIS HIGH SEG EXPANDING?
AOS (P) ;NO,
POPJ P, ;YES, DO NOT TRY TO SWAP THIS JOB IN
;ROUTINE CALLED JUST BEFORE HIGH OR LOW SEG TO BE SWAPPED IN
; AND AFTER CORE HAS BEEN ASSIGNED
;FITHGH SEES IF HIGH SEG AND INCREASES IN-CORE COUNT(USUALLY TO 1)
; FOR JOB BEING SWAPPED IN(SWPIN ALREADY SET TO JOB # BY PREVIOUS CALL
; TO FININ FOR LOW SEGMENT OF THIS JOB
FITHGH::CAIG J,JOBMAX## ;IS THIS A HIGH SEGMENT
POPJ P, ;NO,
;DON'T NEED TO CLEAR LEFT HALF OF MIGRAT HERE SINCE BITS AREN'T ON FOR HI SEG
CAME J,MIGRAT## ;IS THIS A MIGRATING HIGH SEGMENT?
JRST FITHG1 ;NO, DO NORMAL STUFF
LDB T1,IMGIN## ;ELSE DON'T INCREASE IN-CORE COUNT, BUT
ADDM T1,CORTAL## ;DO ADJUST CORTAL
POPJ P,
FITHG1: MOVE T1,JBTSWI##(J) ;YES, GET JOB NUMBER(SET BY FININ) THAT
; GOES WITH THIS HIGH SEG
MOVSI F,(JS.SIP) ;INDICATE A SWAP IS IN PROGRESS FOR THIS JOB
IORM F,JBTST2##(T1) ; SO IT DOESN'T GET PICKED TO BE SWAPPED OUT
; WHILE THE HIGH SGEMENT IS BEING SWAPPED IN FOR IT
JRST INCCNT ;AND INCREMENT INCORE COUNT
;ROUTINE TO CHECK IF THIS WAS A HIGH SEG JUST SWAPPED OUT
;IF YES, RETURN JOB NUMBER SO LOW SEG CAN BE SWAPPED OUT(IF NOT ACTIVE IO)
;CALL: MOVE J,HIGH OR LOW SEG NUMBER JUST FINISHED SWAPPING OUT
; PUSHJ P,FINOT
; RETURN1 - LOW SEG TO BE WRITTEN, C(J) SET TO JOB(LOW SEG) NUMBER
; RETURN2 - NOTHIGN MORE TO SWAP OUT FOR THIS JOB
FINOT:: CAIG J,JOBMAX## ;IS SEG JUST WRITTEN A HIGH SEG?
JRST CPOPJ1## ;NO, IT WAS A LOW SEG-NOTHING MORE TO DO
MOVSI T1,JXPN ;YES, CLEAR EXPAND BIT FOR THIS HIGH SEG
ANDCAM T1,JBTSTS##(J) ;IN CASE IT WAS ON.
SKIPN T1,SWPOUT## ;IF LOW SEG NO. IS 0,THIS SWAPOUT WAS
;A HIGH IDLE SEG(IF NO ASSOCIATED LOW SEG)
JRST FINOT1 ;YES,ADJUST CORTAL AND GIVE NOTHING MORE TO
;SWAPOUT RETURN(ALWAYS SKIP RETURN)
HLL J,JBTSGN##(T1) ;DECREMENT HIGH SEG IN CORE COUNT
PUSHJ P,DECCNT ;WITH CORRECT CORCNT BIT FROM TABLE
;FOR JOB FOR WHICH IT WAS JUST SWAPPED OUT
JFCL ;ALREADY DECREMENTED. IGNORE.
MOVE T1,SWPOUT## ;JOB NUMBER THAT SWAPPING IS IN PROGRESS FOR
MOVE T1,JBTSTS##(T1) ;JOB STATUS
TLNE T1,SHF ;SWAPPING I/O IN PROGRESS FOR THIS LOW SEGMENT?
JRST CPOPJ1## ;YES, NOTHING TO DO
JRST RETJOB ;YES, RETURN JOB NUMBER(LOW SEG NUMBER)
; TO TRY TO BE SWAPPED OUT
FINOT1: LDB T1,IMGOUT## ;GET SIZE OF SHARABLE HIGH DATA SEG
MOVNS T1 ;DECREMENT CORTAL SINCE SWAPPING IDLE CORE
ADDM T1,CORTAL## ;DOESN'T REALLY INCREASE FREE+IDLE+DORMANT COUNT
MOVSI T1,NSHF ;CLEAR NSHF WHICH WAS TURNED
ANDCAM T1,JBTSTS##(J) ; ON TO KEEP THE SEGMENT FROM APPEARING
; DORMANT DURING THE SWAP OUT
PUSHJ P,DLDISQ ; NOT IN CORE ANY MORE
JRST CPOPJ1## ;SKIP RETURN,NO LOW SEG TO SWAP OUT
;ROUTINE TO COMPUTE AMOUNT OF CORE NEEDED TO GET THIS USER INTO CORE
;CALL: MOVE J,JOB NUMBER OR HIGH SEG NUMBER IF LOW SEG ALREADY IN
; MOVE P1,JBTIMI ;SIZE OF THIS SEG WHEN SWAPPED IN(OR O IF ALREADY IN)
; PUSHJ P,FITSIZ
; RET1 - CANNOT FIT THIS USER IN(P1=SUM OF SEGS NEEDED)
; RET2 - BOTH WILL FIT(P1 RESTORED TO SIZE OF THIS SEG)
; J RESTORED ON BOTH RETURNS
FITSIZ::JUMPL J,CPOPJ1## ;PDB'S ALWAYS FIT
PUSH P,P1 ;SAVE SIZE OF THIS SEG FOR RETURN
PUSH P,J ;SAVE LOW OR HIGH SEG NUMBER
CAILE J,JOBMAX## ;IS THIS A LOW SEG(IF NO, LOW SEG ALREADY IN)?
JRST FITCHK ;YES--NO PDB FOR HISEGS
SKIPG J,JBTSGN##(J) ;YES, DOES THIS JOB HAVE A REAL HIGH SEG?
JRST FITCHK ;NO, GO SEE IF JUST THIS HIGH OR LOW SEG WILL FIT
LDB P2,IMGIN## ;YES, INCLUDE SIZE OF HIGH SEG WHEN SWAPPED IN
SKIPN JBTADR##(J) ;IS IT IN CORE SO NO SWAP IN NEEDED?
ADD P1,P2 ;NO, ADD LENGTH OF HIGH SEG IF NEEDED
FITCHK: POP P,J ;RESTORE LOW OR HIGH SEG NUMBER
MOVE T1,P1 ;COPY TO P1
SUB T1,PAGOUC## ;THESE PAGES CAN BE MADE AVAILABLE
CAMLE T1,CORTAL## ;IS AMOUNT OF CORE REQUIRED, AVAILABLE?
; EVEN IF ALL CORE DORMANT SEGS ARE DELETED
JRST TPOPJ## ;NO, POP OFF SIZE OF SEG AND RETURN
; AND SCAN FOR JOB TO SWAP OUT
POP P,P1 ;RESTORE SIZE OF THIS SEG FOR RETURN
JRST CPOPJ1## ;RETURN AND TRY SHUFFLING TO GET A HOLE BIG ENOUGH
; IF THAT NOT GOOD ENOUGH, DELETE SOME DORMANT
; SEGS FROM CORE
;ROUTINE TO RETURN HIGH PRIORITY QUEUE NO FOR A JOB
; IF ITS HIGH SEG IS BEING FIT INTO CORE
;CALL: MOVE J,FIT(LOW OR HI SEG)
; PUSHJ P,FITHPQ
; RETURN WITH J=JOB NO BEING FITTED
FITHPQ::CAILE J,JOBMAX## ;IS THIS A HIGH SEG BEING FIT?
MOVE J,JBTSWI##(J) ;YES, RETURN JOB NO.
POPJ P, ;RETURN
;ROUTINE TO COMPUTE SIZE OF CORE FREED UP IF A JOB WERE TO BE FORCED OUT
;CALL: MOVE J,JOBNUMBER
; MOVE F,LOW SEG SIZE IN 1K BLOCKS
; PUSHJ P,FORSIZ
; RETURN - AC F INCREMENTED APPROPRIATELY(C(J)=JOB NUMBER)
; ACS T1 AND T2 ARE PRESERVED BECAUSE THEY ARE IN USE BY
; QUEUE SCANNING ROUTINES
FORSIZ::PUSHJ P,SAVE3## ;SAVE P1 - P3
MOVSI P3,SWP ;SWP BIT SET WHEN HIGH SEG SWAPPED
TDNN P3,JBTSTS##(J) ;HAS HIGH SEG ALREADY BEEN SWAPPED OUT FOR
;THIS JOB(OR IN-CORE COUNT DECREMENTED)?
SKIPG P3,JBTSGN##(J) ;NO, DOES JOB HAVE A REAL HIGH SEG?
POPJ P, ;NO, RETURN J STILL SETUP TO JOB NUMBER
; (MAYBE SPYSEG)
MOVE P2,JBTSTS##(P3) ;IS HIGH SEGMENT SWAPPABLE?
TLNE P2,SNA ;IDLE?
TLNN P2,NSWP ;YES, AND LOCKED?
JRST FORSZ1 ;NO, PROCEED
POPJ P, ;YES, CAN'T BE SWAPPED OUT
FORSZ1: LDB P2,[POINT 21,JBTIMI##(P3),35]
JUMPE P2,CPOPJ## ;NOT IN CORE - RETURN
MOVE P3,JBTSTS##(P3) ;GET NO. OF IN CORE USERS
TLNN P3,SHRSEG ;SHAREABLE?
JRST FORSZ2 ;NO
SKIPLE SGTLIM## ;YES. RETAINING HISEGS?
SKIPE ZAPIDF## ;YES. FRUSTRATED?
JRST FORSZ2 ;NOT RETAINING OR FRUSTRATED.
POPJ P, ;RETAINING. DON'T COUNT HISEG SIZE
FORSZ2: ANDI P3,ICCMSK ;LET IT COUNT SIZE
IDIV P2,P3 ;COMPUTE HISEG SIZE/NO. OR USERS
ADDI F,1(P2) ;ADD THIS TO TOTAL JOB SIZE AND ADD 1 FOR LUCK?
POPJ P, ;RETURN
;ROUTINE TO FREE UP CORE FOR SWAPPING SYSTEMS
;BY DELETING ONE DORMANT OR IDLE SEGMENT IN CORE (DISK COPY LEFT IF ANY)
;CALL: PUSHJ P,FRECR1
;ERROR RETURN-WITH J=HIGH IDLE SEG WITH NO COPY ON DISK (IT MUST BE
;SWAPPED OUT BEFORE CORE IS FREED SINCE IDLE SEG IS IN SOME SWAPPED OUT USERS
;VIRTUAL ADDRESSING SPACE)
; SKIP RETURN - J PRESERVED
FRECR1::PUSH P,T1 ;SAVE CORE ARG(ON CALLS TO FRECOR)
PUSH P,J ; SAVE JOB OR SEG NUMBER
MOVNI J,DISQ## ;SCAN JUST DORMANT/IDLE HIGH SEGMENTS
MOVEI T1,ICCMSK ;MASK FOR CHECKING NON-ZERO IN-CORE COUNT
HRLI T1,NSHF!SNA ;LOOK FOR DORMANT SEGMENTS FIRST
; SNA =0 AND IN CORE COUNT = 0
FREC0: HRRE J,JBTDIQ##(J) ;SCAN DORMANT/IDLE SEGMENTS FROM OLDEST
JUMPLE J,FREC1 ;GO TO NEXT SECTION IF FINISHED
SKIPE JBTADR##(J) ;DOES THIS HIGH SEG HAVE CORE?
TDNE T1,JBTSTS##(J) ;YES, IS IN-CORE COUNT EQUAL TO 0?
JRST FREC0 ;NOT DORMANT IN CORE. CONTINUE
SKIPGE ZAPIDF## ;SWAPPER GETTING FRUSTRATED?
JRST FREC0A ;YES. DELETE ANYWAY
MOVE T3,UPTIME## ;SYSTEM UPTIME
SUB T3,JBTIDT##(J) ;MINUS TIME WENT DORMANT
CAMG T3,SGTLIM## ;LESS THAN LIMIT?
JRST FREC0 ;YES. DON'T DELETE IT
FREC0A: TLO J,-1 ;J MUST BE < 0 AT FREC4 WHEN
JRST FREC4 ;CALLED BY FRECR1
FREC1: MOVNI J,DISQ## ;NOW LOOK AT IDLE SEGMENTS
MOVEI T3,ICCMSK ;MASK FOR CHECKING NON-ZERO IN-CORE COUNT
HRLI T3,NSHF!NSWP ;NOW LOOK FOR UNLOCKED IDLE SEGMENTS
FREC2: HRRE J,JBTDIQ##(J) ;LOOK AT DORMANT/IDLE FROM OLDEST
JUMPLE J,FREC2A ;CANT HELP IF NO MORE
SKIPE JBTADR##(J) ;DOES THIS SEGMENT HAVE CORE?
TDNE T3,JBTSTS##(J) ;IS IT IDLE AND NOT LOCKED?
JRST FREC2 ;NOT IDLE IN CORE. CONTINUE
FREC3: MOVSI T1,SHRSEG ;SHARABLE SEGMENT BIT
TDNN T1,JBTSTS##(J) ;IS THIS A NON-SHARABLE HIGH SEGMENT?
JRST FREC2 ;NO, IT LOOKS IDLE BUT CANNOT BE
MOVE T1,FIT## ;SEGMENT BEING SWAPPED IN
CAIG T1,JOBMAX## ;IS IT A HIGH SEGMENT?
SKIPG T1,JBTSGN##(T1) ;NO, DOES IT HAVE A HIGH SEGMENT?
JRST FREC3A ;NO, ITS NOT AN IDLE SEGMENT BELONGING TO THE
TLZ T1,-1 ; JOB BEING SWAPPED IN SO DELETE IT
CAIN T1,(J) ;IS JOB BEING SWAPPED IN SHARING THIS IDLE SEG?
JRST FREC2 ; IDLE SEGMENT
FREC3A: SKIPGE ZAPIDF## ;SWAPPER GETTING FRUSTRATED?
JRST FREC3B ;YES. DELETE ANYWAY
MOVE T1,UPTIME## ;SYSTEM UPTIME
SUB T1,JBTIDT##(J) ;MINUS TIME WENT IDLE
CAMG T1,SGTLIM## ;LESS THAN LIMIT?
JRST FREC2 ;YES. DON'T DELETE
FREC3B: TLO J,-1 ;J MUST BE LESS THAN ZERO WHEN
JRST FREC4 ;FREC4 ENTERED FROM FRECR1
FREC2A: POP P,J ;MEMORY IS FRAGMENTED
AOS -1(P) ;GIVE DOUBLE SKIP RETURN SO
JRST TPOPJ1## ; SCHED WILL SHUFFLE OR SCAN FOR OUTPUT
;HERE FROM THE LOCK UUO TO DELETE A SPECIFIC DORMANT
; OR IDLE SEGMENT
FREC4::
IFN FTLOCK,<
PUSH P,J ;REMEMBER WHERE CALLED FROM
>
TLZ J,-1 ;CLEAR OUT LH OF SEG NUMBER
LDB T1,IMGOUT## ;DOES HIGH SEG ALSO HAVE COPY ON DISK?
JUMPN T1,FREC5 ;IF NON-ZERO, DO NOT CLEAR NAME SINCE NEW USERS
; CAN USE DISK COPY
;HERE FROM FRECR1 ROUTINE IF FOUND AN IDLE OR DORMANT SEGMENT IN CORE
;WITH NO DISK COPY SO CANNOT FREE UP CORE WITHOUT SWAPPING IDLE HIGH SEG FIRST
; NOT NECESSARY TO SWAP DORMANT SEG BUT USEFUL FOR MODIFIED HIGH
;SEGMENTS LIKE LOGIN TO STAY AROUND LONGER
SETZM SWPOUT## ;SET ASSOCIATED JOB NUMBER TO ZERO
;AS A FLAG THAT THERE IS NO LOW SEGMENT
MOVSI T1,NSHF ;TURN ON NSHF
IORM T1,JBTSTS##(J) ; SO THAT THE SEGMENT WON'T APPEAR TO BE
; DORMANT DURING THE SWAP OUT
IFN FTLOCK,<
POP P,T1 ;IF CALLED FROM LOCK
JUMPG T1,CPOPJ## ;DON'T RESTORE ACS
>
POP P,T1 ;EXIT AS ERROR RETURN FROM FREC1
JRST TPOPJ## ;WITH J=HIGH SEG TO BE SWAPPED OUT BECAUSE
;CORE NEEDED AND THERE IS NO COPY
;ON DISK (WRITE LOCK OFF)
;HERE IF HIGH SEG ALREADY HAS COPY ON DISK
FREC5: PUSHJ P,KDORCR ; JUST RETURN DORMANT OR IDLE CORE
; BUT LEAVE DORMANT DISK COPY
; STILL DORMANT ON DISK FOR NEW USERS
IFN FTLOCK,<
POP P,J ;IF CALLED FROM LOCK
JUMPG J,CPOPJ1## ;DON'T RESTORE ACS
>
POP P,J ;RESTORE JOB OR SEG NUMBER
JRST TPOPJ1## ;RESTORE CORE REQUEST AND SKIP RETURN
;ROUTINE TO LOOK FOR DORMANT OR IDLE SEGMENTS WHICH ARE IN CORE
;CALL: MOVE J,WHERE TO START LOOKING
; MOVE T1,SEGMENT DESCRIPTOR BITS WHICH MUST BE OFF TO FIND THE SEGMENT
; PUSHJ P,FNDSDI
;RETURNS CPOPJ IF NONE FOUND, CPOPJ1 IF ONE FOUND, J = SEGMENT NUMBER
;CLOBBERS T3
FNDSDI: MOVEI T3,SEGN## ;NUMBER OF SEGMENTS TO LOOK AT
FNDSD1: HRRZS J ;MAKE SURE NO JUNK
CAILE J,JBTMAX## ;REACHED THE TOP?
HRRZ J,SEGPTR## ;YES, START OVER AT THE BOTTOM
SKIPE JBTADR##(J) ;SEGMENT HAVE CORE IN CORE?
TDNE T1,JBTSTS##(J) ;YES, DORMANT OR IDLE?
AOSA J ;NO, LOOK AT THE NEXT SEGMENT
JRST CPOPJ1## ;YES, GIVE FOUND ONE RETURN
SOJG T3,FNDSD1 ;NO, LOOK AT NEXT
POPJ P, ;NONE FOUND RETURN
;ROUTINE TO CHECK IF JOB HAS A HIGH SEG WHICH NEEDS TO BE SWAPPED OUT
;IF YES, IT IS WRITTEN FIRST BEFORE LOW SEG
;IN THIS WAY THE IO BUFFERS MAY STAY ACTIVE LONGER
;IN FACT, THE HIGH SEG CAN BE BROUGHT BACK IN WITHOUT LOW SEG
;EVER LEAVING CORE.
;SHF BIT IS SET IN JOB STATUS WORD IF JOB ONLY HAS A LOW SEG, SO IO WILL STOP
;ON NEXT BUFFERFUL. THUS ONLY 2 SEG JOBS HAVE ACTIVE IO LONGER.
;BUFFER ADVANCE ROUTINES LOOK AT SHF BUT NOT SWP FOR JOB
;CALL: MOVEM FIT SWAP IN JOB NO.,FIT
; MOVE J,LOW OR HIGH SEG NUMBER
; PUSHJ P,FORHGH
; ALWAYS RETURN WITH HIGH OR LOW SEG TO BE WRITTEN IN J
;
FORHGH::MOVSI T1,SWP ;SET WHEN HIGH SEG SWAPPED OUT OR IN-CORE
; COUNT REDUCED
CAIG J,JOBMAX## ;IS THIS A HIGH SEG(ONLY IF WAITING FOR HIGH SEG IO)
TDNE T1,JBTSTS##(J) ;NO, HAS HIGH SEG ALREADY BEEN SWAPPED FOR THIS USER?
POPJ P, ;YES, TRY HIGH SEG AGAIN OR WRITE LOW SEG
IORM T1,JBTSTS##(J) ;NO,SET SWAP BIT IN JOB STATUS WORD TO INDICATE
; 1. HIGH SEG SWAPPED IF ANY OR LOW SEG SWAPPED IF NONE
SKIPLE JBTSGN##(J) ;DOES JOB HAVE A REAL HIGH SEG IN CORE OR DISK?
JRST FORH1 ;YES
MOVSI T1,SHF ;NO, SET WAITING TO SHUFFLE BIT IN JOB STATUS WORD
; SO IO WILL STOP AFTER NEXT BUFFERFUL(MAYBE SPYSEG)
IORM T1,JBTSTS##(J) ;CHECK EVERY BUFFERFUL IN ADVBFF, ADVBFE ROUTINES
POPJ P, ;RETURN AND TRY TO SWAP OUT LOW SEG
;ROUTINE TO CHECK FOR DANGLING HIGH SEGMENT
; WHEN A JOB CANNOT BE FIT INTO CORE
;DANGLING CAN ONLY HAPPEN IF IN-CORE COUNT COUNTED UP
; FOR A HI-SEG FOR JOB BEING SWAPPED IN BECAUSE JOB BEING SWAPPED OUT
; HAD SAME HI-SEG (USUALLY IN-CORE COUNT COUNTED UP AFTER BOTH SEGS ARE
; SWAPPED IN)
;CALL: MOVE J,FIT ;JOB (OR HIGH SEG NO) WHICH CANNOT FIT
; SETZM FIT ;PRETEND WE WEREN'T TRYING TO FIT THE JOB
; IN WITH THE DANGLING HIGH SEGMENT
; PUSHJ P,NOFITH
; SWAP OUT THE FITJOB, J=JOB NO. IF HI-SEG ALREADY ON DISK, =HI SEG NO IF NEEDS SWAPOUT
; NOT A JOB, OR NO HIGH SEG, OR HI-SEG IN CORE COUNT NOT UP FOR
; THIS JOB (2ND RETURN IS USUAL CASE)
NOFITH::MOVSI T1,CORCNT ;HI-SEG IN CORE COUNT UP FOR THIS JOB
CAIG J,JOBMAX## ;IS THIS A LOW SEG BEING FITTED?
TDNN T1,JBTSGN##(J) ;YES, IS IN CORE COUNT UP FOR THIS JOB
JRST CPOPJ1## ;NO, GIVE USUAL NO ACTION RETURN
;YES, FALL INTO FORH1
IFN FTLOCK,<
MOVSI T1,NSWP ;IF THE HIGH SEGMENT IS LOCKED,
MOVE T2,JBTSGN##(J) ;BY DEFINITION ITS NOT DANGLING.
TDNE T1,JBTSTS##(T2) ;IS IT LOCKED?
JRST CPOPJ1## ;YES, GIVE NO ACTION RETURN
>
FORH1: HRRZM J,SWPOUT## ;REMEMBER THIS JOB NUMBER DURING HIGH SEG SWAPOUT
MOVE T1,J ;SET UP JOB NUMBER FOR DECCNT ROUTINE
MOVE J,JBTSGN##(J) ;GET HIGH SEG NUMBER FOR THIS JOB
SKIPE R,JBTADR##(J) ;IS HIGH SEG STILL IN CORE?
; MAY NOT BE IF JOB JUST CONNECTED TO HIGH SEG
; BY GET(XPANDH) OR HIGH SEG SWAPPED OUT PREVIOUSLY
;SETUP R IN CASE KCOREH CALLED
PUSHJ P,DECCNT ;YES, DECREMENT IN CORE USE COUNT
JRST RETJOB ;STILL GREATER THAN 0(OR NOT IN CORE), SWAP OUT LOW SEG
IFN FTLOCK,<
PUSHJ P,LOKHGH## ;SEE IF THE HIGH SEGMENT IS LOCKED OR IS
; BEING LOCKED
JRST FORH1A ;YES, DON'T DELETE HIGH SEGMENT SINCE ITS LOCKED OR
;THE LOW SEGMENT WILL BE SWAPPED IN AS SOON AS
;THE HIGH SEGMENT IS IN PLACE. INSTEAD JUST
; COUNT IN CORE COUNT BACK UP FOR
; THIS JOB AND SWAP OUT
; ONLY THE LOW SEG.
>
MOVE T1,FIT## ;IS JOB BEING FITTED IN(0 IF NOT FITTING IN)
HRRZ T2,JBTSGN##(T1) ;ABOUT TO USE THIS SAME HIGH SEG?
CAIG T1,JOBMAX## ;IS SEGMENT BEING FITTED A LOW SEG(JOB #)
; (USUALLY SINCE SWAPPER DOES NOT SWAP IN UNTIL
; ROOM FOR BOTH HIGH AND LOW SEGS
CAIE T2,(J) ;YES, FIT JOB HIGH SEG SAME?
JRST FORH2 ;NO, EITHER FIT HIGH SEG(RARE) OR NOT SAME
HLL J,JBTSGN##(T1) ;YES, SETUP PROPER LH FOR JOB BEING FITTED IN.
; IN PARTICULAR PRESERVE UWPOFF IN CASE JOB
;BEING SWAPPED OUT HAS WRITE LOCK OFF
;AND JOB BEING SWAPPED IN HAS IT ON.
FORH1A: PUSHJ P,INCCNT ;YES,INCREMENT HIGH SET IN CORE COUNT FOR JOB
; ABOUT TO BE FITTED IN CORE EVEN THOUGH ITS LOW
; SEG HAS YET TO BE SWAPPED IN. (COUNT WILL ONLY
; BE INCREMENTED ONCE SINCE CORCNT BIT WILL BE SET)
; HIGH SEG WILL NOT APPEAR IDLE IN CORE
; DURING OTHER SWAPOUTS AND FIT SWAP IN
; LEAST FRECOR GRAB IT
JRST RETJOB ;RETURN AND SWAP JUST LOW SEG OUT (LEAVING
; HIGH SEG IN CORE FOR FIT USER)
;HERE TO SWAP OUT HIGH SEG UNLESS ALREADY ON DISK
FORH2: LDB T1,IMGIN## ;INPUT SIZE
JUMPE T1,RETJOB ;RETURN JOB IF HI-SEG CORE IS INCLUDED
; IN THE LOW SEG.
MOVE T1,SWPOUT## ;JOB NUMBER OF JOB WHICH HAS HIGH SEG
; WHICH MAY BE WRITTEN
MOVSI T2,JXPN ;SEGMENT EXPANDING BIT
TDNE T2,JBTSTS##(J) ;IS THE SEGMENT EXPANDING?
PJRST INCCNT ;YES, INCREMENT IN-CORE COUNT AND
; SWAP OUT THE HIGH SEGMENT SINCE
; IT HAS NO DISK COPY (UCORHI
; CALLED ZERSWP)
LDB T2,IMGOUT## ;IS A COPY OF SEG ALREADY ON DISK?
PJUMPE T2,INCCNT ;IF NOT(0), RETURN AND WRITE HIGH SEG
; AFTER INCREMENTING IN-CORE COUNT TO 1
; SO IT WILL NOT APPEAR IDLE DURING SWAP OUT
MOVSI T1,SHRSEG ;SHAREABLE SEGMENT?
SKIPLE SGTLIM## ;RETAINING HISEGS?
SKIPE ZAPIDF## ;YES FRUSTRATED?
JRST FORH2D ;NOT RETAINING OR FRUSTRATED
TDNN T1,JBTSTS##(J) ;RETAINING. SHAREABLE? (DON'T DELETE IF IT IS)
JRST FORH2D ;NOT SHAREABLE, GO DELETE CORE IMAGE (SHOULD NEVER GET HERE)
LDB T2,PCORSZ## ;ACCOUNT FOR MAKING SEGMENT IDLE IN CORE
ADDI T2,1 ;WE KNOW IT IS NOT LOCKED, HAS CORE, IS
ADDM T2,CORTAL## ;SHAREABLE, & HAS NO OTHER USERS IN CORE
JRST RETJOB ;NOW SWAP OUT LOW SEGMENT
FORH2D: PUSHJ P,KCOREH ;ALREADY ON DISK, JUST RETURN CORE
; AND FLAG HIGH SEG AS ON DISK(SET SWP=1)
RETJOB: PUSHJ P,CHKTAL ;CHECK CORTAL WITH CORTAB, HALT IF DIFFER
MOVE J,SWPOUT## ;RETURN JOB NUMBER(LOW SEG NUMBER)
POPJ P, ;AND TRY TO SWAP IT OUT
;SUBROUTINE TO EXPAND A HIGH (SHARABLE) SEGMENT AT UUO LEVEL
;CALL: MOVE J, JOB OR HIGH SEG NO. EXPANDING
; PUSHJ P,XPNHGH
; ALWAYS RETURN WITH J=JOB NUMBER
;CALLED FROM XPANDH IN SCHED1.
XPNHGH::CAIG J,JOBMAX## ;IS THIS A LOW SEG EXPANDING?
POPJ P, ;YES, RETURN IMMEDIATELY (MAYBE FROM
; RECURSIVE CALL BELOW)
TLNN J,SHRSEG ;NO, IS THIS HIGH SEG NON-SHARABLE?
JRST XPNRET ;YES, JUST RETURN CURRENT JOB NO.
PUSHJ P,SAVE1## ;NO, SAVE P1 ON STACK
MOVSI T1,JXPN ;FLAG THIS SHARABLE HIGH SEG AS EXPANDING
IORM T1,JBTSTS##(J) ;SO IF OTHER JOBS GETSEG, THEY WILL BE SWAPPED OUT
HRRZ P1,J ;SAVE EXPANDING SHARABLE HIGH SEG NO.
;LOOP TO SCAN ALL JOBS FOR ONES USING THIS SHARABLE HIGH SEG AND FLAG JOBS AS EXPANDING IF IN CORE
MOVE J,HIGHJB## ;SCAN ALL JOBS INITIALIZED
XPNLP1: SKIPLE JBTSGN##(J) ;A REAL HIGH SEGMENT?
CAIE P1,@JBTSGN##(J) ;DOES THIS JOB HAVE THE SAME HIGH SEG?
SOJG J,XPNLP1 ;NO, FINISHED (NULL JOB=0 NEVER HAS HIGH SEG)
JUMPLE J,XPNRET ;YES, FINISHED?
MOVSI T1,SWP ;IS THIS JOB SWAPPED OR LOCKED IN CORE?
TDNN T1,JBTSTS##(J) ;
PUSHJ P,XPANDH## ;NO, EXPAND THIS JOB BY SWAPPING OUT (UNLESS LOCKED)
SOJG J,XPNLP1 ;FINISHED?
XPNRET: MOVE J,.CPJOB## ;YES, ALWAYS RETURN CURRENT JOB NO.
; AS LOW SEG NO. ASSOCIATED WITH EXPANDING
; HIGH SEG NO.
POPJ P, ;RETURN (RESTORE P1)
;ROUTINE TO CHECK FOR A HIGH SEG WITH SWAP READ ERROR
;CALLED FROM ZERSWP WHENEVER PHYSICAL DISK SPACE IS BEING RECLAIMED
;CALL: MOVE J,LOW OR HIGH SEG NO.
; PUSHJ P,ZERSWH
; LOW SEG OR NO ERROR IN HIGH SEG
; ERROR IN HIGH SEG (ERROR BIT IS THEN CLEARED)
ZERSWH::MOVE T2,JBTSTS##(J) ;SEGMENT STATUS WORD
CAILE J,JOBMAX## ;IS THIS A HIGH SEG?
TLNN T2,SERR ;YES, DOES IT HAVE A SWAP READ ERROR?
POPJ P, ;NO, RETURN AND RECLAIM PHYSICAL DISK SPACE
MOVSI T2,SERR ;YES, SWAP READ ERROR FLAG
ANDCAM T2,JBTSTS##(J) ;CLEAR IT IN HIGH SEG STATUS WORD
; SO BE READY TO COUNT A NEW ERROR
; IF IT OCCURS IN A NEW PLACE
JRST CPOPJ1## ;SKIP RETURN AND DO NOT RECLAIM DISK SPACE
; SO NO ONE WILL BE ABLE TO USE IT
;SUBROUTINE TO DELETE ENOUGH DORMANT SEGS ON THIS UNIT TO MAKE ROOM
;ARGS P2=NUMBER 1K BLOCKS NEEDED
; U=ADDR OF UNIT DATA BLOCK
;PRESERVES P2,U,J
;CLOBBERS P1,P3 ***NOTE: VIOLATION OF SUB CALL CONVENTIONS (KCORE1)
;SKIP RETURN IF OK, NON-SKIP IF NOT
DODELE::PUSH P,J
PUSH P,P2
MOVE J,SEGPTR##
DODEL1: LDB T1,IMGOUT## ;GET SPACE ON DISK OF THIS SEG
SKIPL T2,JBTSTS##(J) ;SEG UNUSED? (SNA=0)
CAIN T1,0 ;YES, SPACE ON DISK?
JRST DODEL3 ;NO, KEEP LOOKING
TLNE T2,NSHF ;IS THIS SEGMENT CURRENTLY BEING SWAPPED OUT
JRST DODEL3 ;YES, KEEP LOOKING
SKIPL T1,JBTSWP##(J) ;SEE IF THIS SEG HAS SPACE ON OUR UNIT
JRST DODELA ;NOT FRAGMENTED
; TLZ T1,FRGSEG
DODELB: HLRE T2,(T1) ;GET K OF THIS PIECE
JUMPLE T2,DODELC ;NOT CORE, POINTER TO NEW LIST
LDB T2,[POINT 3,(T1),18] ;GET INDEX OF UNIT IN SWPTAB
CAMN U,SWPTAB##(T2) ;SEE IF ITS US
JRST DODEL2 ;YES, WE DO HAVE SPACE HERE!
AOJA T1,DODELB ;NO, TRY NEXT PIECE
DODELC: SKIPE T1,(T1) ;SEE IF END OF LIST
JRST DODELB ;NO, KEEP GOING
JRST DODEL3 ;YES, WE CANT HELP
DODELA: LDB T1,JBYSUN## ;NOT FRAGMENTED, GET UNIT SEG IS ON
CAME U,SWPTAB##(T1) ;SKIP IF ON THIS UNIT
JRST DODEL3 ;NO
DODEL2: HLLM J,(P) ;SAVE LEFT HALF OF J ON P=PART OF AOBJN PTR
TLZ J,-1 ;CLEAR LH OF J SO J=SEGMENT NUMBER
PUSH P,P4 ;CLRNAM COULD CLOBBER IT
PUSHJ P,CLRNAM ;DELETE THE DORMANT SEGMENT
POP P,P4 ;STUFF THE CALLER WANTS
HLL J,(P) ;RESTORE LEFT HALF OF AOBJN PTR
HRRZS P2,(P) ;P2=NUMBER OF 1K BLOCKS NEEDED
CAMG P2,UNIFKS##(U) ;SKIP IF STILL NOT ENOUGH SPACE
JRST DODELX ;DONE, EXIT
DODEL3: AOBJN J,DODEL1 ;JUMP IF MORE SEGS
SOS -2(P) ;OFFSET SKIP RETURN, GIVE ERROR RETURN, NOT ENOUGH ROOM
DODELX: POP P,P2 ;POP OFF NUMBER 1K BLOCKS NEEDED
JRST IPOPJ1##
;SUBROUTINE TO SEE IF BY DELETING DORMANT SEGS WILL BE ENOUGH ROOM
; ON THIS UNIT
;ARGS P2=NUMBER 1K BLOCKS NEEDED
; U=ADDR OF UNIT DATA BLOCK
;CALL MOVEI P2,1K BLOCKS NEEDED
; MOVEI U,ADDR
; PUSHJ P,IFDELE
; ERROR RETURN - CANT CREATE ENOUGH SPACE ON THIS UNIT
; OK RETURN - CAN CREATE ENOUGH SPACE BY DELETING SEGS
;PRESERVES P1,P2,P3,P4,U,J
IFDELE::PUSH P,J
MOVE T2,UNIFKS##(U) ;T2 IS COUNTER OF AVAILABLE SPACE
MOVE J,SEGPTR##
IFDEL1: LDB T1,IMGOUT## ;GET DISK SPACE OF THIS SEG
SKIPL JBTSTS##(J) ;SEG UNUSED? (SNA=0)
CAIN T1,0 ;YES, SPACE ON DISK?
JRST IFDEL3 ;NO, KEEP LOOKING
SKIPL JBTSWP##(J) ;FRAGMENTED?
JRST IFDEL2 ;NO
PUSH P,P1 ;YES, SAVE P1
MOVE T1,JBTSWP##(J) ;GET FRAGMENT POINTER
; TLZ T1,FRGSEG
IFDFK: HRRZ P1,T1 ;P1=ADDR OF LIST
IFDFK1: MOVE T3,(P1) ;DISK ADDR
HLRE T1,(P1) ;NUMBER OF J
JUMPLE T1,IFDFK2 ;JUMP IF NOT DISK SPACE
LDB T3,[POINT 3,T3,18] ;GET UNIT INDEX
CAMN U,SWPTAB##(T3) ;SEE IF ITS THE RIGHT UNIT
ADD T2,T1 ;YES
AOJA P1,IFDFK1
IFDFK2: SKIPE T1,(P1) ;SKIP IF END OF LIST
JRST IFDFK
POP P,P1 ;RESTORE P1
JRST IFDEL4
IFDEL2: LDB T3,JBYSUN## ;GET SWAPPING UNIT NUMBER
CAMN U,SWPTAB##(T3)
ADD T2,T1 ;IF RIGHT UNIT, COUNT ITS SPACE
IFDEL4: CAML T2,P2 ;HAVE ENOUGH YET?
JRST IPOPJ1## ;YEAH, MAN
IFDEL3: AOBJN J,IFDEL1 ;NO, KEEP ON
JRST IPOPJ## ;CANT DO IT
SUBTTL UUOCON - UUO HANDLING ROUTINES
;ROUTINE TO CHECK TO SEE IF A KNOWN SEGMENT IS BEING SUPERCEDED BY A FILE
;OF THE SAME NAME WITH EXTENSION OF .SHR IN THE SAME DIRECTORY.
;IF YES, THE SHARABLE SEGMENT IF FLAGGED AS NO LONGER SHARABLE FOR
;ADDITIONAL USERS(ITS NAME IS SET TO 0 IN JBTNAM). THE USERS
;WHO ARE USING IT WILL CONTINUE TO SHARE IT UNTIL ALL OF THEM ARE THROUGH.
;IF NO USERS ARE USING SEGMENT ON DISK OR CORE, ITS DISK SPACE WILL BE RETURNED.
;CALLED FROM CLOSE INPUT AND OUTPUT DUMP AND BUFFERED(RELSEG) AND SUCCESSFUL RENAME(RELSG1)
;CALL: MOVE F,ADR. OF DEVICE DATA BLOCK
; PUSHJ P,RELSEG
; ALWAYS RETURN (RELSEG)
; ALWAYS SKIP RETURN (RELSG1)
RELSEG::TLNE F,ENTRB ;HAS AN ENTER BEEN DONE(HERE ON CLOSE)?
; IS THIS OUTPUT CLOSE?
; I.E. WAS A FILE CREATED OR RECREATED?
PUSHJ P,FNDSGU ;YES, DOES A KNOWN SEG ALREADY HAVE THIS NAME?
; SEARCH USING OLD (RATHER THAN NEW) IF RENAME
POPJ P, ;NO, NO CONFLICT
JRST RNMSG1 ;YES, CLEAR NAME AND DELETE CORE AND DISK IF
; BUT LEAVE DIRECTORY NAME FOR SYSTAT
; SO IT CAN PRINT (OBS) P,P
; HIGH SEGMENT IS ALREADY DORMANT
;ROUTINE TO RESET HIGH SEG
;CALLED ON RESET UUO
;SETS USER:MODE WRITE PROTECT BIT ON IN HARDWARE AND SOFTWARE FOR THIS
;JOB ONLY(CURRENT JOB). OTHER JOBS MAY HAVE UWP ON OR OFF FOR
;SAME HIGH SEGMENT(EXCEPT THAT INITIALLY SETUWP UUO DOES NOT ALLOW
;TURNING UWP OFF IF HIGH SEG SHARABLE)
;CALL: MOVE J,CURRENT JOB NUMBER
; PUSHJ P,HRESET
; RETURN WITH APR RESET AND SOFTWARE RESET
HRESET::MOVSI T1,UWPOFF ;FLAG THIS USER AS HAVING UWP ON FOR HIGH SEG
ANDCAM T1,JBTSGN##(J) ;SO HE WILL NOT BE ABLE TO WRITE HIGH SEG
JRST SETMAP## ;GO DO DATAO APR AND SET UWP ON
;UUO ROUTINE TO SET OR CLEAR USER-MODE WRITE PROTECT(UWP)
;ON HIGH SEGMENT FOR CURRENT JOB
;CALL: MOVEI AC,0 OR 1(CLEAR OR SET UWP)
; MOVE J,CURRENT JOB NUMBER
; PUSHJ P,USTUWP
; ERROR RETURN - MACHINE OR MONITOR NOT HAVE 2 REG. CAPABILITY OR
; TRYING TO TURN OFF UWP AFTER R HAS BEEN MEDDLED WITH
; AND USER DOES NOT HAVE WRITE PRIV. TO FILE WHICH INIT HIGH SEG
; OR HIGH SEG IS A SPYSEG(IE PHYSICAL CORE)
; OK RETURN - WHETHER JOB HAS HIGH SEG OR NOT
; PREVIOUS SETTING OF UWP RETURNED IN AC(BOTH RETURNS)
USTUWP::PUSHJ P,SAVE2## ;SAVE ACS P1-P2
AOS (P) ;ASSUME OK RETURN
SKIPN J,JBTSGN##(J) ;DOES JOB HAVE A REAL OR SPY HIGH SEG?
JRST USTU0 ;NO, GIVE OK RETURN, BUT RETURN 0 AS PREVIOUS
; UWP SETTING
JUMPN T1,UWPON ;YES, IS USER TRYING TO TURN UWP ON?
IFN FTPEEKSPY,< ;PEEK AND SPY
JUMPL J,USTUE ;NO, IS THIS A SPY SEG? (IF YES, GIVE ERROR RETURN)
>
PUSHJ P,CHKHWC ;NO, HAS CURRENT JOB AVOIDED MEDDLING OR
;DOES CURRENT JOB HAVE WRITE PRIVILEGES TO FILE
; EVEN THOUGH MEDDLING WITH PROGRAM?
; MAYBE SHARED DATA SEGMENT WITH GETSEG UUO
USTUE: SOSA (P) ;NO, THEN DO NOT ALLOW PROGRAM TO TURN OFF UWP
TLOA J,UWPOFF ;YES, SO OK TO TURN OFF UWP, EVEN IF THIS
; IS SHARABLE HIGH SEG
UWPON: TLZ J,UWPOFF ;TURN OFF UWPOFF SO UWP WILL BE ON
TLNE J,UWPOFF ;WILL HIGH SEG BE WRITEABLE?
IFE FTMP,<
PUSHJ P,ZERSWP## ;YES, RETURN SWAPPING SPACE SO HIGH SEG
; WILL HAVE TO BE WRITTEN WHEN JOB
; IS SWAPPED OUT
>
IFN FTMP,<
PUSHJ P,[PUSHJ P,GGVMM## ;GET MM RESOURCE FOR CALL TO ZERSWP
PJRST ZERSWP##] ;RETURN SWAPPING SPACE, GIVE UP MM
>
MOVE T1,.CPJOB## ;CURRENT JOB NUMBER
PUSHJ P,COMIT ;COMPARE J WITH JBTSGN(T1), HALT IF DIFF.
EXCH J,JBTSGN##(T1) ;MARK NEW UWP SETTING FOR THIS USER AND GET OLD ONE
MOVEI T1,1 ;ASSUME UWP WAS ON FOR THIS USER
TLNE J,UWPOFF ;WAS UWP OFF?
USTU0: MOVEI T1,0 ;YES, RETURN 0
PUSHJ P,STOTAC## ;TO USER'S AC ARG
IFN FTKL10&FTMP,<
PUSHJ P,CLRCSH## ;CAUSE CACHE BITS TO BE CLEARED IN THE MAPS
; OF ALL JOBS SHARING THIS HIGH SEGMENT SO
; WRITTEN DATA WILL BE SEEN BY ALL
>
JRST SETMAP## ;GO RESET HARDWARE AND SOFTWARE RELOC.
; AND RETURN TO USER
;ROUTINE TO CHECK ACCESS PRIVILEGES FOR SHARED SEGMENTS
;CALL: MOVE J,HIGH SEG NUMBER
; MOVEI P1,FUNCTION (FNCEXC,FNCRED,FNCUPD)
; MOVE P2,JOB NUMBER
; PUSHJ P,CHKHSA
; CAN'T READ OR WRITE
; USER HAS PRIV IF SHARABLE, OR HIGH SEG NOT SHARABLE
;CHKHSW IS WRITE ENTRY POINT, CHKHWC IS WRITE FOR CURRENT JOB
;DTA READ OK IF DEVICE UNASSIGNED,SYSTEM, OR ASSIGNED TO THIS JOB
;DTA WRITE OK IF DEVICE UNASSIGNED OR ASSIGNED TO THAT JOB, EXCEPT CAN'T
;DEPOSIT SYSTEM TAPE
;CALLED FROM SAVGET TO SEE IF USER HAS READ PRIVILEGES TO SHARE
;CALLED FROM DEPOSIT COMMAND IF IN HIGH SEG TO SEE FI WRITE PROV
;CALLED FROM SETUWP IF TRY TO SET UWP TO 0 AND MEDDLE BIT IS ON TO
; SEE IF WRITE PRIV. OK
;ROUTINE TO CHECK WRITE PRIV FOR CURRENT JOB IF MEDDLING
;GIVE OK RETURN IF CURRENT JOB NOT MEDDLING
CHKHWC::TLNN J,MEDDLE ;HAS CURRENT USER BEEN MEDDLING WITH ITS HIGH SEG?
; OR IS THIS A SPY SEG?
PJRST CPOPJ1## ;NO, GIVE OK TO UPDATE THIS HIGH SEG RETURN
MOVE P2,.CPJOB## ;YES, CHECK UPDATE PRIVILEGES FOR CURRENT JOB
;ROUTINE TO CHECK WRITE PRIV
CHKHSW: PUSHJ P,SAVE1## ;SAVE P1
MOVEI P1,PR.WRT## ;CHECK FOR WRITE PROTECTION
CHKHSA: TLNN J,SHRSEG ;IS THIS HIGH SEG SHARABLE?
JRST CPOPJ1## ;NO, ALWAYS OK TO READ OR WRITE
PUSH P,J ;SOME MAY WANT IT
HRRZS J ;CLEAR LEFT
SKIPN T2,JBTPPN##(J) ;YES, IS HIGH SEG FROM DTA OR MTA
; DIRECTORY NAME IS 0 ON DTA,MTA
JRST CHKHS3 ;YES, GO SEE IF DEVICE IS AVAILABLE
TLNN T2,-1 ;FROM AN SFD?
MOVE T2,(T2) ;YES, GET THE PPN
MOVE T3,JBTPPN##(P2) ;SET REQUESTORS DIRECTORY PPN
MOVE T1,P1 ;SETUP HIGH SEG ACCESS PRIV
LDB T4,JBYSPR## ;HIGH SEG ACCESS PRIV
MOVE J,P2 ;SETUP JOB NUMBER
PUSHJ P,CHKACC## ;GO CHECK ACCESS PRIV (IN DISK SERVICE)
PJRST JPOPJ## ;ERROR - CANNOT ACCESS,RESTORE HIGH SEG NO
PJRST JPOPJ1## ;OK TO ACCESS, RESTORE HIGH SEG NO.
CHKHS3: MOVE T1,JBTDEV##(J) ;DEVICE NAME OF DTA OR MTA
PUSHJ P,DEVPHY## ;YES, SEARCH FOR PHYSICAL DEVICE
JRST JPOPJ
TLNE F,SYSDEV ;SYSTEM TAPE?
JRST CHKHS2 ;NO
LDB P3,PJOBN## ;JOB DEVICE ASSIGNED TO, IF ANY
JUMPE P3,JPOPJ1## ;IS NON-SYSTEM DEVICE ASSIGNED?
; ALWAYS READ OR WRITE IF UNASSIGNED
CAMN P3,P2 ;YES, IT IT ASSIGNED TO THIS JOB?
JRST JPOPJ1
JRST JPOPJ
CHKHS2: CAIGE P1,PR.WRT## ;YES, TRYING TO WRITE(UPDATE)CLEAR UWP OR DEPOSIT)
JRST JPOPJ1
JRST JPOPJ
;UUO TO ALLOW PRIVILEGED USER PROGRAM TO LOOK AT ALL OF CORE
; BY HAVING PHYSICAL CORE APPEAR AS HIGH SEG
; ANY PROGRAMS WRITTEN TO USE THIS UO SHOULD BE PROGRAMMED TO USE THE
; PEEK UUO TOO, IN CASE THIS MACHINE OR MONITOR DOES NOT HAVE 2 RELOC. REG.
; OR INSTALLATION DECIDES TO MAKE THIS UUO RESTRICTED
; THIS UUO IS PROVIDED ONLY FOR EFFICIENT, SINCE IT NEED ONLY BE DONE
; ONCE, WHILE PEEK UUO MUST BE DONE FOR EVERY WORD EXAMINED
;CALL: HRRI AC,HIGHEST PYHSICAL ADR. TOAPPEAR IN HIGH SEG
; CALL AC,[SIXBIT /SPY/] OR CALLI AC,42
; ERROR RETURN, ADR. TOO IGH OR THIS USER CAN'T USE
; THIS UUO, OR NOT 2 RELOC. REG. MACHINE
; OK RETURN, HIGH SEG SETUP IN ADDRESSING SPACE
;NOTE: A SPYSEG APPEARS TO THE SYSTEM AS IF TIS USER DOES NOT HAVE A HIGH SEG
; IN ALL CASES EXCEPT WHEN THE RELOC. HARDWARE IS SET. THIS IS BECAUSE
; THE SIGN BIT OF JBTSGN(JOBNUMBER) IS SET TO INDICATE SPY SEG
; AND THE MONITOR CHECK FOR REAL HIGH SEGS SITH SKIPG INSTR.
; THE RH OF JBTSGN(JOBNUMBER) HAS HIGHEST LEGAL PHY. ADR.
; FOR THIS USER TO LOOK AT(CARE IS TAKEN SINCE THIS IS MUCH BIGGER THAN A
; HIGH SEG NUMBER WHICH IS USUALLY IN RH)
IFN FTPEEKSPY,<
USPY:: MOVSI T1,PVSPYM!PVSPYA
PUSHJ P,PRVBIT## ;IS USER PRIVILEGED TO SPY?
SKIPA ;YES
POPJ P,0 ;NO, ERROR RETURN
SKIPE JBTSGN##(J)
PUSHJ P,VERWAT##
SKIPA
PUSHJ P,PRRBKC
IFN FTMP,<
PUSHJ P,GGVMM## ;GET MM RESOURCE BEFORE REMOVING THE HIGH SEGMENT
>
PUSHJ P,KILHGC ;YES, REMOVE PREVIOUS HIGH SEG FROM LOGICAL
;ADR. SPACE, IF ANY INCLUDING PREVIOUS SPY SEG
PUSHJ P,GETWDU## ;GET USER'S COR ARG ON UUO
JUMPE T1,SETRL1 ;DOES HE WANT TO SPY AT ALL?
; IF 0, SET RELOC HARDWARE AND SKIP RETURN
TLZN T1,-1 ;YES, ANY LH BITS (CLEAR FOR COMPARE)?
CAML T1,MEMSIZ## ;NO, IS HIGHEST ADR. USER WANTS ABOVE MONITOR?
PJRST SETMAP## ;YES, ERROR RETURN TO USER (AFTER SETTING HARDWARE)
PUSH P,T1 ;SAVE USER'S ARGUMENT
CAMGE T1,SYSSIZ## ;TRYING TO SPY BEYOND END OF MONITOR ?
JRST USPY1 ;NO, O.K.
MOVSI T1,PVSPYA ;YES, IS HE PRIVILEGED TO DO SO ?
PUSHJ P,PRVBIT## ;
JRST USPY1 ;YES, O.K.
POP P,T1 ;NO, ERROR RETURN
PJRST SETMAP##
USPY1: POP P,T1 ;RESTORE ARGUMENT
MOVE T3,T1
TRO T3,PG.BDY## ;INSURE AT LEAST ONE PAGE
; (ALSO MAKE SURE RH CAN NOT LOOK LIKE A HIGH SEG NO.)
PUSHJ P,HSVAD ;CALCULATE ORIGIN OF SPY SEG IN USER'S ADR SPACE
MOVE T1,T2 ;T1 = STARTING VIRTUAL ADDRESS
ADD T1,T3 ;T1 = TOP VIRTUAL ADDRESS
TLNE T1,-1 ;TOP VIRTUAL ADDRESS 256K
PJRST SETMAP## ;YES, GIVE ERROR RETURN
PUSHJ P,CKNZ1## ;WILL THE SPY SEG OVERLAP THE LOW SEGMENT?
PJRST SETMAP## ;YES, GIVE ERROR RETURN
HRLI T3,SPYSEG!MEDDLE;FLAG THIS USER AS SPYING
MOVEM T3,JBTSGN##(J) ;STORE HIGHEST PHYSICAL ADR. USER WANTS
JRST SETRL1 ;OK RETURN TO USER AFTER SETTING HARDWARE
> ;END CONDITIONAL ON FTPEEKSPY
IFE FTPEEKSPY,<
USPY==:CPOPJ##
>
;SUBROUTINE TO SEE IF F POINTS AT A KNOWN SEGMENT WHEN NOT
; IN THE CONTEXT OF THE MONITOR JOB (RENAME OR SUPERCEDING CLOSE)
FNDSGU: PUSHJ P,SAVE4## ;SAVE P1-P4
PUSH P,M ;SAVE M FOR UUO ARGS
PUSH P,.JDAT+SGAPPN## ;SAVE POSSIBLE USER AC
MOVE T1,.CPJOB##
PUSH P,JBTSTS##(T1) ;SAVE STATE OF JS.ASA
PUSHJ P,SETASJ## ;SET JS.ASA
MOVEI T1,JOBUAL##+MAXLVL##+2 ;WHERE FNDSEG LOOKS FOR PATH PTR
MOVEM T1,.JDAT+SGAPPN## ;STORE POINTER TO PATH
PUSHJ P,PTHFIL ;GET PATH
POP P,T1
MOVE J,.CPJOB## ;JOB NUMBER
TRNN T1,JS.ASA
PUSHJ P,CLRASA## ;CLEAR JS.ASA
PUSHJ P,FNDSEG ;A KNOWN SEGMENT?
SOS -2(P) ;NO, SET FOR NON-SKIP RETURN
IFN FTMP,<
PUSHJ P,TGVMM## ;FNDSEG MAY RETURN WITH THE MM
>
POP P,.JDAT+SGAPPN## ;AND SGAPPN
MOVE T4,DEVSER(F) ;RESTORE DEVICE DISPATCH
MOVE S,DEVIOS(F) ; AND DEVIOS
POP P,M ;RESTORE M
JRST CPOPJ1## ;AND GIVE FOUND OR NOT ROUND RETURN
;ROUTINE TO SCAN KNOWN SEG TABLE(JBTPPN/JBTNAM) TO SEE IF A SEG IS ALREADY
;IN IT AFTER FILE HAS BEEN LOOKED UP AND WRITTEN OR RENAMED
;CALL: MOVE F,DEVICE DATA BLOCK ADDRESS OF DEVICE WITH FILE
; PUSHJ P,FNDSEG
; NOT FOUND RETURN, OR FILE EXT WAS NOT SHR, OR DEVICE HAS SHORT DISP TABLE
;C(J)=GARBAGE
; FOUND RETURN, C(J)=HIGH SEG NUMBER(LH=SHRSEG)
; C(T1)=DIRECTORY NAME(PROJPROG NO IF DISK, 0 IF MTA OR DTA
; C(T2)=FILE NAME
; C(U)=DEVICE OR FILE STRUCTURE NAME
;CALLED FROM RELSEG(CLOSE OUTPUT AND SUCCESSFUL RENAME)
;AND GET AFTER INPUT
;MUST BE CALLED AT UUO LEVEL
IFN FTMP,<
;TRY TO FIND A KNOWN SEGMENT, ALWAYS RETURN WITH THE MM
FNDSMM: PUSHJ P,FNDSEG
SOS (P)
PUSHJ P,MMOWN##
PUSHJ P,UPMM##
JRST CPOPJ1##
;TRY TO FIND A KNOWN SEGMENT, RETURNS WITH THE MM ONLY IF FOUND
FNDSMS: PUSHJ P,FNDSEG
JRST TGVMM##
JRST CPOPJ1##
>
IFE FTMP,<
FNDSMM:
FNDSMS:
>
FNDSEG: PUSHJ P,NAMSTR## ;GET FILE STRUCTURE NAME
SKIPA U,DEVNAM(F) ;DEVICE NOT A DISK, USE PHYSICAL NAME
MOVE U,T1 ;SETUP F.S. NAME
MOVE T2,DEVMOD(F) ;DEVICE CHARACTERISTICS
HLRZ T1,DEVEXT(F) ;FILE EXTENSION
TLNE T2,DVLNG ;IS DEVICE HAVE FILES(MTA,DTA,DSK)?
CAIE T1,(SIXBIT /SHR/) ;YES, IS EXTENSION SHR?
CAIN T1,(SIXBIT /EXE/) ;ALLOW EXE FILES AS SHARABLE
SKIPA ;SKIP OVER POPJ IF EXE
JRST ZPOPJ## ;NO, DO NOT LOOK FOR NAME IN KNOWN TABLE
TLNE T2,DVDSK ;IS THIS DEVICE A DISK?
SKIPA T1,DEVPPN(F) ;YES, GET PROJECT-PROGRAMMER NUMBER
MOVEI T1,0 ;NO, SET DIR TO 0, MUST BE DTA OR MTA
MOVE T2,DEVFIL(F) ;GET FILE NAME FROM DEVICE DATA BLOCK
; OLD (RATHER THAN NEW) IF RENAME
;FALL INTO SERSEG
;ROUTINE SAME AS FNDSEG, EXCEPT DEVICE NOT LOOKED UP(CALLED FROM GET WHEN DEVICE IS DTA)
;USED TO AVOID DOING OPEN AND LOOKUP WHEN DEVICE IS DTA
;SINCE OPEN MAY QUEUE FOR SYS AND LOOKUP SPINS TAPE
;CALL: MOVE T1,PROJ,PROG NO IF DISK, ZERO IF DTA OR MTA
; MOVE T2,FILE NAME
; MOVE U,DEVICE NAME OR FILE STRUCTURE NAME
; PUSHJ P,SRCSEG
; NOT FOUND RETURN
; FOUND RETURN - J SET UP TO HIGH SEG NUMBER
; LH OF J SET AS SHARABLE(SHRSEG=1)
; (MEDDLE=UWPOFF=SPYSEG=0)
;RETURNS WITH THE MM RESOURCE
SRCSEG:
IFN FTMP,<
PUSH P,.JDAT+SGAPPN## ;SAVE PATH POINTER IN CASE JS.ASA NOT SET
PUSHJ P,UPMM## ;MUST HAVE THE MM TO SEARCH TABLES
POP P,.JDAT+SGAPPN## ;RESTORE SAME
>
MOVE J,SEGPTR## ;POINTER TO JUST HIGH SEGMENTS IN JOB TABLES
FNDLOP: CAMN U,JBTDEV##(J) ;DO DEVICE(STR) NAMES MATCH?
CAME T2,JBTNAM##(J) ;DO FILE NAMES MATCH?
FNDLP1: AOBJN J,FNDLOP ;NO
JUMPGE J,CPOPJ## ;JUMP IF NO MATCH
PUSHJ P,PTCMP ;DO PATHS MATCH?
JRST FNDLP1 ;NO, LOOK AT NEXT SEGMENT
HRLI J,SHRSEG ;INDICATE SHARABLE
JRST CPOPJ1## ;AND GIVE FOUND RETURN
;SUBROUTINE TO CHECK IF A PATH TO A FILE MATCHES A PATH TO A HIGH SEGMENT
PTCMP: SKIPE T4,.JDAT+SGAPPN## ;IS THERE A DIRECTORY OR A PATH?
TLNE T4,-1 ;SKIP IF THE USER SPECIFIED A PATH
JRST [CAMN T1,JBTPPN##(J) ;NOT A PATH, DO DIRECTORIES MATCH?
AOS (P) ;YES, FOUND
POPJ P,] ;GIVE FOUND OR NOT FOUND RETURN
PUSHJ P,SAVT## ;SAVE T1 AND T2
PUSH P,M ;AND M
PUSH P,J ;AND J
SKIPE T3,JBTPPN##(J) ;IS THERE A DIRECTORY OR PATH?
TLNN T3,-1 ;YES, SKIP IF A DIRECTORY
JRST PTCMP0 ;A PATH SO SEE IF THEY MATCH
HRRI M,3(T4) ;FIRST SFD
MOVE T3,T1 ;SAVE PPN
PUSHJ P,GETWDU## ;GET FIRST SFD OR 0
JUMPN T1,PTCMP3 ;IF SFDS WERE SUPPLIED, PATHS DON'T MATCH
MOVE J,(P) ;RESTORE SEGMENT NUMBER
CAMN T3,JBTPPN##(J) ;NO SFDS, PPNS MATCH?
JRST PTCMP2 ;YES, PATHS MATCH
JRST PTCMP3 ;NO, NO MATCH
PTCMP0: HRRI M,1(T4) ;ADDRESS OF PATH-1
PTCMP1: PUSHJ P,GETWD1## ;GET THE NEXT ELEMENT OF THE PATH TO THE SEGMENT?
CAME T1,(T3) ;USER PATH SAME AS PATH TO THIS HIGH SEGMENT?
JRST PTCMP3 ;NO, NO MATCH
SKIPE (T3) ;LAST SFD?
AOJA T3,PTCMP1 ;NO, SEE IF NEXT MATCHES
PTCMP2: AOS -2(P) ;GIVE FOUND RETURN
PTCMP3: POP P,J ;RESTORE J
JRST MPOPJ## ;RESTORE M AND RETURN
;ROUTINE TO GET WORD FROM HIGH SEGMENT IN CORE
;CALL: MOVE J,JOB NO.
; HRR M,RELATIVE(USER) ADDRESS IN HIGH SEGMENT
; PUSHJ P,HGHWRD
; ERROR RETURN, ADR NOT IN HIGH SEG OR NO HIGH SEG
; OK RETURN, CONTENTS OF LOC RETURNED IN T1
; ABS. OR USER VIRTUAL ADR. OF LOC RETURNED IN AC T2(USED BY DEPOSIT)
;CAN BE CALLED AT CLOCK OR UUO LEVELS
;CALLED FROM E COMMAND AND CALL,INIT UUOS,SAVE AND GET JOBS
HGHWRD::SKIPG T2,JBTSGN##(J) ;YES, DOES JOB HAVE A HIGH SEG?
POPJ P, ;NO, ERROR RETURN - LESS THAN 400000 OR NO HIGH SEG
; OR SPYSEG
PUSHJ P,HSVAD
CAIG T2,(M)
CAIGE T1,(M)
POPJ P, ;NO, ERROR RETURN
LDB T2,JBYSG2## ;GET SECTION # OF HIGH SEG
HLRZS T2
HRR T2,M ;SETUP T2 FOR HGHDEP
EXCTUX <MOVE T1,(T2)> ;GET CONTENTS OF THAT WORD
JRST CPOPJ1## ;OK RETURN
;ROUTINE TO FLAG SHARABLE SEGMENT AS NO LONGER SHARABLE AND RETURN
;DISK OR CORE IF POSSIBLE, THEN DISPATCH TO SERVICE ROUTINE TO DO RENAME
;CALL: MOVE F,ADDRESS OF DEVICE DATA BLOCK
; PUSHJ P,RNMSEG
;CALLED FROM RENAME
RNMSEG::PUSHJ P,FNDSGU ;DOES A KNOWN SEGMENT HAVE OLD NAME?
PJRST UDREN## ;NO SO TRY RENAME
PUSH P,J ;YES,SAVE HIGH SEGMENT#
PUSHJ P,UDREN## ;ATTEMPT A RENAME
JRST JPOPJ## ;FAILURE
POP P,J
AOS (P) ;GIVE SUCCESS RETURN
RNMSG1:
IFN FTMP,<
PUSHJ P,GGVMM## ;GET MM RESOURCE FOR CALL TO CLRNAM
>
PUSHJ P,SAVE4## ;SAVE P1-P4
JRST CLRNM1 ;CLEAR NAME AND DELETE DISK AND CORE IF ANY
;AND RETURN
;SUBROUTINE TO LOOKUP A FILE AND RETURN THE PATH TO IT
LUPFIL: LOOKUP 0,SGANAM## ;LOOKUP THE HIGH SEGMENT
POPJ P, ;LOOKUP ERROR
MOVEI T1,JOBUAL## ;WHERE PATH WILL BE STORED
MOVEM T1,.JDAT+SGAPPN## ;INDICATE PATH IS KNOWN
AOS (P) ;LOOKUP SUCEEDED
TDZA T1,T1 ;DO PATH ON CHANNEL 0
PTHFIL::HLRZ T1,.USCTA ;DO PATH ON PROGRAM'S CHANNEL
HRRZ T3,.JDAT+SGAPPN## ;ASSUME ITS NOT A DISK
EXCTXU <SETZM (T3)>
MOVE T2,DEVMOD(F) ;DEVICE CHARACTERISTICS
TLNN T2,DVDSK ;A DISK?
POPJ P, ;NO, ALL DONE
EXCTXU <MOVEM T1,(T3)> ;CHANNEL NUMBER FOR PATH UUO
HRLI T3,MAXLVL##+3
PUSH P,F ;PATH MIGHT CHANGE F
PUSH P,.JDAT+SGANAM## ;SAVE TEMP
MOVEM T3,.JDAT+SGANAM## ;STORE ARGUMENT POINTER
PATH. 0, ;PATH SGANAM,
STOPCD .+1,JOB,PUF, ;++PATH UUO FAILED
POP P,.JDAT+SGANAM## ;RESTORE SGANAM
JRST FPOPJ## ;AND RETURN
SEGEND: END