1
0
mirror of https://github.com/PDP-10/stacken.git synced 2026-02-02 06:40:56 +00:00
Files
PDP-10.stacken/files/stacken-tape-backup/dskb:10_7/mon/core1.mac
Lars Brinkhoff 6e18f5ebef Extract files from tape images.
Some tapes could not be extracted.
2021-01-29 10:47:33 +01:00

1850 lines
68 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
TITLE CORE1 - LOGICAL AND PHYSICAL CORE ALLOCATION ROUTINES - V714
SUBTTL T. HASTINGS/TH/RCC/CHW/JMF/DAL 20-JUL-88
SEARCH F,S
$RELOC
$HIGH
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION
; 1973,1974,1975,1976,1977,1978,1979,1980,1982,1984,1986,1988.
;ALL RIGHTS RESERVED.
.CPYRT<1973,1988>
XP VCORE1,714
;THIS MACRO PUTS VERSION NO. IN STORAGE MAP AND GLOB
ENTRY CORE1 ;ALWAYS LOAD CORE1(FOR LIB SEARCH)
;CORE ALLOCATION IS DONE ON A 1K BLOCK BASIS
;USING A USE BIT TABLE(CORTAB). EACH 1K BLOCK IS REPRESENTED BY A 1 OR 2
;BIT ENTRY IN CORTAB (2 BITS IF THE LOCK UUO IS INCLUDED IN THE SYSTEM)
;A ZERO ENTRY MEANS BLOCK NOT IN USE
;A NON-ZERO ENTRY INDICATES MEMORY IN USE AS FOLLOWS:
;(NUMBERS IN BRACKETS INDICATE CONTENTS OF ENTRIES IN CORTAB IN THE FOLLOWING FORMAT
;[CONTENTS OF CORTAB IN SYSTEM NOT INCLUDING LOCK UUO, CONTENTS OF CORTAB
;IN SYSTEM INCLUDING LOCK UUO]
; 1. IN USE BY MONITOR [1,2]
; 2. IN USE BY A LOCKED JOB [-,2]
; 3. IN USE BY A JOB NOT LOCKED [1,1]
; 4. NON-EXISTANT [1,2]
;WHEN THE SYSTEM IS STARTED, SYSINI SETS THE CORTAB TABLE
;IT ALSO SETS A BYTE POINTER(CORLST) WHICH POINTS TO THE
;LOWEST NON-EXISTANT BLOCK IMMEDIATELY ABOVE THE HIGHEST
;EXISTANT BLOCK. IT ALSO SETS CORTAL TO THE NO. OF
;FREE BLOCKS AVAILABLE.
;THE CORE1 ROUTINE ASSIGNS CORE IF POSSIBLE, SETS THE USE BITS,
;AND MOVES THE JOB IF NEW ASSIGNMENT IS A DIFFERENT PLACE THAN OLD
;THE JBTADR TABLE IS ALSO UPDATED BY THE CORE ROUTINES
;LH=PROTECTION,RH=RELOCATION
;JOBADR IS MODIFIED IF CORE FOR CURRENT JOB
;HARDWARE RELOC. AND PROTEC. ARE RESET IF CURRENT JOB
;FINALLY JOBREL(PROTECTION) IN JOB DATA AREA IS ALWAYS UPDATED
;LIST OF GLOBALS AFFECTED:
;JBTADR,CORTAL,CORTAB,HOLEF,SHFWAT,JOBADR,HOLES
;CORE UUO
;CALL: MOVEI AC,HIGHEST REL. ADR. DESIRED IN LOW SEG
; HRLI AC,HIGHEST REL. ADR. DESIRED IN HIGH SEG
; CALL AC,[SIXBIT /CORE/]
; ERROR RETURN
; OK RETURN TO USER, JOB MOVED IF NECESSARY
;RETURN NO. OF FREE 1K BLOCKS IN AC(OR MAX. NO. BLOCKS ALLOWED IF SWAPPING SYS)
;BOTH HALVES 0 MEANS ERROR RETURN NO. OF FREE 1K BLOCKS(OR MAX. NO. OF BLOCKS
; ALLOWED IF SWAPPING SYSTEM) IMMEDIATELY WITHOUT AFFECTING CORE
; OR WAITING FOR IO DEVICES
;LH=0 MEANS DO NOT CHANGE HIGH SEG ASSIGNMENT
;RH=0 MEANS DO NOT CHANGE LOW SEG ASSIGNMENT
CORUUO::SKIPE T1 ;IF ZERO CORE REQUESTED JUST RETURN
; THE AMOUNT AVAILABLE
PUSHJ P,CHGCOR ;CHANGE THE CORE ASSIGNMENT
SKIPA ;NOT ENOUGH
AOS (P) ;OK RETURN TO USER
PUSHJ P,CORBND ;T1 = UPPER BOUND ON WORDS FOR JOB
LSH T1,W2KLSH ;CONVERT TO K
JRST STOTAC## ;STORE IN USER AC AND RETURN TO USER
;SUBROUTINE TO CHANGE CORE - JUST LIKE CORE UUO
; EXCEPT VALUE NOT STORED IN USER'S UUO ACS
; USED BY MONITOR JOBS INSTEAD OF CORE UUOS
;CALL: MOVE T1,XWD NEW HIGH, NEW LOW SEG HIGHEST ADR
; PUSHJ P,CHGCOR
; ERROR RETURN
; OK RETURN
CHGCOR::PUSHJ P,SAVE4## ;SAVE P1-P4
PUSH P,T1 ;NO, SAVE HIGHEST DESIRED ADDRESS IN BOTH SEGS
MOVSI T2,JACCT
TDNE T2,JBTSTS##(J) ;PRIVILEGED PROGRAM?
TLO P1,PHONLY ;YES, PHYSICAL ONLY THEN
PUSHJ P,IOWAIT## ;WAIT FOR ALL DEVICE INACTIVE
IFN FTMP,<
PUSHJ P,UPMM## ;GET THE MEMORY MANAGEMENT RESOURCE
>
HRRZ T1,(P) ;HIGHEST REL. LOC. DESIRED FOR LOW SEG(RH)
JUMPE T1,CORU1 ;IS RH 0(IF YES DO NOT CHANGE LOW SEG)?
IORI T1,PG.BDY ;NO, MAKE IT AN EVEN MULTIPLE OF 1K-1
IFN FTLOCK,<
MOVSI T2,NSHF!NSWP ;LOCKED JOBS CANNOT CHANGE THEIR SIZE
TDNN T2,JBTSTS##(J) ;IS HE LOCKED?
>
PUSHJ P,CORE1 ;TRY TO ASSIGN CORE
JRST CORERR ;NOT AVAILABLE, ERROR RETURN
; SUM OF NEW LOW AND OLD HIGH SEG TOO BIG
CORU1: HLRZ T1,(P) ;CHECK TO SEE IF USER IS REQUESTING HIGH CORE
PUSHJ P,UCORHI## ;TRY TO ASSIGN CORE FOR HIGH SEG,
; UCORHI EXPECTS ARG ON PD LIST
JRST CORERR ;ERROR-ACTIVE IO(SAVE IN PROGRESS FOR SOME USER)
; OR PROTECTION FAILURE (CAN'T UPDATE)
AOS -1(P) ;SET FOR OK(SKIP) RETURN
CORERR: POP P,T1 ;REMOVE ARG FROM LIST
IFN FTMP,<
PUSHJ P,TGVMM## ;GIVE UP THE MM IF OWNED
>
MOVE T1,JBTSTS##(J) ;JOB STATUS WORD
TLNE T1,JXPN!SWP ;MUST LOW SEGMENT BE SWAPPED OUT TO EXPAND OR
; HIGH SEGMENT LOGICAL CORE ASSIGNED ON DISK?
PUSHJ P,WSCHED## ;YES, CALL SCHEDULER TO STOP JOB
; LOW SEG MUST BE SWAPPED OUT TO EXPAND
POPJ P,
;SUBROUTINE TO RETURN UPPER BOUND CORE LIMIT FOR JOB IN WORDS
;CALL: MOVE J,JOB NO
; PUSHJ P,CORBND
; ALWAYS RETURN - T1 = UPPER BOUND
CORBND::PUSH P,T2
IFN FTLOCK,<
PUSH P,J ;SAVE JOB NUMBER
SETZ T2,
MOVSI T1,NSWP!NSHF
TDNE T1,JBTSTS##(J) ;SEGMENT LOCKED?
PUSHJ P,SEGSIZ## ;YES, GET ITS CORE SIZE
PUSH P,T2 ;SAVE CORE SIZE
MOVSI T2,LOKSEG ;USING LOCKED SEG?
TDNN T2,JBTSGN##(J) ; THAT IS LOCKED?
JRST CRBND1 ;NO
HRRZ T1,JBTSGN##(J) ;POINTER TO BLOCKS
JUMPE T1,CRBND1 ;?
CRBND0: SKIPLE J,.HBSGN(T1) ;SEGMENT WORD
TLNN J,SHRSEG ;ONLY SHARABLE ONES COUNT
JRST CRBN0A
HRRZS J ;CLEAR JUNK
MOVE T2,JBTSTS##(J) ;IS THIS SEG LOCKED?
TLNE T2,NSHF!NSWP ;LOCKED?
PUSHJ P,SEGSIZ## ;YES, GET HIGH SEG SIZE
ADDM T2,(P) ;ADD IT IN
CRBN0A: HRRZ T1,.HBLNK(T1) ;NEXT HIGH SEG
JUMPN T1,CRBND0 ;PROCEED IF MORE
CRBND1: POP P,T1 ;GET BACK LOW SEG SIZE
LSH T1,P2WLSH
ADD T1,CORMAX## ;ADD TO CORMAX TO GET APPARENT CORMAX
POP P,J ;RESTORE JOB NUMBER
>
IFE FTLOCK,<
MOVE T1,CORMAX## ;GET CORMAX
>
LDB T2,JBYLCR## ;GET THIS JOBS CORE LIMIT
JUMPE T2,CRBND2
LSH T2,^D9
CAMLE T1,T2 ;WE WANT
MOVE T1,T2 ; THE SMALLER OF THE TWO
CRBND2: PUSHJ P,FNDPDB## ;FIND THE PDB
JRST CRBND4 ;NO LIMIT OR GUIDELINE IF NO PDB
HRRZ T2,.PDCVL##(W) ;CURRENT PHYSICAL LIMIT OR GUIDELINE
JUMPE T2,CRBND3 ;IGNORE IF NONE
TRZN T2,400000 ;LIMIT?
JUMPL P1,CRBND3 ;NO, IGNORE GUIDELINE IF PHONLY
LSH T2,P2WLSH ;NUMBER OF WORDS
CAMLE T1,T2 ;SMALLEST YET?
MOVE T1,T2 ;NO, USE SMALLER
CRBND3: HRRZ T2,.PDMVL##(W) ;FINALLY, MAX PHYSICAL LIMIT
JUMPE T2,CRBND4
LSH T2,P2WLSH
CAMLE T1,T2
MOVE T1,T2
CRBND4:IFN FTLOCK,<
LSH T1,W2PLSH
CAILE T1,@CORLIM## ;CORLIM MIGHT BE EVEN SMALLER
HRRZ T1,CORLIM## ; IF SO, IT IS THE LIMIT
LSH T1,P2WLSH
>
SUBI T1,UPMSZW## ;ACCOUNT FOR THE FACT THAT THE UPMP IS ALLOCATED
; FROM USER CORE. THUS, MAXIMUM SIZE A JOB
; A JOB CAN OBTAIN IS MIN (CORMAX, JOB LIMIT)-
; THE SIZE OF THE USER PAGE MAP PAGE
JUMPL P1,T2POPJ## ;RETURN IF PHYSICAL ONLY
PUSHJ P,FNDPDB##
PJRST T2POPJ## ;NO LIMITS IF NO PDB
HLRZ T2,.PDCVL##(W) ;CURRENT VIRTUAL LIMIT
LSH T2,P2WLSH ;CONVERT TO PAGES
CAMGE T1,T2
MOVE T1,T2
PJRST T2POPJ## ;YES, USE SMALLER JOB LIMIT
;CORLM. UUO -- SET JOB'S CORE LIMIT
;CALL: HRLZI AC,12
; HRRI AC,LIMIT IN NO. OF WORDS
; SETUUO AC,
; ERROR
; OK
CORELM::JUMPE T2,CORLM1
CAIG T2,MINMAX## ;GREATER THAN MIN
MOVEI T2,MINMAX## ;YES--USE MINMAX
CORLM1: ADDI T2,PG.BDY ;ROUND UP TO LAST LOWSEG ADDRESS
; + HIGH SEG SIZE
;THIS IS TO BE SIMILAR TO CORE UUO
TLNE T2,-1 ;SEE IF OVERFLOW
SETOM T2 ;YES--SET TO INFINITY
LSH T2,-^D9 ;CONVERT TO 512 UNITS
DPB T2,JBYLCR## ;STORE
JRST CPOPJ1## ;RETURN
;ROUTINE TO TEST FOR ANY ACTIVE DEVICES
;CALL: MOVE J,JOB NUMBER OR HIGH SEG NUMBER
; MOVE R,ADDRESS OF JOB DATA AREA
; PUSHJ P,ANYACT
; DEVICES ACTIVE
; DEVICES NOT ACTIVE EXCEPT POSSIBLY TTY
;IN REENTRANT SYSTEMS ANYACT IS BROKEN INTO 2 CALLS, ANYSAV AND ANYDEV
;ANYSAV TESTS WHTETHER THIS IS A HI SEG THAT HAS A SAVE IN PROGRESS
ANYACT::PUSHJ P,ANYSAV## ;IS A SAVE IN PROGRESS FOR HI SEG?
POPJ P, ;YES - RETURN
ANYDEV::PUSHJ P,SAVE2## ;PRESERVE ACCUMULATORS P1, P2, P3
IFN FTMP,<
PUSHJ P,ANYRUN## ;IS THIS JOB RUNNING ON THE SLAVE
POPJ P, ;YES, RETURN IMMEDIATELY
>
CAILE J,JOBMAX## ;YES, IT THIS A HIGH SEG?
JRST CPOPJ1## ;YES, OK TO SHUFFLE OR SWAP SINCE NSHF,NSWP NOT SET
; AND NO SAVE IN PROGRESS
LDB P1,PJBSTS## ;JOB'S QUEUE CODE
CAIE P1,PIOWQ## ;IN PAGING I/O WAIT?
CAIN P1,DIOWQ## ;OR DSK I/O WAIT?
POPJ P, ;YES, CAN'T SWAP IT OUT NOW
; ONLY HAPPENS IF LOCK IS TRYING
; TO FORCE THIS JOB OUT
MOVEI P1,0 ;ASSUME JOB IS CURRENT JOB (DEVICE TABLE IS THE MONITOR)
CAME J,.CPJOB## ;IS IT?
PUSHJ P,SVEUB## ;NO, MAKE THE JOB DATA AREA ADDRESSABLE
PUSH P,T1
ANY: PUSHJ P,NXTCH##
JRST ANY3
IFN FTMPXSER,<
HRRZ F,T1
LDB P2,PDVTYP## ;GET THE DEVICE TYPE
CAIE P2,.TYMPX ;MPX?
JRST ANY1 ;NO--JUST LOOK AT IOACT
PUSHJ P,MPXACT## ;SEE IF IT IS ACTIVE
JRST TPOPJ## ;RETURN IF ACTIVE
JRST ANY ;LOOK AT NEXT DEVICE
> ;END FTMPXSER
ANY1: TRNN S,IOACT ;IS DEVICE ACTIVE?
JRST ANY
MOVSI P2,DVTTY ;DEVICE IS A TTY BIT
TDNN P2,DEVMOD(T1) ;NOT FINISHED, IS DEVICE TTY?
JRST TPOPJ## ;NO, ERROR RETURN, CANNOT ASSIGN CORE
JRST ANY ;YES, KEEP LOOKING FOR AN ACTIVE DEVICE
ANY3:
SKIPN F,DIADSK## ;DSK CHAN STOPPED?
JRST TPOPJ1## ;NO, OK RETURN
LDB P1,PJOBN## ;YES, IS THIS THE JOB THAT STOPPED IT!
CAMN P1,J
JRST TPOPJ## ;YES, SOMETHING IS ACTIVE
PJRST TPOPJ1## ;OK RETURN
;ROUTINE TO FLUSH PHYSICAL CORE ASSIGNED IN MEMORY
;NOTE: THIS ROUTINE DIFFERS SIGNIFICANTLY FROM CORE0 AND CORE1 IN THAT
;IT IS ONLY A PHYSICAL REMOVAL OF CORE(VIRTAL IS NOT AFFECTED)
;SEE COMMENTS FOR CORE1
;CALL: MOVE J,HIGH OR LOW SEGMENT NUMBER
; PUSHJ P,KCORE1
; ALWAYS RETURN HERE
;SCORE1 IS CALLED FROM SHUFFLER WITH T1 SET TO SEG SIZE
KCORE1::MOVEI T1,0 ;SETUP DESIRED HIGHEST ADR
SCORE1::SOS (P) ;CORE1 WILL ALWAYS SKIP RETURN
MOVE R,JBTADR##(J)
PJRST CORE1A ;BYPASS LOGICAL CORE ASSIGNMENT PART
; AND FLUSH PHYSICAL CORE(LOGICAL CORE UNEFFECTED)
;CALL: MOVE T1,HIGHEST LEGAL ASSRESSABLE LOC. DESIRED
; MOVE J,JOB NUMBER
; MOVE R,[XWD PROT.,RELOC.]=JBTADR(J)
; PUSHJ P,CORE0
; ERROR ;EITHER JOB HAS ACTIVE IO
; OR NOT ENOUGH CORE
; OK RETURN
;JOB IS MOVED IF NECESSARY TO SATISFY REQUEST
;R IS SET TO NEW CORE ASSIGNMENT ON EITHER RETURN
;0 MEANS NONE ASSIGNED IN MEMORY, ASSIGNED ON DISK
;ENTER HERE FROM CORE CONSOLE COMMAND OR INITIAL CORE
;ASSIGNMENT OF JUST A JOB DATA AREA FOR RUN COMMAND
;IE ENTER WHEN DEVICES MAY BE ACTIVE OR JOB MAY HAVE NO PREVIOUS CORE
;JOB CAN HAVE CORE IN MEMORY, CORE ON DISK, OR NONE EITHER PLACE
;JOB CANNOT BE IN PROCESS OF SWAP OUT OR SWAP IN(CALLER'S RESPONSIBILITY)
;CORE0 NO LONGER REASSIGN CORE ON DISK IF OLD CORE ON DISK
;BECAUSE OF FRAGMENTED SWAPPING(TOO HARD) UNLESS 0 BEING ASKED FOR
;THEREFORE THE CORE COMMAND CAUSES JOB TO BE SWAPPED INTO CORE FIRST(INCORE=1)
;HOWEVER, THE R,RUN,GET,KJOB COMMANDS DO NOT REQUIRE THE PREVIOUS CORE IMAGE TO
;BE SWAPPED IN(AS THIS IS SLOW). THEY ASK FOR 140 WORDS, AND LARGER DISK SPACE IS RELINQUISHED
;UPON SWAPIN BY THE SWAPPER, VIRTAL IS INCREASED THEN RATHER THAN
;ON THE CALL TO CORE0.
;IT WILL TRY TO REASSIGN CORE IN MEMORY IF OLD CORE IN MEMORY
;IF THIS FAILS, IT WILL REASSIGN NEW CORE ON DISK AND ASK SWAPPER TO EXPAND
;IF JOB DID NOT HAVE OLD CORE, AN ATTEMPT WILL BE MADE TO ASSIGN CORE IN MEMORY
;IF THIS FAILS, TI WILL BE ASSIGNED ON THE DISK AND ASK SWAPPER TO EXPAND
;THE OTHER PLACES IN THE MONITOR WHERE THE IN-CORE COUNT IS TOUCHED IS
;IN GET WHERE IT INCREMENTS TO SHARE COPY ALREADY IN CORE.
;AND END OF SWAPIN OF LOW SEG AND HIGH SEG IS ALREADY IN CORE FOR OTHER USER
;THE CORE ROUTINES DO NOT ALTER THE HIGH SEG IN CORE COUNT. IT IS UP TO THE CALLER
;(IN SEGCON) TO CALL THE CORE ROUTINES ONLY IF IN CORE COUNT IS 0.
;AND END OF SWAPIN OF LOW SEG AND HIGH SEG IS ALREADY IN CORE FOR OTHER USER
CORE0:: MOVE R,JBTADR##(J)
JUMPN R,CORE0A ;DOES JOB HAVE CORE IN MEMORY?
; (ALWAYS TRUE BOTH SEGS IF CORE UUO)
PUSHJ P,SUMSEG## ;NO, WILL SUM OF BOTH SEGMENTS FIT IN PHYSICAL CORE?
; LARGEST PERMITTED CORE. COMPARE SUM WITH CORMAX
POPJ P, ;NO, GIVE ERROR RETURN
MOVSI T2,SWP ;IS JOB SWAPPED OUT?
TDNN T2,JBTSTS##(J) ;(MAY HAVE 0 DISK SPACE ALTHOUGH SWAPPED OUT)
JRST CORE1 ;NO, TRY TO ASSIGN CORE IN MEMORY
PUSHJ P,CHGSWP## ;YES, CHANGE ASSIGNMENT OF SWAPPING SPACE ON DISK
; INCREASE VIRTAL(COUNT OF FREE 1K BLOCKS OF SWAPPING
; (SHOULD NEVER NEED TO DECREASE VIRTAL SINCE
; CORE COMMAND ALWAYS SWAPS JOB IN FIRST).
; (FRAGMENTATION POSTPONES RETURNING SPACE AND
; INCREASING VIRTAL UNTIL SWAP IN IF NOT ASKING
; FOR 0 VIRTUAL CORE)
JRST CPOPJ1## ;GIVE OK RETURN TO CALLER
CORE0A:
SKIPN .CPSTS## ;NO,IS TIME SHARING STOPPED BY
; TRPSET UUO DONE FOR JOB 1?
PUSHJ P,ANYACT ;NO,ANY ACTIVE DEVICE?
POPJ P, ;YES, CANNOT ASSIGN CORE
; NO, FALL INTO CORE1
;ROUTINE TO TRY TO ASSIGN CORE IN CORE
;LOW OR HIGH SEG MUST NOT BE SWAPPED OUT(CALLER'S RESPONSIBILITY)
;AND MUST NOT HAVE ANY ACTIVE DEVICES(IT MAY HAVE 0 CORE IN CORE THOUGH)
;IN OTHER WORDS HIGH OR LOW SEG MAY OR MAY NOT HAVE VIRTUAL CORE
;BUT IF IT HAS VIRTUAL CORE IT MUST BE IN PHYSICAL CORE
;THIS IS BOTH A LOGICAL AND A PHYSICAL CORE ASSIGNMENT
;FIRST OLD CORE IS RETURNED TO SYSTEM
;THEN NEW REQUEST IS ATTEMPTED TO BE SATISFIED IN LOWEST
;POSITION POSSIBLE. THUS CORE TENDS TO BE PACKED
;IF NEW REQUEST CANNOT BE GRANTED, OLD AMOUNT IS RETAINED, IF NON-SWAPPING SYS
;OTHERWISE SWAPPER IS CALLED(XPAND) TO EXPAND CORE BY SWAPPING OUT
CORE1:: MOVE R,JBTADR##(J)
JUMPL T1,CPOPJ## ;DON'T ALLOW NEGATIVE ARGUMENTS
IFN FTLOCK,<
MOVSI T2,NSHF!NSWP ;LOCKED SEGMENTS CANNOT CHANGE THEIR CORE SIZE
TDNE T2,JBTSTS##(J) ;IS THIS SEGMENT LOCKED?
POPJ P, ;YES, ERROR RETURN
;END IFN FTLOCK
>
CAILE J,JOBMAX## ;IS THIS A HIGH SEGMENT?
JRST CORE12 ;YES, PROCEED
MOVE T3,T1 ;LOW SEGMENT, SAVE AMOUNT OF CORE REQUESTED
SETZ T1, ;SEARCH HIGH SEGMENTS IN THIS SECTION
CORE30: PUSHJ P,NXSPCS## ;GET NEXT HIGH SEG IN PCS
JRST CORE31 ;ALL CLEAR
PUSH P,T1 ;SAVE FOR CHAINING
PUSHJ P,HSVAD## ;COMPUTE HIGH SEGMENT BOUNDS
CAIL T3,(T2) ;TRYING TO EXPAND INTO THE HIGH SEGMENT?
JUMPN T1,TPOPJ## ;YES IF THERE IS ONE - FAIL IF SO (FIXING STACK)
POP P,T1 ;RESTORE CHAINING ARG
JRST CORE30
CORE31: MOVE T1,T3 ;OK, RESTORE ARGUMENT
CORE12: NOSCHEDULE ;PREVENT SCHEDULING
PUSHJ P,SEGSIZ## ;T2=OLD SEG SIZE
JUMPE T2,CORE10
CAIG J,JOBMAX## ;IF THIS IS A LOW SEGMENT,
SUBI T2,UPMPSZ## ;SUBTRACT OUT THE SIZE OF THE UPMP WHICH WAS
; ADDED IN FOR ACCOUNTING PURPOSES
CORE10: SKIPN T3,T1 ;IS O BEING REQUESTED?
MOVNI T3,1 ;YES, PRETEND -1(DEPEND ON ASH BUG WHICH KEEPS -1
; ON RT. SHIFT)
ASH T3,W2PLSH ;CONVERT TO NO. OF K-1(01,0,1,2,...)
SUB T3,T2 ;NO. OF K-1 INCREASE=NEW-OLD-1
PUSHJ P,VIRCHK## ;ALLOCATE CORE ON DSK? (USER JUST GOING
; VIRTUAL OR ALREADY VIRTUAL)
POPJ P, ;ALREADY VIRTUAL BUT TRYING TO EXCEED LIMITS
PJRST CPOPJ1## ;YES, TAKE GOOD RETURN
PUSHJ P,SAVE1##
TLO P1,PHONLY ;PHYSICAL ONLY FOR CORBND
CAMGE T3,VIRTAL## ;IS THERE ENOUGH FREE VIRTUAL CORE IN SYSTEM?
PUSHJ P,SUMSEG## ;YES, IS SUM OF SEGS LESS THAN MAX. ALLOWED CORE+1?
POPJ P, ;NO, ERROR RETURN
AOJE T3,CPOPJ1## ;YES, GET NO. K OF INCREASE AND
;RETURN WITHOUT MOVING CORE IF NO CHANGE IN SIZE
CAILE J,JOBMAX## ;IF A LOW SEG...
JRST CORE11
SKIPN R ;IF GOING FROM 0 TO N,
ADDI T3,UPMPSZ##+1 ;U DECREASE VIRTAL
SKIPN T1 ;IF GOING FROM N TO 0,
SUBI T3,UPMPSZ##+1 ;U DECREASE VIRTAL
CORE11: MOVNS T3 ;MAKE MINUS FOR UPDATE
ADDM T3,VIRTAL## ;AND UPDATE TOTAL VIRTUAL CORE IN SYSTEM
; SINCE THIS REQUEST CAN BE SATISFIIED
;HERE TO ALLOCATE PHYSICAL CORE IN CORE OR ON THE DISK
;ALWAYS SKIP RETURN - R = NEW PROTECTION,,RELOCATION
; R = 0 IF CORE IS ASSIGNED ON THE SWAPPING SPACE
CORE1A::JUMPE R,CORGT0 ;JUMP IF SEGMENT HAS NO CORE IN CORE
HLRZ T3,R ;T3 = CURRENT HIGHEST RELATIVE ADDRESS IN THE SEGMENT
SKIPN T1 ;IS ZERO CORE BEING REQUESTED?
MOVNI T1,1 ;YES, PRETEND -1 AND DEPEND ON BUG IN ASH
; WHICH MAKES -1 = -1 WHEN SHIFTED
SUB T3,T1 ;T3 = NUMBER OF WORDS OF INCREASE OR DECREASE IN
; SEGMENT SIZE
ASH T3,W2PLSH ;CONVERT TO NUMBER OF PAGES OF INCREASE OR DECREASE
JUMPG T3,CORE1B ;JUMP IF SEGMENT IS GETTING SMALLER
MOVMS T3 ;T3 = NUMBER OF PAGES OF INCREASE
PUSHJ P,FRDCR## ;ARE THERE THAT MANY FREE PAGES AVAILABLE IN CORE?
JRST CORGT7 ;NO, MARK THE SEGMENT AS EXPANDING AND ALLOCATE
; THE REQUIRED NUMBER OF PAGES ON SWAP-IN
PUSH P,T3 ;SAVE THE NUMBER OF PAGES OF INCREASE
LDB T1,JBYSSA## ;FIRST PAGE OF SEGMENT
MOVE T2,(P) ;T2 = NUMBER OF PAGES TO ADD TO THE SEGMENT
ADDM T2,JBTIMI##(J) ;INCREASE JBTIMI BY THAT NUMBER OF PAGES
CAILE J,JOBMAX## ;IF A HISEG,
PUSHJ P,SCPAGS ;KEEP THEM IN ORDER
MOVE T2,(P) ;SCPAGS CLOBBERS THIS
PUSHJ P,ADPAGS ;ALLOCATE ENOUGH PAGES TO SATISFY THE REQUEST
POP P,T2 ;RESTORE THE NUMBER OF PAGES OF INCREASE
LSH T2,^D18+P2WLSH ;CONVERT TO NUMBER OF WORDS OF INCREASE IN
; POSITION TO UPDATE CURRENT RELOCATION
ADD R,T2 ;R = NEW PROTECTION,,RELOCATION
JRST CORGT2 ;STORE NEW PROTECTION,,RELOCATION AND CLEAR
; PAGES JUST ADDED TO INSURE SECURITY
CORE1B: JUMPG T1,CORE1C ;REQUESTING 0K CORE IN CORE?
IFN FTMP&FTKL10,<
PUSHJ P,CLCSN## ;YES, DON'T HAVE TO SWEEP BEFORE WE
; RUN HIM AGAIN
>;END IFN FTMP&FTKL10
CAMN J,.CPJOB## ;CORE 0 ON THE CURRENT JOB?
JRST [MOVEI T2,NUPMPP## ;NULL JOB'S UPMP PAGE NUMBER
CONO PI,PI.OFF ;MAKE CHANGING THE SPT AND THE UBR ATOMIC
MOVEM T2,@.CPSPT## ;POINT SPT AT THE NULL JOB'S MAP
DATAO PAG,NULDOP## ;AND THE UBR AT THE NULL JOB'S MAP
CONO PI,PI.ON ;BOTH AGREE, ALLOW INTERRUPTS AGAIN
JRST .+1] ;AND CONTINUE
PUSH P,T3 ;SAVE THE NUMBER OF PAGES OF DECREASE
PUSH P,J ;IN CASE LEFT HALF CRUFT,
HRRZS J ;CLEAR CRUFT
LDB T1,JBYSSA## ;FIRST PAGE OF THE SEGMENT
POP P,J
JRST CORE1D ;GO RETURN PAGES
CORE1C: LDB T2,[POINT 9,R,8];T2 = THE CURRENT SIZE OF THE SEGMENT IN
; PAGES - 1
SUBI T2,(T3) ;COMPUTE THE RELATIVE PAGE NUMBER OF THE FIRST
; PAGE TO RETURN TO THE FREE CORE LIST
PUSH P,T3 ;SAVE THE NUMBER OF PAGES OF DECREASE
PUSHJ P,SNPAGS ;FIND THE ABSOLUTE PAGE NUMBER OF THE FIRST PAGE
; TO RETURN TO THE FREE CORE LIST
IFN FTXMON,<
XJRST [MCSEC1+.+1]
>
SSX T1,MS.MEM ;SET SECTION NUMBER
HRRZ T2,PAGTAB(T1) ;T2 = THE LINK TO THE FIRST PAGE TO FREE
HLLZS PAGTAB(T1) ;INDICATE THAT THIS IS NOW THE LAST PAGE
; OF THE SEGMENT
MOVE T1,T2 ;T1 = THE ABSOLUTE PAGE NUMBER OF FIRST PAGE TO FREE
IFN FTXMON,<
JRST @[0,,.+1] ;RETURN TO SECTION 0
>
CORE1D: PUSHJ P,GVPAGS ;RETURN FREED PAGES TO THE FREE CORE LIST
LDB T2,IMGOUT## ;SWAPPER DEALLOCATION?
JUMPN T2,CORE1E ;JUMP IF YES
LDB T2,IMGIN## ;UPDATE IMGIN TO REFLECT # OF PAGES ALLOCD
SUB T2,(P)
DPB T2,IMGIN##
CORE1E: POP P,T2 ;RESTORE THE NUMBER OF PAGES OF DECREASE
LSH T2,^D18+P2WLSH ;CONVERT TO NUMBER OF WORDS OF DECREASE AND
; POSITION TO UPDATE CURRENT RELOCATION
SUB R,T2 ;R = NEW PROTECTION,,RELOCATION
SKIPG R ;WERE ALL OF THE PAGES BELONGING TO THE SEGMENT
; RETURNED TO FREE CORE
SETZB T1,R ;YES, INDICATE SEGMENT HAS NO CORE IN CORE
CAILE J,JOBMAX## ;IS THIS SEGMENT A HIGH SEGMENT?
JUMPE R,CORGT1 ;YES, AND DOES IT STILL HAVE CORE IN CORE?
JUMPN R,CORGT2 ;NO, DOES LOW SEGMENT HAVE CORE IN CORE?
LDB T1,IMGOUT## ;SWAPPER DEALLOCATION?
SKIPN T1
PUSHJ P,JOBFNQ## ;NO, CHECK VIRTUAL PAGES
HRRZ T1,JBTUPM##(J) ;NO, RETURN UPMP TO THE FREE CORE LIST
SETZ R,
HLLZS JBTUPM##(J) ;INDICATE NO UPMP OR CORE IN CORE
PUSHJ P,GVPAGS ;GIVE UP THE PAGE ALLOCATED TO THE UPMP
JRST CORGT6 ;STORE R AND RETURN
;HERE WHEN THE SEGMENT IS EXPANDING FROM ZERO (CALLED BY THE SWAPPER AND ABOVE)
CORGET::PUSHJ P,SVEUB## ;SAVE UBR ON CALL FROM THE SWAPPER
CORGT0: JUMPE T1,CPOPJ1## ;RETURN IF MULTIPLE CALLS TO RETURN CORE
AOS T2,T1 ;T2 = NUMBER OF WORDS OF CORE REQUIRED TO
; SATISFY REQUEST
LSH T2,W2PLSH ;T2 = NUMBER OF PAGES REQUIRED
MOVE T3,T2
CAILE J,JOBMAX##
JRST CORG0A ;NO
LDB T3,IMGOUT##
JUMPE T3,CORG0B
LDB T3,NZSICN## ;# OF NZS MAPS WANTED FOR SWAPIN
SKIPE T3 ;ANY WANTED?
DPB T3,NZSXCN## ;YES, WE "HAVE THEM NOW"
LDB T3,IFYPGS##
JUMPE T3,[LDB T3,NFYPGS##
JRST CORG0C]
MOVEI T4,0
DPB T4,IFYPGS##
CAIA
CORG0B: MOVEI T3,UPMPSZ##+1
DPB T3,NFYPGS##
CORG0C: ADDM T2,T3 ;ADD THAT IN
LDB T4,NZSSCN##
ADD T3,T4 ;# OF NZS MAPS
CORG0A: CAMLE T3,BIGHOL## ;NO, IS THERE ENOUGH FREE CORE IN CORE TO
; ACCOMODATE THE REQUEST?
SOJA T1,CORGT7 ;NO, MARK THE SEGMENT AS EXPANDING AND ALLOCATE
; THE REQUIRED NUMBER OF PAGES ON SWAP-IN
DPB T2,IMGIN## ;STORE THE NUMBER OF PAGES ALLOCATED IN CORE
HRLI R,-1(T1) ;R = NEW PROTECTION,,?
CAILE J,JOBMAX##
SKIPA T2,T3
MOVEI T2,-UPMPSZ##-1(T3)
PUSHJ P,GTPAGS ;ALLOCATE THE PAGES TO SATISFY THE REQUEST
HRLI T1,(<PM.DCD>B2+PM.WRT+PM.PUB+PM.CSH+PM.AAB+PM.COR)
CAILE J,JOBMAX## ;IS THIS A LOW SEGMENT
JRST CORGT1 ;NO, UPMP HAS ALREADY BEEN ALLOCATED
PUSH P,T1 ;SAVE THE PAGE NUMBER OF FIRST PAGE OF THE LOW SEGMENT
MOVEI T2,UPMPSZ##+1 ;ALLOCATE ONE PAGE FOR THE UPMP
PUSHJ P,GTPAGS ;GET ONE PAGE OFF THE FREE CORE LIST
HRRM T1,JBTUPM##(J) ;STORE IT AS THE ADDRESS OF THE UPMP
MOVE T3,.CPMAP##
HRLI T1,(<PM.DCD>B2+PM.WRT+PM.PUB+PM.AAB)
MOVEM T1,.EUPMP/PAGSIZ(T3)
CLRPT .EUPMP ;THE UPMP IS NOW MAPPED THROUGH THE EXEC
; MAP. CLEAR THE AM SO THE NEW MAPPING
; WILL BE IN AFFECT
SETZM .EUPMP
MOVE T2,[.EUPMP,,.EUPMP+1]
BLT T2,.EUPMP+PG.BDY ;ZERO THE ENTIRE UPMP
MOVSI T2,NUPPMT## ;NOW SETUP THE REST OF THE MAP FROM THE
HRRI T2,.EUPMP+.UPTVC ; PROTOTYPE MAP (NULL JOB'S UPMP)
BLT T2,.EUPMP+NUPMPL##-1
MOVE T2,T1
IFN FTXMON,<
XJRST [MCSEC1+.+1] ;REFERENCES TO PAGTAB REQUIRE WE MUST BE IN SECTION 1
SSX T2,MS.MEM
HRR T1,PAGTAB(T2)
JRST @[0,,.+1] ;RETURN TO SECTION 0
>
IFE FTXMON,<
HRR T1,PAGTAB(T2)
>
EXCH T1,.EUPMP/PAGSIZ(T3)
CLRPT .EUPMP
SETZM .EUPMP
MOVE T2,[.EUPMP,,.EUPMP+1]
BLT T2,.EUPMP+PG.BDY
EXCH T1,.EUPMP/PAGSIZ(T3)
CLRPT .EUPMP
TLO T1,(PM.PUB+PM.CSH+PM.COR) ;ALWAYS PUBLIC HERE, USER MAP SPECIFIES
MOVEM T1,.EUPMP+SECTAB ;SECTION 0 MAP POINTER
IFN FTMP,<
SKIPE [M.CPU##-1] ;IF NOT CONFIGURED FOR SMP
>
TLZ T1,(PM.CSH) ;TURN ON CACHE BIT
MOVEM T1,.EUPMP+.UMUPM ;PAGE MAP - UNCACHED IF SMP
HRR T1,JBTUPM##(J) ;PROCESS TABLE
MOVEM T1,.EUPMP+.UMUPT ;PROCESS TABLE MAPPING - UNCACHED IF SMP
TLO T1,(PM.CSH)
MOVEM T1,.EUPMP+.UMUUP ;PROCESS TABLE MAPPING - CACHED REFERENCES
POP P,T1 ;RESTORE THE MAPPING FOR THE FIRST PAGE OF THE
; LOW SEGMENT
PUSHJ P,STEUB## ;MAKE THE UPMP ADDRESSABLE (SET THE UBR TO
; POINT TO THIS PAGE)
MOVEM T1,.UPMAP
IFN FTMP,<
TLZ T1,(PM.CSH) ;TURN OFF CACHE BIT
>
MOVEM T1,.UPMP+.UMJDT
CLRPT .JDAT ;CLEAR OUT OLD ENTRY FOR .JDAT
; DPB T1,JBYLSA## ;STORE FIRST PAGE OF LOW SEG IN JBTAD2
; JRST CORGT2 ;CLEAR THE PAGES JUST ALLOCATED
CORGT1: DPB T1,JBYHSA## ;STORE THE STARTING PAGE NUMBER OF THE HIGH SEG
CORGT2: JUMPE R,CORGT6 ;ALL DONE IF THE SEGMENT HAS NO CORE AT THIS POINT
HLRZ T1,R ;T1 = HIGHEST RELATIVE ADDRESS SEGMENT CURRENTLY HAS
HLRZ T2,JBTADR##(J) ;T2 = HIGHEST RELATIVE ADDRESS SEGMENT PREVIOUSLY HAD
JUMPN T2,CORGT3 ;JUMP IF SEGMENT HAD CORE IN CORE
LDB T2,IMGOUT## ;T2=AMT OF CORE SEG HAD WHEN LAST IN CORE
LSH T2,P2WLSH ;CONVERT TO NUMBER OF WORDS
SOS T2 ;HIGHEST RELATIVE ADDRESS
CORGT3: CAMG T1,T2 ;CURRENT SEGMENT SIZE GREATER THAN PREVIOUS SIZE?
JRST CORGT5 ;NO, NOTHING TO CLEAR
SUB T1,T2 ;T1 = NUMBER OF WORDS OF INCREASE
ADDI T2,1 ;T2 = NUMBER OF WORDS PREVIOUSLY ALLOCATED THE SEGMENT
LSH T2,W2PLSH ;CONVERT TO PAGE NUMBER OF LAST PAGE
; PREVIOUSLY ALLOCATED TO THE SEGMENT
PUSHJ P,ZERHGH## ;IF JOB HAS A NON-SHARABLE HI-SEG
JRST CORGT5 ; ZERO THE CORE DIFFERENTLY
ADDM T1,CLRWRD## ;INCREASE COUNT OF NUMBER OF WORDS CLEARED
PUSHJ P,SNPAGS ;GET THE ABSOLUTE PAGE NUMBER OF THE FIRST
; NEW PAGE (PAGE TO BE CLEARED)
MOVSI T3,SHRSEG ;IS THIS SEGMENT SHARABLE
CAILE J,JOBMAX## ;?
TDNN T3,JBTSTS##(J) ;?
TDZA T3,T3 ;LOW SEG OR NOT SHARABLE, CLEAR T3
SKIPA T3,JBTADR##(J) ;OLD SIZE OF HIGH SEG
SOJA T3,CORG3A ;T3=-1 IS FLAG THAT THERE'S NOTHING TO UPDATE
LSH T3,W2PLSH-^D18 ;LAST RELATIVE PAGE ALLOCATED TO IT
ADD T3,JBTVAD##(J) ;ADDRESS OF HIGH SEG MAP
CORG3A:
IFN FTXMON,<
XJRST [MCSEC1+CORGT4] ;REFERENCES TO PAGTAB REQUIRE WE MUST BE IN SECTION 1
>
CORGT4: HRLI T1,(<PM.DCD>B2!PM.WRT!PM.CSH!PM.AAB!PM.COR!PM.PUB)
IFN FTMP&FTKL10,<
PUSHJ P,MLSCSH## ;IS FRECOR CACHED
TDZ T1,[PM.CSH] ;NO, MUST BE UNCACHED
>
MOVE T2,.CPMAP##
MOVEM T1,.EUPMP/PAGSIZ(T2)
CLRPT .EUPMP
MOVEI T2,.EUPMP+1 ;MAKE A BLT POINTER
HRLI T2,.EUPMP ;SET TO ZERO THE PAGE
SETZM .EUPMP ;ZERO THE FIRST WORD OF THE PAGE
BLT T2,.EUPMP+PG.BDY
;ZERO THE PAGE
AOSN T3 ;IF WAS -1
SOSA T3 ;BE SURE IT STAYS THAT WAY
MOVEM T1,(T3) ;STORE NEW POINTER
ANDI T1,PM.PAG ;CLEAR THE ACCESS BITS
SSX T1,MS.MEM ;SET SECTION NUMBER
HRRZ T1,PAGTAB(T1) ;GET THE ABSOLUTE PAGE NUMBER OF THE
; NEXT PAGE OF THE SEGMENT
JUMPN T1,CORGT4 ;IF NOT THE LAST PAGE ZERO IT
IFN FTXMON,<
JRST @[0,,.+1] ;RETURN TO SECTION 0
>
CORGT5: HRRI R,.VJDT ;ASSUME A HIGH SEGMENT,.I.E., RH(R) = EVA
; OF THE VESTIGUAL JOB DATA AREA
CAILE J,JOBMAX## ;IS IT A HIGH SEGMENT?
JRST CORGT6 ;NO
HRRI R,.JDAT ;LOW SEGMENT, RH(R) = EVA OF JOB DATA AREA
HLRZM R,.JDAT+JOBREL## ;STORE THE NEW SIZE OF THE LOW SEGMENT FOR THE
; USER SO HE WON'T GET CONFUSED ON EXAMINE COMMAND
CORGT6: SKIPE R ;GETTING CORE?
PUSHJ P,IICLNK## ;YES, ADD TO IN-CORE LIST
MOVEM R,JBTADR##(J) ;STORE NEW PROTECTION,,RELOCATION
LDB T1,IMGOUT## ;CORE ALLOCATION FOR THE SWAPPER?
JUMPN T1,CPOPJ1## ;YES, ALL DONE
CAMN J,.CPJOB## ;IS THIS THE CURRENT JOB (CORE UUO)?
PUSHJ P,SETREL## ;YES, SETUP THE MAP AND SOFTWARE RELOCTATION INFO.
AOS (P) ;GIVE SKIP (OK) RETURN
CAILE J,JOBMAX## ;IS THIS A HIGH SEGMENT?
PJRST CURHGH## ;YES SEE IF CORE WAS ALLOCATED FOR THE HIGH
; SEGMENT WHICH THE CURRENT JOB MIGHT BE SHARING
SKIPE R ;DON'T STORE JOB IF CORE 0
; NULL JOB MIGHT BE ADDRESSABLE
MOVEM J,.USJOB ;SAVE THE JOB NUMBER FOR DEBUGGING AND
; VIRCHK (FOR GIVING BACK HIGH SEG CORE)
CAMN J,.CPJOB## ;CURRENT JOB?
TLNN R,-PAGSIZ ; OR ONLY ONE PAGE ALLOCATED TO THE CURRENT JOB?
; IF ONLY 1 PAGE SETREL MIGHT NOT CALL MAPLOW
JUMPN R,MAPLOW ;NO, SETUP THE MAP FOR E AND D COMMANDS
POPJ P, ;YES, MAP IS ALREADY SETUP
;HERE IF NOT ENOUGH FREE PAGES AVAILABLE IN CORE TO SATISFY REQUEST
; INDICATE JOB IS EXPANDING AND THE REQUIRED NUMBER OF PAGES WILL BE
; ALLOCATED WHEN THE SEGMENT IS NEXT SWAPPED IN
CORGT7: AOS (P) ;SET FOR SKIP RETURN
PJRST XPAND## ;AND MARK THE JOB AS EXPANDING
;ROUTINE TO SETUP THE PORTION OF THE MAP WHICH MAPS THE
; LOW SEGMENT
;CALLING SEQUENCE:
; PUSHJ P,MAPLOW
; ... ALWAYS RETURN HERE
MAPLOW::LDB T1,PCORSZ## ;HIGHEST PAGE IN THE LOW SEGMENT
ADDI T1,1 ;LOW SEGMENT SIZE
PUSHJ P,CLRWS## ;CLEAR WORKING SET BITS
LDB T1,[POINT 9,JBTADR##(J),8];NEW HIGHEST PAGE IN THE LOW SEGMENT
ADDI T1,1 ;NEW LOW SEGMENT SIZE
PUSHJ P,ADJWS## ;SET WORKING SET BITS FOR NEW SIZE
MOVEI T1,.UPMAP-1
MOVSI T2,(<PM.DCD>B2+PM.WRT+PM.PUB+PM.CSH+PM.AAB+PM.COR)
IFN FTLOCK,<
MOVSI T3,(JS.NCS) ;DON'T CACHE BIT
TDNE T3,JBTST2##(J) ;SHOULD CACHE BIT BE OFF IN THE MAP?
PUSHJ P,[TDZ T2,[PM.CSH] ;YES, CLEAR IT
JRST CSDMP##];AND FLUSH THE CACHE
>
LDB T3,JBYLSA## ;FIRST PHYSICAL PAGE IN THE LOW SEGMENT
HLRZ T4,JBTADR##(J) ;LOW SEGMENT SIZE
PUSHJ P,REMAP ;SETUP THE MAP FOR THE LOW SEGMENT
PJRST STEUB## ;CLEAR PAGE TABLE AND RETURN
;ROUTINE TO SETUP THE PORTION OF THE MAP WHICH MAPS THE HIGH SEGMENT
;CALLING SEQUENCE:
; PUSHJ P,MAPHGH
; ... ALWAYS RETURN HERE
;IF CALLED AT REMHGH, T1 HAS ADDRESS OF HIGH SEG DATA BLOCK FOR
;SEGMENT BEING REMOVED.
SETMAP::SKIPA J,.CPJOB## ;CURRENT JOB NUMBER
REMHGH::TDZA T3,T3 ;REMOVE HIGH SEG
MAPHGH::SETO T3, ;REDO MAPS
MAPHGX::PUSHJ P,SAVE2## ;SAVE P1
PUSHJ P,SVEUB## ;MAKE SURE THE JOB IS ADDRESSABLE
JUMPE T3,MAPHG0 ;REMHGH MUST HAVE WHICH HS SPECIFIED
SKIPN T1,JBTSGN##(J) ;ADDR OF HIGH SEG DATA BLOCK
POPJ P, ;NONE
MAPHG0: SE1ENT ;ENTER SECTION 1 (FOR MAPS)
HGHLOP: HRRZS P2,T1 ;MORE PERMANENT PLACE, CLEAR JUNK
JUMPE P2,HGHLP8 ;?
JUMPE T3,HGHLP1 ;REMOVING HIGH SEG?
MOVE T3,.HBSGN(T1) ;NO, LOAD DATA BITS # SEGMENT # INTO T3
TLNN T3,REDOMP ;NEED TO REDO THIS SEGMENT?
JRST HGHLP7 ;NO
HGHLP1: PUSHJ P,HSVAD## ;COMPUTE HIGH SEGMENT STARTING AND ENDING ADDRESSES
MOVSI P1,SPYSEG ;SIGN BIT
TDON P1,.HBSGN(P2) ;IS THIS A SPY SEG
HLRZ P1,JBTADR##(P1) ;NO, GET SIZE
HRLZS P1 ;HIGH SEGMENT SIZE,,0
SKIPL USRHCU## ;SAVE IN PROGRESS?
HRRM T1,JOBHRL##+.JDAT ;YES, DON'T CLOBBER IOWD IN COMPRESSED LOW SEGMENT
TLNN T3,SHRSEG+SPYSEG ;HIGH SEGMENT SHARABLE?
JUMPN T3,SCWEXO ;NO, THE MAP IS RIGHT EXCEPT FOR W.E. AND PUBLIC BITS
LDB T1,[PSG2LH+.HBSG2(P2)] ;SECTION # OF HIGH SEG
LSH T1,S2PLSH ;PAGE #
LSH T2,W2PLSH
ADD T1,T2 ;1ST PAGE
ADD T1,[MS.MAP+UMAPS-1] ;SET UP FOR PRE-INCREMENT
JUMPL T3,SETSPY ;JUMP IF A SPY SEGMENT
HRRZ T2,T3 ;GET COPY WITHOUT BITS
JUMPE T3,SETM20 ;IF REMOVING HIGH SEG, STORE 0
SKIPN T2,JBTVAD##(T2) ;DID THIS SEGMENT GO AWAY?
JRST SETM20 ;YES
MOVSI T2,(<PM.ICD>B2+PM.WRT+PM.CSH+PM.NIA)
IFN FTLOCK!FTMP,<
TLNE T3,NCSH+NOCSH ;CACHE?
PUSHJ P,[TLZ T2,(PM.CSH);NO, CLEAR THE BIT
JRST CSDMP##];AND FLUSH THE CACHE
>
PUSH P,T1 ;CHKPUB CLOBBERS T1
PUSHJ P,CHKPUB ;SEE IF THE SEGMENT SHOULD BE CONCEALED
TLO T2,(PM.PUB) ;JACCT OR NOT EXECUTE ONLY, SO MAKE PAGES PUBLIC
POP P,T1 ;RESTORE T1
TLNN T3,UWPOFF ;USER WRITE PROTECT OFF?
TLZ T2,(PM.WRT) ;NO, DON'T ALLOW WRITE
HRRZS T3 ;CLEAR JUNK
LDB T4,[POFFLH##+JBTVAD##(T3)]
TLO T2,(T4) ;STARTING OFFSET OF MAP
HRRI T2,JBTUPM##-SPTTAB##(T3) ;OFFSET INTO SPT
SETM20: HLRZ T4,P1 ;HIGH SEGMENT SIZE
PUSHJ P,REMASH ;MAP THE HIGH SEGMENT INTO THE USER'S ADDRESS SPACE
JRST SETMP3 ;CONTINUE
;HERE FOR SPY SEG
SETSPY: MOVSI T2,(<PM.DCD>B2!PM.PUB!PM.NIA) ;SPY SEGS MUST BE PUBLIC BUT
;NOT WRITABLE OR CACHED
LDB T3,[POINT 9,P1,8];SIZE OF THE SPY SEGMENT
SETMP2: AOS T1 ;INCREMENT
MOVEM T2,(T1) ;AND DEPOSIT, MAP MONITOR ADDRESSES
AOS T2 ;STEP TO NEXT MONITOR PAGE
SOJGE T3,SETMP2 ;MAP AS MANY PAGES AS THE USER REQUESTED
SETMP3: LDB T3,[PHSSLH+.HBHSZ(P2)] ;PREVIOUS HS SIZE
TLNE P1,-1 ;IF THE HIGH SEGMENT SIZE ISN'T 0,
SUBI T3,1 ;HIGHEST PAGE IN THE HIGH SEGMENT
LDB T2,[POINT 9,P1,8] ;CURRENT SIZE -1 OF THE SEGMENT IN PAGES
PUSHJ P,ZERMAP ;ZERO MAP SLOTS NO LONGER A PART OF THE HIGH SEGMENT
MOVSI T1,(UP.CTX) ;DOING CONTEXT STUFF?
CAMN J,.CPJOB## ;ONLY IF AT UUO LEVEL
TDNN T1,.USBTS ;?
CAIA ;NOT DOING A PUSH
JRST SETMP4 ;YES, DON'T CHANGE .HBHSZ
TLNE P1,-1 ;IF THERE STILL IS A HIGH SEGMENT
ADDI T2,1 ;COMPUTE NEW NUMBER OF PAGES IN THE HIGH SEGMENT
DPB T2,[PHSSLH+.HBHSZ(P2)] ;STORE NEW NUMBER OF PAGES IN THE HIGH SEGMENT
SETMP4: MOVSI T1,REDOMP ;CLEAR REDOMP FOR THIS SEGMENT
ANDCAM T1,.HBSGN(P2)
HGHLP7: JUMPE T3,HGHLP8 ;REMOVE ONLY ONE HS
SKIPE T1,.HBLNK(P2) ;NEXT SEGMENT
JRST HGHLOP
HGHLP8: CLRPGT ;CLEAR THE PAGING MEMORY SO NEW MAPPING WILL BE SEEN
POPJ P, ;RETURN
;SUBROUTINE TO MAKE WRITE-ENABLE AND PUBLIC BITS RIGHT FOR A HI SEG
;P2 HAS HIGH SEG BLOCK ADDR FOR THIS JOB
SCWEXO::MOVE R,JBTADR##(J) ;MAKE SURE R IS SETUP TO POINT AT
; THE LOW SEGMENT
SKIPG .HBSGN(P2) ;REAL HIGH SEG?
POPJ P, ;NO, DON'T BOTHER
MOVE T1,P2 ;PUT HIGH SEG BLOCK IN T1 FOR HSVAD
PUSHJ P,HSVAD## ;GET HIGH SEG ADDRESSES
DMOVE T3,T1 ;COPY NUMBERS
LSHC T3,W2PLSH ;ORIGIN PAGE, HIGHEST PAGE
PUSHJ P,CHKPUB ;SEE IF THE HIGH SEGMENT SHOULD BE CONCEALED
TLO T3,400000 ;NO, MAKE THE HIGH SEGMENT PUBLIC
LDB T1,[PSG2LH+.HBSG2(P2)] ;GET SECTION #
LSH T1,S2PLSH ;PART OF PAGE #
IORI T1,(T4) ;AND PUT IN REST
SE1ENT ;FOR PAGE MAP REFERENCES
SCWEX1: PUSHJ P,TSWST## ;IS THIS PAGE IN THE WORKING SET?
JRST SCWEX2 ;NO, SKIP IT
PUSHJ P,GTPME## ;GET CONTESTS OF MAP
TLO T2,(PM.NIA) ;NO I/O ALLOWED
TLZ T2,(PM.WRT!PM.PUB) ;ASSUME WRITE-LOCKED AND EXECUTE ONLY
SKIPGE T3 ;PUBLIC?
TLO T2,(PM.PUB) ;YES, TURN ON THE PUBLIC BIT
MOVEM T2,(T4) ;STORE BACK IN THE MAP WITH NEW ATTRIBUTES
SCWEX2: MOVEI T2,HLGPNO ;IGNORE SECTION # HERE
ANDI T2,(T1)
CAIE T2,(T3) ;LAST PAGE?
AOJA T1,SCWEX1 ;NO, LOOP OVER ALL HIGH SEGMENT PAGES
CLRPGT ;CLEAR THE PAGING MEMORY SO NEW MAPPING WILL BE SEEN
POPJ P, ;RETURN
;SUBROUTINE TO SEE IF A HIGH SEGMENT SHOULD BE CONCEALED, CALL WITH J =
; JOB NUMBER, AND P2=HIGH SEGEMENT BLOCK ADDR FOR HIGH SEG IN QUESTION
;RETURNS CPOPJ1 IF SO
CHKPUB: MOVE T1,.HBSGN(P2) ;SEGMENT WORD
TLNN T1,GTSSEG ;SEGMENT GETSEGED?
POPJ P, ;NO, ALWAYS PUBLIC
IFN FTFDAE,<
MOVSI T1,(JS.FXO) ;XO BY THE FILE DAEMON BIT
TDNE T1,JBTST2##(J) ;IS IT EXECUTE ONLY ?
JRST CPOPJ1## ;YES, MAKE IT CONCEALED
>
MOVE T1,JBTSTS##(J) ;CURRENT JOB STATUS
TLNN T1,JACCT ;A PRIVLEDGED PROGRAM (TOO STUPID TO BE XO)?
TRNN T1,JS.XO ;AN EXECUTE ONLY PROGRAM?
POPJ P, ;NO, MAKE THE HIGH SEGMENT PUBLIC
JRST CPOPJ1## ;YES, MAKE IT CONCEALED
;SUBROUTINE TO SETUP THE USER PAGE MAP PAGE TO REFLECT THE LOCATION
; OF THE PAGES OF A SEGMENT IN PHYSICAL MEMORY
;CALLING SEQUENCE:
; MOVE T1,BYTE POINTER TO THE MAP
; MOVE T2,PAGE ATTRIBUTES
; MOVE T3,ABSOLUTE PAGE NUMBER OF FIRST PAGE OF THE SEGMENT
; MOVE T4,HIGHEST ADDRESS IN THE SEGMENT
; PUSHJ P,REMAP
; ... ALWAYS RETURN HERE
REMAP: JUMPE T4,CPOPJ## ;IF THE SEGMENT IS ZERO LENGTH RETURN
SE1ENT ;MUST BE IN SECTION 1
LSH T4,W2PLSH ;CONVERT TO NUMBER OF PAGES - 1
REMAP1: TDO T3,T2 ;ABSOLUTE PAGE NUMBER PLUS ACCESS BITS
AOS T1
MOVEM T3,(T1) ;STORE PHYSICAL LOCATION OF THE PAGE AND
; THE ACCESS BITS IN THE MAP
TDZ T3,T2 ;CLEAR ACCESS BITS
SSX T3,MS.MEM ;SET SECTION NUMBER
HRRZ T3,PAGTAB(T3) ;GET THE ABSOLUTE PAGE NUMBER OF THE NEXT
; PAGE IN THE SEGMENT
SOJL T4,CPOPJ## ;RETURN IF ALL THE PAGES IN THE SEGMENT
; HAVE BEEN MAPPED
JUMPG T3,REMAP1 ;MAP ALL THE PAGES IN THE SEGMENT
STOPCD .,STOP,PMU, ;++PAGTAB MESSED UP
;EQUIVALENT ROUTINE FOR A SHARABLE HIGH SEG
REMASH: JUMPE T4,CPOPJ## ;IF THE SEGMENT IS ZERO LENGTH RETURN
LSH T4,W2PLSH ;CONVERT TO NUMBER OF PAGES - 1
SKIPE T3,T2 ;IF STORING ZERO, STORE ALL ZEROES
MOVSI T3,1 ;INCREMENT THROUGH SPT
REMSH1: AOS T1
MOVEM T2,(T1) ;STORE PHYSICAL LOCATION OF THE PAGE AND
; THE ACCESS BITS IN THE MAP
ADD T2,T3 ;INCREMENT
; PAGE IN THE SEGMENT
SOJGE T4,REMSH1 ;CONTINUE
POPJ P,
;ROUTINE TO DETERMINE IF THE SIZE OF A SEGMENT HAS CHANGED SINCE THE LAST
; TIME THE JOB WHOSE ADDRESSING SPACE CONTAINS THIS SEGMENT WAS RUN. IF THE
; SEGMENT IS SMALLER THAN THE IT PREVIOUSLY WAS, THE ROUTINE
; ZEROES THE LOCATIONS IN THE MAP WHICH CORRESPOND TO THE PAGES REMOVED FROM
; THE SEGMENT (OR ALL THE LOCATIONS IF THE SEGMENT WAS REMOVED) SO THE JOB
; WILL PAGE FAIL ON AN ILLEGAL MEMORY REFERENCE
;CALLING SEQUENCE:
; MOVE T3,PREVIOUS SEGMENT SIZE IN PAGES - 1
; PUSHJ P,ZERMAP
; ... ALWAYS RETURN HERE - T2 = CURRENT SEGMENT SIZE IN PAGES - 1
ZERMAP: SE1ENT ;NEED TO BE IN SECTION 1 FOR MAPS
SUBI T3,(T2) ;NEW SIZE MINUS OLD SIZE
JUMPLE T3,CPOPJ## ;RETURN IF THE SEGMENT IS THE SAME
; SIZE OR BIGGER THAN IT WAS THE LAST TIME
; THE JOB WAS RUN
ZRMAP1: AOS T1 ;INCREMENT
SETZM (T1) ;ZERO
SOJG T3,ZRMAP1 ; ILLEGAL MEMORY REFERENCE
POPJ P, ;RETURN
;SUBROUTINE TO RETURN PAGES TO THE LINKED LIST OF FREE PAGES AND UPDATE
; BIGHOL (THE TOTAL NUMBER OF FREE PAGES) AND CORTAL (THE TOTAL NUMBER
; OF FREE PAGES PLUS THE NUMBER OF PAGES OCCUPIED BY
; DORMANT OR IDLE SEGMENTS)
;CALLING SEQUENCE:
; MOVE T1,FIRST PAGE TO RETURN TO THE FREE CORE LIST
; PUSHJ P,GVPAGS
; ALWAYS RETURN HERE
GVPAGS::
IFN FTMP,<
PUSHJ P,MMOWN## ;OWN THE MM RESOURCE?
PUSHJ P,MMDIE ;NO, MUST DIE
>
SE1ENT ;MUST BE IN SECTION 1 TO REFERENCE PAGTAB
HRRZS T2,T1 ;T2 = FIRST PAGE TO RETURN (CLEAR ANY JUNK IN LH)
EXCH T1,PAGPTR## ;STORE FIRST PAGE TO FREE AS FIRST PAGE ON THE
; FREE CORE LIST AND GET FIRST PAGE ON CURRENT LIST
PUSH P,T1 ;SAVE
SSX T2,MS.MEM
HRRZ T1,PT2TAB(T2) ;GET BACK LINK (IF ANY)
SKIPE T1 ;IGNORE IF NONE
HLLZS @[IW MS.MEM,PAGTAB(T1)] ;CLEAR BACK LINK
HLLZS PT2TAB(T2) ;NO BACK LINK
MOVSI T1,(P2.LIP) ;LOKCON CHECK
MOVEI T3,1 ;AT LEAST ONE PAGE IS BEING RETURNED
GVPAG1: MOVSI T4,FREPAG ;THIS PAGE IS ON THE FREE CORE LIST BIT
SSX T2,MS.MEM ;SET SECTION NUMBER
TDNE T4,PAGTAB(T2) ;PAGE MUST NOT BE FREE ALREADY
STOPCD .,STOP,ARF, ;++ATTEMPT TO RETURN FREE PAGE
IORB T4,PAGTAB(T2) ;MARK THIS PAGE AS BEING ON THE FREE CORE LIST
; AND GET THE NEXT PAGE TO BE RETURNED
TDNN T1,PT2TAB(T2) ;LOKCON WAITING FOR THIS PAGE?
JRST GVPAG5 ;NO, PROCEED
HRRZ T1,PT2TAB(T2) ;YES, PREVIOUS PAGE TO THIS ONE
SSX T4,MS.MEM ;SET SECTION IN SUCCESSOR
SSX T1,MS.MEM ;AND PREDECESSOR
TRNE T4,-1 ;IS THE A SUCCESSOR?
HRRM T1,PT2TAB(T4) ;YES, SET OUR PREDECESSOR AS HIS
PUSH P,T1 ;FOR IF WE EXIT
TRNN T1,-1 ;IS THIS FIRST PAGE ON FREE LIST?
MOVEI T1,PAGPTR-PAGTAB ;YES, SET TO STORE IN PAGPTR
HRRM T4,PAGTAB(T1) ;STORE SUCCESSOR
SOS T3 ;UNDO THE FOLLOWING AOJA
AOS LOKHOL## ;ONE MORE PAGE IN LOKCON'S QUEUE
AOS LOKTAL## ;AND LOKCON'S VERSION OF CORTAL
HRRZ T1,LOKPTR## ;FIRST PAGE IN LOKCON'S QUEUE
SSX T1,MS.MEM ;IN CASE POINTED @PAGPTR
HRRM T1,PAGTAB(T2) ;IS NOW OUR SUCCESSOR
HRRZM T2,LOKPTR## ;WE ARE NOW FIRST
HLLZS PT2TAB(T2) ;WE HAVE NO PREDECESSOR
TRNE T1,-1 ;DO WE HAVE A SUCCESSOR?
HRRM T2,PT2TAB(T1) ;YES, SET US AS PREDECESSOR
MOVSI T1,(P2.LIP) ;RESTORE T1
POP P,T2 ;REAL LAST PAGE ON FREE LIST
GVPAG5: TRNN T4,-1 ;LAST PAGE TO BE RETURNED?
JRST GVPAG2 ;YES, UPDATE BIGHOL AND CORTAL AND RETURN
HRRZ T2,T4 ;INDEX TO NEXT PAGE TO FREE
AOJA T3,GVPAG1 ;COUNT NUMBER OF PAGES FREED AND RETURN NEXT PAGE
GVPAG2: POP P,T1 ;RESTORE T1 (OLD PAGPTR)
TRNN T2,-1
MOVEI T2,PAGPTR-PAGTAB ;THEN POINT AT PAGPTR
HRRM T1,PAGTAB(T2) ;LINK THE REST OF THE FREE CORE LIST TO THE PAGES
SSX T1,MS.MEM
; FREED
ADDM T3,BIGHOL## ;UPDATE THE AMOUNT OF FREE CORE BY THE NUMBER
; OF PAGES FREED
ADDM T3,CORTAL## ;ALSO, UPDATE THE AMOUNT OF POTENTIALLY FREE CORE
IFN FTMP&FTKL10,<
SETOM SAVCTL## ;MAKE SURE A SWEEP HAPPENS
>
CAIE T2,PAGPTR-PAGTAB ;ALREADY SET IF NO PAGES ADDED
TRNN T1,-1 ;OR IF THERE WERE NO PAGES
POPJ P, ;THEN RETURN NOW
HRRM T2,PT2TAB(T1)
POPJ P, ;AND RETURN
;SUBROUTINE TO FIND THE NTH PAGE FOR N.LT.THE NUMBER OF PAGES
; ASSIGNED TO THE JOB OR THE JOBS LAST PAGE
;CALLING SEQUENCE:
; PUSHJ P,SCPAGS ;TO FIND THE LAST PAGE OF THE JOB
;OR
; PUSHJ P,SNPAGS ;TO FIND THE NTH PAGE OF A JOB
; RETURN HERE - T1 = PAGE NUMBER OF THE NTH PAGE
SCPAGS::MOVEI T2,-1 ;STOP AFTER SCANNING ALL PAGES
SNPAGS::
IFN FTMP,<
PUSHJ P,MMOWN## ;OWN THE MM RESOURCE?
PUSHJ P,MMDIE ;NO, MUST DIE
>
SE1ENT ;MUST BE IN SECTION 1 TO REFERENCE PAGTAB
PUSH P,J ;SAVE J
IFN FTXMON,<
HRRZS J ;COULD BE IN SECTION 1 AND LH OF J CONTAINS CRUFT
>
LDB T3,JBYHSA## ;PHYSICAL PAGE NUMBER OF PAGE 0 IN THE LOW SEGMENT
CAIG J,JOBMAX## ;IS THIS A HIGH SEGMENT?
LDB T3,JBYLSA## ;YES, PHYSICAL PAGE NUMBER OF FIRST PAGE OF
; THE HIGH SEGMENT
POP P,J ;RESTORE SEGMENT NUMBER
SNPAG1::HRRZ T1,T3 ;CURRENT PAGE WITHIN THE SEGMENT
SSX T1,MS.MEM ;SET SECTION NUMBER
SKIPGE T3,PAGTAB(T1) ;GET NEXT PAGE IN THE SEGMENT
STOPCD .,STOP,PSF, ;++PAGE IN SEGMENT FREE
TRNE T3,-1 ;IS THIS THE LAST PAGE IN THE SEGMENT?
SOJGE T2,SNPAG1 ;NO, IS THIS THE NTH PAGE WITHIN THE SEGMENT?
HRRZS T1 ;RETURN ONLY THE PHYSICAL PAGE NUMBER
POPJ P, ;YES, RETURN WITH T1 = NTH OR LAST PAGE
;SUBROUTINE TO GET PAGES FROM THE LINKED LIST OF FREE PAGES AND
; UPDATE CORTAL AND BIGHOL
;CALLING SEQUENCE:
; MOVE T1,WHERE TO BEGIN ALLOCATION IF ADDING PAGES
; MOVE T2,NUMBER OF PAGES TO ALLOCATE
; PUSHJ P,ADPAGS ;OR
; PUSHJ P,GTPAGS ;IF NO PAGES ARE CURRENTLY ALLOCATED
; ALWAYS RETURN HERE - T1 = PAGE NUMBER OF FIRST PAGE ALLOCATED
ADPAGS::MOVE T4,PAGPTR## ;FIRST FREE PAGE
SE1ENT ;GET TO SECTION 1
SSX T1,MS.MEM ;SET SECTION INDEX
PUSH P,PAGTAB(T1) ;SAVE PREVIOUS LINK
HRRM T4,PAGTAB(T1) ;LINK IT TO THE PAGES CONTAINED IN THIS SEGMENT
MOVE T4,T1 ;PRE-LOAD PAGE
JRST GTPAG0
GTPAGS::
SETZ T4,
SE1ENT ;GET TO SECTION 1
PUSH P,T4 ;VALUE TO PUT ON END OF PAGTAB CHAIN
GTPAG0:
IFN FTMP,<
PUSHJ P,MMOWN## ;OWN THE MM RESOURCE?
PUSHJ P,MMDIE ;NO, MUST DIE
>
SKIPN T1,PAGPTR## ;GET FIRST FREE PAGE
STOPCD .,STOP,PEZ, ;++PAGPTR=0
MOVNS T2 ;MINUS NUMBER OF PAGES BEING ALLOCATED
ADDM T2,BIGHOL## ;DECREASE THE NUMBER OF FREE PAGES BY THAT AMOUNT
ADDM T2,CORTAL## ;AND THE NUMBER OF POTENTIALLY FREE PAGES
MOVE T3,T1 ;FIRST PAGE TO ALLOCATE
GTPAG1: SSX T3,MS.MEM
HRRM T4,PT2TAB(T3) ;SET PREVIOUS POINTER (CLEARING REST)
HRRZ T4,T3 ;ALLOCATE THIS PAGE
MOVSI T3,FREPAG ;PREPARE TO MARK THIS PAGE AS IN-USE
SKIPN T4 ;END OF THE FREE CORE LIST?
STOPCD .,STOP,FPI, ;++FREE PAGE INUSE
SSX T4,MS.MEM ;SET SECTION INDEX
ANDCAB T3,PAGTAB(T4) ;CLEAR THE BIT INDICATING A FREE PAGE AND GET
; THE NEXT PAGE ON THE FREE CORE LIST
AOJL T2,GTPAG1 ;LOOP UNTIL ALL PAGES REQUESTED ARE ALLOCATED
HRRZM T3,PAGPTR## ;STORE THE NEW FIRST PAGE IN THE FREE CORE LIST
SSX T3,MS.MEM
HLLZS PT2TAB(T3) ;IT HAS NO BACK LINK NOW
POP P,T3 ;THE BEGINNING OF THE REST OF THE CHAIN
HRRZM T3,PAGTAB(T4) ;POINT NEW PART TO OLD PART
JUMPE T3,CPOPJ## ;RETURN IF NO BACK LINK TO UPDATE
SSX T3,MS.MEM ;POINT TO PAGTAB SECTION
HRRM T4,PT2TAB(T3) ;UPDATE BACK LINK
POPJ P, ;AND RETURN TO THE CALLER
;HERE IF TRYING TO DO CORE ALLOCATION WITHOUT THE MM RESOURCE
IFN FTMP,<
MMDIE:: STOPCD .,STOP,DOM, ;DON'T OWN MM RESOURCE
>
;*** THIS PROBABLY CAN BE MADE TO DO SOME REASONABLE RECOVERY
SUBTTL SWAP - USER PROGRAM SWAPPING ROUTINES
;SUBROUTINE TO SETUP THE MAP FOR A JOB WHICH WAS JUST SWAPPED IN
; THIS INCLUDES THE TRAP LOCATIONS AS WELL AS THE MAP ITSELF
;CALLING SEQUENCE:
; MOVE J,JOB NUMBER OF JOB JUST SWAPPED IN
; MOVE R,XWD LOW SEGMENT SIZE, EVA OF THE JOB DATA AREA
; SETUP THE USER BASE REGISTER TO POINT TO THIS JOB'S UPMP
; PUSHJ P,MAPUSR
; ALWAYS RETURN HERE
MAPUSR::MOVE R,JBTADR##(J) ;R=WXD LOW SEGMENT SIZE, ADDRESS OF JOB DATA AREA
PJRST MAPHGH ;MAP THE HIGH SEGMENT
SUBTTL SWPSER - SWAPPING SERVICE ROUTINE
;SUBROUTINE TO MAKE THE FIRST WORD OF A SEGMENT ADDRESSABLE FOR JBTCHK
; CALLING SEQUENCE:
; MOVE T1,IOWD USED FOR SWAPPING
; MOVE J,SEGMENT NUMBER OF SEGMENT SWAPPED IN OR OUT
; PUSHJ P,GETCHK
; ALWAYS RETURN HERE
;T1 = EXEC VIRTUAL ADDRESS OF WORD 0 OF THE SEGMENT. IF THIS IS A LOW
; SEGMENT, JUST SETUP THE UBR SINCE T1 CONTAINS THE ADDRESS OF WORD 0
; OF THE SEGMENT MAPPED THROUGH THE PER PROCESS MAP. IF THIS IS A HIGH
; SEGMENT, MAP WORD 0 THROUGH THE EXEC MAP SINCE THE SEGMENT MAY BE
; DORMANT OR IDLE AND THUS NOT APPEAR IN ANY USERS MAP.
GETCHK::LDB T1,JBYLSA ;ABSOLUTE PAGE #
;SUBROUTINE TO MAKE A PHYSICAL PAGE ADDRESSABLE FOR SWAPPER
;CALLING SEQUENCE:
; MOVEI T1,PAGE NUMBER
; PUSHJ P,SWPAD
; ALWAYS RETURNS HERE
;T1=EVA OF FIRST WORD IN PAGE
;PRESERVES T2-T4
SWPAD:: PUSHJ P,SAVE1##
MOVE P1,.CPMAP##
HRLI T1,(<PM.DCD>B2+PM.WRT+PM.PUB)
MOVEM T1,.ECKSM/PAGSIZ(P1)
CLRPT .ECKSM ;FLUSH THE ASSOCIATIVE MEMORY SO THE NEW
; MAPPING WILL BE IN EFFECT
MOVEI T1,.ECKSM ;T1 = EXEC VIRTUAL ADDRESS OF WORD 0 OF THE
; HIGH SEGMENT
POPJ P, ;RETURN
;ROUTINE TO CLEAR PART OF JOB DATA AREA(PART PROTECTED FROM USER IO)
;CALLED WHEN SWAP READ ERROR AND AT SYSTEM RESTART(140)
; MOVE J,JOB NO.
;CALL: MOVE R,ADDRESS OF JOB DATA AREA
; PUSHJ P,CLRJOB
CLRJOB::PUSHJ P,SVEUB## ;MAKE SURE JOB DATA AREA IS ADDRESSABLE
SETZM USRPRT## ;FIRST LOC. PROTECTED FROM USER
MOVSI T1,USRPRT##
HRRI T1,USRPR1##
MOVE T2,.JDAT+JOBDDT## ;SAVE DDT STARTING ADDRESS
BLT T1,USRJDA##+17
MOVEM T2,.JDAT+JOBDDT##
SETZM .JDAT+JOBENB## ;ALSO CLEAR APR ENABLE WORD
SETZM .JDAT+JOBPD1## ;AND UUO PC FLAGS(USED WHEN JOB STARTS)
PJRST ESTOP1## ;GO SET JOB STATUS NOT BE ALLOWED
;NOTE JACCT IS CLEARED
SUBTTL CORE ALLOCATION -- EXTENSIBLE BITMAP MEMORY ROUTINES
;ROUTINES CALLED TO ALLOCATE EXTENSIBLE BITMAP MEMORY
;LINKAGE:
; T2/ NUMBER OF WORDS
; T3/ ADDRESS OF ALLOCATION CONTROL BLOCK
; PUSHJ P,GTXWDS
;RETURNS:
; CPOPJ ON ALLOCATION ERROR
; CPOPJ1 ON SUCCESS WITH:
; T1/ ADDRESS OF MEMORY ALLOCATED
GTXWDS::TDZA T1,T1 ;CLEAR ZERO FLAG AND SKIP
GTXWDZ::SETO T1, ;SET ZERO FLAG
PUSHJ P,SAVE4## ;SAVE P1-P4
PUSH P,T1 ;SAVE ZERO FLAG
MOVE P4,T3 ;SAVE ADDRESS OF ALLOCATION CONTROL BLOCK
SKIPN P3,ACBAHB(P4) ;GET ADDRESS OF ALLOCATION HEADER BLOCK
STOPCD CPOPJ##,DEBUG,CORNAH ;++NO ALLOCATION HEADER BLOCK
IDIV T2,AHBCSZ(P3) ;COMPUTE NUMBER OF CHUNKS TO ALLOCATE
SKIPE T3 ;ANY REMAINDER?
ADDI T2,1 ;YES, ROUND UP
IMUL T2,AHBCSZ(P3) ;CONVERT BACK INTO WORDS
MOVE P1,T2 ;SAVE IN P1
GTXWD0: MOVE T1,P1 ;GET WORD COUNT
ADDB T1,ACBUSD(P4) ;UPDATE ALLOCATOR'S COUNT OF USED MEMORY
CAMLE T1,ACBMAX(P4) ;WITHIN MAXIMUM ALLOWABLE AMOUNT?
JRST GTXWX1 ;NO, GO FIX COUNT AND RETURN
CAMLE T1,ACBHWM(P4) ;GREATER THAN PREVIOUS HIGH WATER MARK?
MOVEM T1,ACBHWM(P4) ;YES, STORE NEW HIGH WATER MARK
MOVN T1,P1 ;GET NEGATIVE WORD COUNT
ADDB T1,AHBFRE(P3) ;UPDATE HEADER BLOCK'S COUNT OF FREE WORDS
JUMPL T1,GTXWX2 ;IF NOT ENOUGH, GO TRY AND EXTEND POOL
CAMGE T1,AHBLWM(P3) ;LESS THAN PREVIOUS LOW WATER MARK?
MOVEM T1,AHBLWM(P3) ;YES, STORE NEW LOW WATER MARK
SKIPA P2,AHBAEB(P3) ;GET ADDRESS OF FIRST ALLOCATION EXTENT BLOCK
GTXWD1: MOVE P2,AEBNXT(P2) ;GET ADDRESS OF NEXT ALLOCATION EXTENT BLOCK
JUMPE P2,GTXWX2 ;AT END OF LIST, GO ATTEMPT TO EXTEND POOL
MOVE T1,P1 ;GET NUMBER OF WORDS TO ALLOCATE
IDIV T1,AHBCSZ(P3) ;CONVERT INTO CHUNKS
MOVEI T2,AEBBMP(P2) ;GET ADDRESS OF BIT MAP AOBJN POINTER
CAMG P1,AEBFRE(P2) ;DOES THIS EXTENT HAVE ENOUGH FREE WORDS?
PUSHJ P,GETBIT ;YES, TRY TO ALLOCATE CORE
JRST GTXWD1 ;FAILED, LOOP BACK FOR NEXT ALLOCATION EXTENT
IMUL T1,AHBCSZ(P3) ;COMPUTE WORD OFFSET OF ALLOCATION
ADD T1,AEBADR(P2) ;COMPUTE ADDRESS OF ALLOCATION
EXCH T1,(P) ;SAVE ADDRESS, GET BACK ZERO FLAG
;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE
MOVN T2,P1 ;GET NEGATIVE WORD COUNT
ADDB T2,AEBFRE(P2) ;UPDATE EXTENT BLOCK'S COUNT OF FREE WORDS
CAMGE T2,AEBLWM(P2) ;LESS THAN PREVIOUS LOW WATER MARK?
MOVEM T2,AEBLWM(P2) ;YES, STORE NEW LOW WATER MARK
JUMPE T1,GTXWD2 ;JUMP IF NOT ZEROING ALLOCATED CORE
IFE FTXMON,<
MOVS T1,(P) ;GET STARTING ADDRESS OF ALLOCATION
HLRI T1,1(T1) ;GET ADDRESS OF SECOND WORD OF ALLOCATION
MOVE T2,P1 ;GET NUMBER OF WORDS ALLOCATED
ADD T2,(P) ;COMPUTE LAST ADDRESS+1 TO ZERO WITH BLT
SETZM -1(T1) ;ZERO FIRST WORD OF ALLOCATION
CAIE T2,(T1) ;IS ALLOCATION ONE WORD LONG?
BLT T1,-1(T2) ;NO, ZERO REMAINDER OF ALLOCATION
>; END IFE FTXMON
IFN FTXMON,<
MOVE T1,P1 ;GET NUMBER OF WORDS ALLOCATED
SUBI T1,1 ;COMPUTE WORDS TO ZERO WITH XBLT
MOVE T2,(P) ;GET STARTING ADDRESS OF ALLOCATION
MOVE T3,T2 ;GET ADDRESS OF SECOND WORD OF ALLOCATION
ADDI T3,1 ;...
SETZM (T2) ;ZERO FIRST WORD OF ALLOCATION
EXTEND T1,[XBLT] ;ZERO REMAINDER OF ALLOCATION
>; END IFN FTXMON
GTXWD2: MOVE T1,AHBFRE(P3) ;GET HEADER BLOCKS'S COUNT OF FREE WORDS
ADD T1,AHBPND(P3) ;PLUS CURRENT PENDING ALLOCATION AMOUNT
CAMGE T1,AHBTHR(P3) ;BELOW ALLOCATION THRESHOLD?
PUSHJ P,GTXXTD ;YES, GO TRY TO EXTEND POOL
JFCL ;DON'T CARE IF EXTENSION FAILED OR PENDING
PJRST TPOPJ1## ;RESTORE ADDRESS OF ALLOCATION AND RETURN
;HERE IF REQUESTED AMOUNT WOULD PUT ALLOCATOR OVER MAXIMUM
GTXWX1: MOVN T1,P1 ;GET NEGATIVE WORD COUNT
ADDM T1,ACBUSD(P4) ;FIX ALLOCATOR'S COUNT OF USED MEMORY
PJRST TPOPJ## ;CLEAN STACK AND RETURN
;HERE TO EXTEND A BITMAP MEMORY POOL
GTXWX2: ADDM P1,AHBFRE(P3) ;FIX HEADER BLOCK'S COUNT OF FREE WORDS
MOVN T1,P1 ;GET NEGATIVE WORD COUNT
ADDM T1,ACBUSD(P4) ;FIX ALLOCATOR'S COUNT OF USED MEMORY
PUSHJ P,GTXXTD ;EXTEND ALLOCATOR'S POOL IF POSSIBLE
PJRST TPOPJ## ;FAILED OR PENDING, CLEAN STACK AND RETURN
JRST GTXWD0 ;LOOP BACK TO TRY WITH LARGER POOL
;ROUTINE CALLED TO EXTEND A BITMAP MEMORY POOL
;LINKAGE:
; P3/ ADDRESS OF ALLOCATION HEADER BLOCK
; PUSHJ P,GTXXTD
;RETURNS:
; CPOPJ IF EXTENSION FAILED OR PENDING
; CPOPJ1 IF EXTENSION COMPLETED
GTXXTD: PUSHJ P,SAVE2## ;SAVE P1-P2
MOVE P1,AHBMIN(P3) ;GET MINIMUM FREE ALLOCATION AMOUNT
SUB P1,AHBFRE(P3) ;COMPUTE TARGET INCREMENTAL ALLOCATION
SUB P1,AHBPND(P3) ;...
TRZE P1,PG.BDY ;ROUND UP TO PAGE BOUNDARY
ADDI P1,PAGSIZ ;...
PJMPLE P1,CPOPJ## ;RETURN IF DON'T NEED INCREMENTAL ALLOCATION
CAMGE P1,AHBINC(P3) ;LESS THAN INCREMENTAL ALLOCATION AMOUNT?
MOVE P1,AHBINC(P3) ;YES, GET INCREMENTAL ALLOCATION AMOUNT
MOVE T1,AHBMAX(P3) ;GET MAXIMUM ALLOCATION AMOUNT
SUB T1,AHBCUR(P3) ;COMPUTE MAXIMUM AMOUNT TO ADD TO ALLOCATION
SUB T1,AHBPND(P3) ;...
CAMLE P1,T1 ;LESS THAN TARGET INCREMENTAL ALLOCATION
MOVE P1,T1 ;YES, USE MAXIMUM INCREMENTAL ALLOCATION
PJMPLE P1,CPOPJ## ;RETURN NOW IF AT MAXIMUM ALLOCATION
MOVE T2,P1 ;GET INCREMENTAL ALLOCATION AMOUNT
IDIV T2,AHBCSZ(P3) ;COMPUTE INCREMENTAL NUMBER OF CHUNKS
ADDI T2,^D35 ;CALCULATE NUMBER OF WORDS FOR BITMAP
IDIVI T2,^D36 ;...
ADDI T2,AEBLEN ;ADD IN SIZE OF ALLOCATION EXTENT BLOCK
PUSHJ P,GETWDS ;ALLOCATE SECTION 0 CORE
POPJ P, ;FAILED, RETURN NOW
MOVE P2,T1 ;SAVE ADDRESS OF ALLOCATION EXTENT BLOCK
MOVEM P1,AEBSIZ(P2) ;INITIALIZE EXTENT BLOCK'S EXTENT SIZE
MOVEM P1,AEBFRE(P2) ;AND COUNT OF FREE WORDS
MOVEM P1,AEBLWM(P2) ;AND LOW WATER MARK
MOVE T2,P1 ;GET INCREMENTAL ALLOCATION AMOUNT
IDIV T2,AHBCSZ(P3) ;CONVERT TO CHUNKS
ADDI T2,^D35 ;CALCULATE NUMBER OF WORDS FOR BITMAP
IDIVI T2,^D36 ; (REMAINDER IN T3)
MOVN T1,T2 ;BUILD AOBJN POINTER TO BIT MAP
HRLZS T1 ;...
HRRI T1,AEBBMP+1(P2) ;...
MOVEM T1,AEBBMP(P2) ;AND SAVE IN EXTENT BLOCK
SETZM AEBBMP+1(P2) ;ZERO FIRST WORD OF BITMAP
MOVSI T1,AEBBMP+1(P2) ;CONSTRUCT BLT POINTER TO CLEAR BITMAP
HRRI T1,AEBBMP+2(P2) ;...
ADDI T2,AEBBMP+1(P2) ;CALCULATE ADDRESS OF WORD FOLLOWING BITMAP
CAIE T2,AEBBMP+2(P2) ;IS BITMAP ONE WORD LONG?
BLT T1,-1(T2) ;NO, ZERO REMAINDER OF BITMAP
;CONTINUED ON NEXT PAGE
;CONTINUED FROM PREVIOUS PAGE
SUBI T3,^D35 ;CALCULATE NUMBER OF BITS TO MARK OFF
MOVNS T3 ; IN LAST WORD OF BITMAP
SETO T1, ;START WITH A COMPLETE MASK
LSH T1,(T3) ;COMPUTE MASK OF BITS TO KEEP
SETCAM T1,-1(T2) ;MARK OFF APPROPRIATE BITS IN LAST WORD
ADDM P1,AHBPND(P3) ;UPDATE HEADER BLOCK'S PENDING ALLOCATION
MOVE T1,P1 ;GET INCREMENTAL ALLOCATION AMOUNT
LSH T1,W2PLSH ;CONVERT TO PAGES
HRL T1,AHBSEC(P3) ;GET SECTION NUMBER FOR ALLOCATION
XMOVEI T2,GTXXT1 ;GET ADDRESS OF CALLBACK ROUTINE
MOVE T3,P2 ;GET ADDRESS OF ALLOCATION EXTENT BLOCK
MOVE T4,P3 ;AND ADDRESS OF ALLOCATION HEADER BLOCK
PJRST GETCLP## ;QUEUE ALLOCATION REQUEST AND RETURN
;HERE ON ALLOCATION COMPLETION CALLBACK
GTXXT1: PUSHJ P,SAVE3## ;SAVE P1-P3
MOVE P2,T3 ;GET BACK ADDRESS OF ALLOCATION EXTENT BLOCK
MOVE P3,T4 ;AND ADDRESS OF ALLOCATION HEADER BLOCK
MOVEM T1,AEBADR(P2) ;STORE ALLOCATED ADDRESS OF NEW EXTENT
MOVE P1,AEBSIZ(P2) ;GET SIZE OF ALLOCATION EXTENT
SKIPA T1,AHBAEB(P3) ;GET ADDRESS OF FIRST ALLOCATION EXTENT BLOCK
GTXXT2: MOVE T1,AEBNXT(T1) ;GET ADDRESS OF NEXT ALLOCATION EXTENT BLOCK
SKIPE AEBNXT(T1) ;FOUND END OF EXTENT BLOCK CHAIN?
JRST GTXXT2 ;NO, LOOP BACK
SETZM AEBNXT(P2) ;LINK NEW EXTENT BLOCK AT END OF CHAIN
MOVEM P2,AEBNXT(T1) ;...
MOVN T1,P1 ;GET NEGATIVE INCREMENTAL ALLOCATION AMOUNT
ADDM T1,AHBPND(P3) ;UPDATE HEADER BLOCK'S PENDING AMOUNT
ADDM P1,AHBCUR(P3) ;AND CURRENT ALLOCATION AMOUNT
ADDM P1,AHBFRE(P3) ;AND CURRENT FREE WORD AMOUNT
POPJ P, ;RETURN
;ROUTINE CALLED TO DEALLOCATE EXTENSIBLE BITMAP MEMORY
;LINKAGE:
; T1/ NUMBER OF WORDS
; T2/ ADDRESS OF MEMORY
; T3/ ADDRESS OF ALLOCATION CONTROL BLOCK
; PUSHJ P,GVXWDS
;RETURNS:
; CPOPJ ALWAYS
GVXWDS::PUSHJ P,SAVE4## ;SAVE P1-P4
MOVE P4,T3 ;SAVE ADDRESS OF ALLOCATION CONTROL BLOCK
MOVE P3,ACBAHB(P4) ;GET ADDRESS OF ALLOCATION HEADER BLOCK
MOVE P1,T1 ;GET SIZE OF MEMORY TO DEALLOCATE
IDIV P1,AHBCSZ(P3) ;CALCULATE NUMBER OF CHUNKS
SKIPE P2 ;ANY REMAINDER?
ADDI P1,1 ;YES, ROUND UP
IMUL P1,AHBCSZ(P3) ;CONVERT BACK INTO WORDS
SKIPA P2,AHBAEB(P3) ;GET ADDRESS OF FIRST ALLOCATION EXTENT BLOCK
GVXWD1: MOVE P2,AEBNXT(P2) ;GET ADDRESS OF NEXT ALLOCATION EXTENT BLOCK
SKIPN P2 ;AT END OF ALLOCATION EXTENT LIST?
STOPCD CPOPJ##,DEBUG,CORCNA ;++YES, CHUNK NOT ALLOCATED
MOVE T1,AEBSIZ(P2) ;GET SIZE OF EXTENT
ADD T1,AEBADR(P2) ;COMPUTE LAST ADDRESS WITHIN EXTENT
SUBI T1,1 ;...
CAML T2,AEBADR(P2) ;DOES CHUNK FALL WITHIN THIS EXTENT?
CAMLE T2,T1 ;...
JRST GVXWD1 ;NO, LOOP BACK AND TRY NEXT EXTENT
PUSH P,T2 ;SAVE ADDRESS OF CHUNK
MOVE T1,P1 ;GET NUMBER OF WORDS TO DEALLOCATE
IDIV T1,AHBCSZ(P3) ;CONVERT TO CHUNKS
POP P,T2 ;GET BACK CHUNK ADDRESS
SUB T2,AEBADR(P2) ;COMPUTE CHUNK OFFSET WITHIN EXTENT
IDIV T2,AHBCSZ(P3) ;...
SKIPE T3 ;ANY REMAINDER?
STOPCD CPOPJ##,DEBUG,CORNCB ;++NOT ON A CHUNK BOUNDARY
IDIVI T2,^D36 ;COMPUTE BIT TABLE AND BIT NUMBER OFFSETS
HRLS T2 ;MAKE AN AOBJN POINTER TO REST OF BITMAP
ADD T2,AEBBMP(P2) ;...
PUSHJ P,SETZRS ;CLEAR THE BITS
ADDM P1,AEBFRE(P2) ;UPDATE FREE WORD COUNTS
ADDM P1,AHBFRE(P3) ;...
MOVN T1,P1 ;GET NEGATIVE WORD COUNT
ADDM T1,ACBUSD(P4) ;UPDATE USED WORD COUNT
POPJ P, ;AND RETURN
SUBTTL CORE ALLOCATION -- NZS BITMAP MEMORY ROUTINES
;SUBROUTINES TO GET "FREE" CORE FROM NON-ZERO SECTIONS. USED
;BY DECNET, SCA, AND ETHERNET CODE (TO GIVE THEM A SEPARATE POOL,
;AND TO ALLOW CORE TO BE IN EXTENDED SECTIONS).
;CALL:
; T2/ NUMBER OF WORDS DESIRED
; PUSHJ P,GET?WS
;RETURN:
; CPOPJ IF AMOUNT DESIRED NOT AVAILABLE
; CPOPJ1 IF SUCCESS WITH:
; T1/ START OF CHUNK
IFN FTSCA,<
$CSENT (GETSWS::) ;GLOBAL ENTRY POINT
PUSHJ P,SAVE2## ;SAVE P1 AND P2
MOVEI P1,SCAPTR## ;ADDRESS OF AOBJN TABLE DESCRIBING POOL
MOVE P2,SCALOC## ;ADDRESS OF BASE OF POOL
PJRST GETXWS ;TRY TO FIND THE SPACE
>; END IFN FTSCA
IFN FTENET,<
GETEWZ::PUSHJ P,SAVE2## ;SAVE P1 AND P2
MOVEI P1,ETHPTR## ;ADDRESS OF AOBJN TABLE DESCRIBING POOL
MOVE P2,ETHLOC## ;ADDRESS OF BASE OF POOL
PJRST GETXWZ ;TRY TO FIND THE SPACE
GETEWS::PUSHJ P,SAVE2## ;SAVE P1 AND P2
MOVEI P1,ETHPTR## ;ADDRESS OF AOBJN TABLE DESCRIBING POOL
MOVE P2,ETHLOC## ;ADDRESS OF BASE OF POOL
PJRST GETXWS ;TRY TO FIND THE SPACE
IFN FTKL10,<
GETNWZ::PUSHJ P,SAVE2## ;SAVE P1 AND P2
MOVEI P1,KNIPTR## ;ADDRESS OF AOBJN TABLE DESCRIBING POOL
MOVE P2,KNILOC## ;ADDRESS OF BASE OF POOL
PJRST GETXWZ ;TRY TO FIND THE SPACE
GETNWS::PUSHJ P,SAVE2## ;SAVE P1 AND P2
MOVEI P1,KNIPTR## ;ADDRESS OF AOBJN TABLE DESCRIBING POOL
MOVE P2,KNILOC## ;ADDRESS OF BASE OF POOL
PJRST GETXWS ;TRY TO FIND THE SPACE
>; END IFN FTKL10
>; END IFN FTENET
;HERE TO DO THE WORK FOR GET?WS
IFN FTDECNET!FTSCA!FTENET,<
GETXWZ: MOVEI T1,3(T2) ;MAKE IT 4-WORD INCREMENTS
ASH T1,-2
EXCH T2,P1 ;SAVE SIZE, GET AOBJN POINTER TO BIT TABLE
PUSHJ P,GETBIT ;FIND THAT MANY BITS
POPJ P, ;NO GO, RETURN FAILURE.
ASH T1,2 ;CONVERT TO NUMBER OF WORDS
ADD T1,P2 ;ADD IN START ADDRESS OF POOL.
SETZM (T1) ;ZERO FIRST WORD OF CHUNK
SOS T2,P1 ;GET SIZE OF REMAINDER OF CHUNK
PJUMPE T2,CPOPJ1## ;RETURN IF NO OTHER WORDS TO ZERO
MOVE T3,T1 ;GET START ADDRESS OF CHUNK
XMOVEI T4,1(T3) ;AND START ADDRESS +1 OF CHUNK
EXTEND T2,[XBLT] ;ZERO REMAINDER OF CHUNK
JRST CPOPJ1## ;RETURN SUCCESS
GETXWS: MOVEI T1,3(T2) ;MAKE IT 4-WORD INCREMENTS
ASH T1,-2
MOVE T2,P1 ;AOBJN WORD TO BIT TABLE DESCRIBING THIS POOL
PUSHJ P,GETBIT ;FIND THAT MANY BITS
POPJ P, ;NO GO, RETURN FAILURE.
ASH T1,2 ;CONVERT TO NUMBER OF WORDS
ADD T1,P2 ;ADD IN START ADDRESS OF POOL.
JRST CPOPJ1## ;RETURN SUCCESS
>; END IFN FTDECNET!FTSCA!FTENET
;SUBROUTINES TO RETURN "FREE" CORE OBTAINED BY A CALL TO GET?WS.
;CALL:
; T1/ NUMBER OF WORDS TO RETURN
; T2/ ADDRESS OF CHUNK
; PUSHJ P,GIV?WS
;RETURN:
; CPOPJ ALWAYS
IFN FTSCA,<
$CSENT (GIVSWS::) ;GLOBAL ENTRY POINT
PUSHJ P,SAVE2## ;SAVE P1 AND P2
MOVE P1,SCAPTR## ;AOBJN TABLE DESCRIBING POOL
MOVE P2,SCALOC## ;ADDRESS OF BASE OF POOL
PJRST GIVXWS ;RETURN THE SPACE
>; END IFN FTSCA
IFN FTENET,<
GIVEWS::PUSHJ P,SAVE2## ;SAVE P1 AND P2
MOVE P1,ETHPTR## ;AOBJN TABLE DESCRIBING POOL
MOVE P2,ETHLOC## ;ADDRESS OF BASE OF POOL
PJRST GIVXWS ;RETURN THE SPACE
IFN FTKL10,<
GIVNWS::PUSHJ P,SAVE2## ;SAVE P1 AND P2
MOVE P1,KNIPTR## ;AOBJN TABLE DESCRIBING POOL
MOVE P2,KNILOC## ;ADDRESS OF BASE OF POOL
PJRST GIVXWS ;RETURN THE SPACE
>; END IFN FTKL10
>; END IFN FTENET
IFN FTDECNET!FTSCA!FTENET,<
GIVXWS: ADDI T1,3 ;ROUND UP
ASH T1,-2 ;CONVERT WORD COUNT TO 4-WORD COUNT
SUB T2,P2 ;CONVERT FROM ABSOLUTE TO RELATIVE ADDRESS
ASH T2,-2 ;CONVERT TO NUMBER OF 4 WORD BLOCKS
IDIVI T2,^D36 ;CONVERT TO OFFSET INTO TABLE OF BITS
HRLS T2 ;LEFT HALF....
ADD T2,P1 ;MAKE AN AOBJN POINTER TO REST OF TABLE
PJRST SETZRS ;AND ZERO BITS IN THE TABLE
>;END IFN FTDECNET!FTSCA!FTENET
SUBTTL CORE ALLOCATION -- SECTION 0 BITMAP MEMORY ROUTINES
;SUBROUTINE TO GET "FREE" CORE
;ENTER GETWDS: T2=# WORDS TO GET
;RETURN CPOPJ IF NOT AVAILABLE, WITH T2=LARGEST HOLE AVAILABLE
;RETURN CPOPJ1 IF GOTTEN, WITH T1=LOC OF CORE
$CSENT (GETWDS::) ;GLOBAL ENTRY POINT
ADDI T2,3 ;CONVERT TO 4 WORD BLOCKS
ASH T2,-2
MOVE T1,T2 ;NUMBER OF BLOCKS TO GET
SKIPE DINITF## ;INITIALIZATION?
SKIPE FREPTR## ;YES, BUT HAS FREE POINTER BEEN SET UP?
CAIA ;CAN USE REGULAR ALLOCATION NOW
JRST GETWDI ;JUST ALLOCATE FROM SYSSIZ
MOVEI T2,FREPTR## ;L(AOBJN WORD)
PUSH P,T1 ;SAVE NUMBER BEING REQUESTED
PUSHJ P,GETBIT ;GET, SET THE BITS
JRST GET4W2 ;NOT ENOUGH AVAILABLE
POP P,T2 ;RESTORE AMOUNT GOTTEN
IFN FTRSP,<
ADDM T2,FRUSED## ;BUMP FREE-CORE-USED WORD
>
LSH T1,2 ;*4 TO CONVERT TO AN ADDRESS
ADD T1,LOCORE## ;+START OF TABLE = ACTUAL ADDRESS
PJRST CPOPJ1## ;TAKE GOOD RETURN
;HERE IF REQUESTED AMOUNT ISNT AVAILABLE
GET4W2: MOVE T2,T1 ;LARGEST HOLE WE FOUND
JRST TPOPJ## ;TAKE LOST RETURN
$INIT
;HERE TO GET CORE DURING INITIALIZATION
GETWDI: PUSH P,T1 ;SAVE NUMBER OF BLOCKS REQUESTED
LSH T2,2 ;BACK TO WORDS NOW
MOVE T1,SYSSIZ## ;T1 = START OF ALLOCATION
ADD T2,T1 ;T2 = NEW FIRST FREE
MOVEM T2,SYSSIZ## ;UPDATE SYSSIZ
SKIPE .UONCE## ;USER MODE?
JRST GETWRO ;NEED CORE UUO
SUBI T2,1 ;BACK OFF BY A WORD
CAMLE T2,LOWLIM## ;GONE PAST THE LIMIT?
STOPCD .,STOP,EMA, ;++EXCEEDED MEMORY ALLOCATION
JRST T2POJ1## ;RESTORE # BLOCKS REQUESTED AND RETURN
GETWRO: MOVEM T2,.JBFF## ;KEEP MONITOR HAPPY
CAMLE T2,.JBREL## ;ALREADY HAVE CORE?
CORE T2, ;GET IT NOW
JFCL
JRST T2POJ1## ;RESTORE # BLOCKS REQUESTED AND RETURN
$HIGH
;SUBROUTINE TO ZERO BITS IN A BIT TABLE
;CALLING SEQUENCE:
; MOVE T1,NUMBER OF BITS TO CLEAR
; MOVE T2,AOBJN POINTER TO TABLE
; MOVE T3,BIT POSITION WITHIN TABLE
; PUSHJ P,ZERBTS
;ALWAYS RETURNS CPOPJ
ZERBTS::IDIVI T3,^D36 ;36 BITS/WORD
HRLS T3 ;WORD NUMBER TO BOTH HALVES
ADD T2,T3 ;POINT AOBJN POINTER TO WORD IN TABLE
MOVE T3,T4 ;BIT POSITION WITHIN WORD
PJRST SETZRS ;ZERO TIME BITS
;SUBROUTINE TO RETURN "FREE" CORE
;ENTER GIVWDS: T1=# WDS. TO RETURN, T2=START ADR. OF CORE
$CSENT (GIVWDS::) ;GLOBAL ENTRY POINT
SKIPE DINITF## ;INITIALIATION?
SKIPE FREPTR ;YES, BUT FREE POINTER SET UP?
CAIA ;OK TO DO BIT MAP STUFF
JRST GIVWDI ;INITIALIZATION, A BIT MORE TRICKY
ADDI T1,3 ;CONVERT TO # 4WD. BLOCKS
ASH T1,-2
SUB T2,LOCORE## ;GET ADR. RELATIVE TO START OF TABLE
IFN FTRSP,<
MOVN T3,T1
ADDM T3,FRUSED## ;DECREMENT FREE-CORE USED
>
LSH T2,-2 ;/4 TO CONVERT TO BITS
IDIVI T2,^D36 ;COMPUTE WORD LOC, STARTING BIT
HRLS T2 ;WORD POSITION IN BOTH HALVES
ADD T2,FREPTR## ;SET AOBJN WORD FOR TABLE
JRST SETZRS ;FALL INTO SETZRS
$INIT
;HERE DURING INITIALIZATION
GIVWDI: POPJ P, ;THANKS, WE DID OUR BEST
;MAYBE CALL GVFWDS HERE?
$HIGH
;SUBROUTINE TO SET ZEROS IN A TABLE
;ARG T1=HOW MANY BITS TO CLEAR
; T2=AOBJN POINTER FOR TABLE
; T3=POSITION IN WORD OF FIRST BIT TO CLEAR
; (0=BIT 0, 1=BIT 1, ETC.)
SETZRS::PUSH P,P3
SETZ P3, ;NOT TABLE RELATIVE
PUSHJ P,SETZRP ;ZERO THE BITS
JRST P3POPJ## ;RESTORE P3 AND RETURN
SETZRP::EXCH T1,T3 ;SET ACS FOR CLRBTS
MOVEI T4,^D36 ;ADJUST FOR 1ST WORD
SUBM T4,T1
HRRZ T4,T2 ;SET T4 FOR CLRBTS
PUSH P,T2 ;SAVE AOBJN WORD
PUSHJ P,CLRBTS ;CLEAR SOME BITS
STOPCD T2POPJ##,DEBUG,BAC, ;++BIT ALREADY CLEAR
POP P,T2 ;RESTORE AOBJN WORD
HLRE T3,T2 ;LENGTH OF POINTER
SUB T2,T3 ;COMPUTE TOP OF TABLE
CAILE T4,(T2) ;FINAL ADR PAST TOP?
STOPCD CPOPJ##,DEBUG,PTT, ;++PAST TOP OF TABLE
POPJ P, ;NO, GOOD RETURN
STRTAD==200000
RELABP==40000
;SUBROUTINE TO FIND N CONSECUTIVE 0'S IN A TABLE
;ENTER WITH P1 = AOBJN WORD TO THE TABLE
;P2 = PREVIOUS BEST SO FAR
;RH(P3)= HOW MANY, BIT STRTAD =1 IF START LOC SPECIFIED
;LH(P3) HAS BITS 0,1,2 USED BY FILSER
;EXIT CPOPJ1 IF FOUND, WITH P4 = WHERE THE HOLE IS, P1=UPDATED POINTER
;EXIT CPOPJ IF UNSUCCESSFUL, P2 = LARGEST HOLE FOUND
;P2,P4 CHANGED
;NOTE--SHOULD NOT CONTAIN A METER POINT SINCE IS CALLED
; BY ENDSTS ON 407 START BEFORE METINI IS CALLED
GETZ:: PUSHJ P,SETR ;ZERO R IF OLD STYLE CALL
GETZ0: TLNE P3,STRTAD ;START LOC SPECIFIED? (NOTE THAT ENTRY TO ROUTINE
; IS AT GETZR IF START LOC SPECIFIED)
POPJ P, ;YES, ERROR RETURN
HRRM P1,-2(P) ;STORE ABOJN POINTER IN INDIRECT WORD
SETCM T1,@-2(P) ;WORD TO INVESTIGATE
JRST GETZA ;SKIP CALL TO SETR
GETZX:: PUSHJ P,SETR ;SETUP INDIRECT POINTER
GETZA: MOVEI T4,^D36 ;NO. SET UP COUNT
JUMPE T1,GETZ4 ;FULL IF 0
JUMPG T1,GETZ3 ;1ST BIT UNAVAILABLE IF POSITIVE
GETZ1: SETCA T1, ;SET TO REAL CONTENTS
JFFO T1,.+2 ;COUNT THE NUMBER OF 0'S
MOVEI T2,^D36 ;36 OF THEM
JRST GETZB ;SKIP CALL TO SETR
GETZR:: PUSHJ P,SETR ;SETUP INDIRECT POINTER TO THE BIT TABLE
GETZB: MOVE T3,T2 ;SHIFT COUNT (T3 CAN BE .GT. 36 AT GETZ2)
MOVEM P1,P4 ;SAVE POSITION IN P4
HRLM T4,P4 ;LOC OF HOLE
GETZ2: CAIL T3,(P3) ;FOUND ENOUGH?
JRST CPOPJ1## ;YES. GOOD RETURN
CAILE T3,(P2) ;NO. BEST SO FAR?
HRRI P2,(T3) ;YES. SAVE IT
SUBI T4,(T2) ;DECREASE POSITION COUNTER
JUMPLE T4,GETZ5 ;0'S ON END
TLNE P3,STRTAD ;THIS HOLE NOT GOOD ENOUGH
POPJ P, ;ERROR RETURN IF START ADDRESS GIVEN
SETCA T1, ;NOW WE WANT TO COUNT 1'S
LSH T1,1(T2) ;REMOVE BITS WE ALREADY LOOKED AT
JUMPE T1,GETZ4 ;GO IF THE REST OF THE WORD IS ALL ONES
GETZ3: JFFO T1,.+1 ;NUMBER OF (REAL) 1'S
LSH T1,(T2) ;GET RID OF THEM
CAIN T4,^D36 ;1ST POSITION IN WORD?
ADDI T4,1 ;YES, SUBTRACT REAL JFFO COUNT
SUBI T4,1(T2) ;DECREASE POSITION COUNT
JUMPG T4,GETZ1 ;TRY NEXT 0 - HOLE
GETZ4: AOBJN P1,GETZ0 ;1'S ON END - START FRESH AT NEXT WORD
;HERE IF THE DESIRED SIZE NOT YET FOUND, BUT THE WORD HAD 0'S ON THE END
GETZ5: AOBJP P1,CPOPJ## ;THROUGH IF END OF SAT
HRRM P1,-2(P) ;STORE UPDATED AOBJN POINTER
SKIPGE T1,@-2(P) ;NEXT WORD POSITIVE?
JRST GETZ0 ;NO. THIS HOLE NOT GOOD ENOUGH
JFFO T1,.+2 ;YES. COUNT THE 0'S
MOVEI T2,^D36 ;36 0'S
ADDI T3,(T2) ;ADD TO PREVIOUS ZERO-COUNT
MOVEI T4,^D36 ;RESET T4
JRST GETZ2 ;AND TEST THIS HOLE
;SUBROUTINE TO SET UP A BIT MASK FOR IORM OR ANDCAM INTO A TABLE
;ENTER WITH T1=POSITION (36=BIT0, 1=BIT35)
; AND T3=HOW MANY
;AFTER THE FIRST CALL USE BITMS2, T3=COUNT RETURNS T1=MASK,
;T3=REMAINING COUNT ROUTINE HAS RETURNED FINAL MASK IF
;T3 .LE. 0 ASSUMES T4=ADR IN TABLE, BITMS2 INCREMENTS T4
BITMSK::PUSH P,T1 ;SAVE POSITION
MOVN T1,T3 ;- COUNT
CAILE T3,^D36 ;MORE THAN 1 WORD?
MOVNI T1,^D36 ;YES, SETTLE FOR A WORD (OR LESS)
MOVSI T2,400000 ;SET TO PROPOGATE A MASK
ASH T2,1(T1) ;GET THE RIGHT NUMBER OF BITS
SETZ T1,
LSHC T1,@0(P) ;POSITION THE BITS IN T1 (=MASK)
SUB T3,0(P) ;REDUCE THE COUNT TO THE NEW VALUE
PJRST T2POPJ## ;AND RETURN
;HERE AFTER FIRST CALL, MASK STARTS AT BIT 0
BITMS2::SETO T1, ;MASK STARTS AT BIT 0
MOVNI T2,-^D36(T3) ;SET UP SHIFT
CAIGE T3,^D36 ;DONT SHIFT IS .GE. 36
LSH T1,(T2) ;POSTION THE MASK
SUBI T3,^D36 ;REDUCE THE COUNT
AOJA T4,CPOPJ## ;UPDATE THE POSITION AND RETURN
;SUBROUTINE TO MARK BITS AS TAKEN IN A TABLE
;USES ACS AS RETURNED BY GETZ - P3=HOW MANY
; LH(P4)=POSITION, RH(P4)=WHERE (POSITION=36 IF BIT0, 1 IF BIT35)
;RETURNS CPOPJ IF BIT IS ALREADY SET, CPOPJ1 NORMALLY, RESPECTS T1
SETOS:: PUSHJ P,SETR ;SETUP INDIRECT POINTER TO THE BIT TABLE
PUSH P,T1 ;SAVE T1
MOVE T4,P4 ;WHERE
HRRZ T3,P3 ;COUNT
HLRZ T1,P4 ;POSITION IN WORD
PUSHJ P,BITMSK ;SET UP A MASK
SETOS1: HRRM T4,-3(P) ;FOR INDIRECT
BTSOFF ;BETTER NOT INTERRUPT HERE
TDNE T1,@-3(P) ;BIT ALREADY ON?
JRST SETOS2 ;YES
IORM T1,@-3(P) ;NO, NOW IT IS
BTSON ;RESTOR PI
JUMPLE T3,TPOPJ1## ;DONE IF COUNT .LE. 0
PUSHJ P,BITMS2 ;NOT DONE, GET MASK FOR NEXT WORD
JRST SETOS1 ;AND GO SET THE BITS IN THAT WORD
;HERE IF BIT ALREADY ON
SETOS2: BTSON ;PI CAN BE ON
PUSH P,T3 ;SAVE CURRENT COUNT
HLRZ T1,P4 ;RESTORE ORIGINAL VALUES
HRRZ T3,P3
MOVE T4,P4
PUSHJ P,BITMSK ;AND GENERATE A MASK
SETOS3: HRRM T4,-4(P) ;SET FOR INDIRECT
CAMN T3,(P) ;IS THE COUNT FOR MASK=COUNT WHEN SET?
JRST SETOS4 ;YES, DONE
ANDCAM T1,@-4(P) ;NO, CLEAR THOSE BITS
PUSHJ P,BITMS2 ;GENERATE NEXT MASK
JRST SETOS3 ;AND CONTINUE
SETOS4: POP P,(P) ;CLEARED ALL THE RIGHT BITS - FIX PD LIST
JRST TPOPJ## ;AND NON-SKIP RETURN
;SUBROUTINE TO OBTAIN FREE BITS, MARK THEM AS TAKEN IN THE TABLE
;ENTER WITH T1=HOW MANY,
;T2=XWD ADR OF 1ST WORD OF TABLE, ADR OF TABLE AOBJN WORD (OR 0, LOC OF AOBJN)
;RETURNS CPOPJ IF NOT ENOUGH AVAILABLE, T1=SIZE OF LARGEST HOLE
;RETURNS CPOPJ1 IF GOTTEN, T1= RELATIVE ADDRESS OF BLOCK OBTAINED
;T3 IS UPDATED AOBJN POINTER
GETBIT::PUSHJ P,SAVE4## ;SAVE P1-P4
TLNN T2,-1 ;STARTING AT AN OFFSET?
HRL T2,(T2) ;NO, START AT FIRST WORD
PUSH P,T2 ;SAVE ADR OF AOBJN WORD FOR TABLE
GETBI1: HRRZ P1,0(P) ;GET AOBJN WORD
MOVE P1,(P1)
SETZ P2, ;NO BEST SO FAR
MOVE P3,T1 ;NUMBER OF BITS TO GET
PUSHJ P,GETZ ;GET THE BITS
JRST GETBI2 ;NOT ENOUGH AVAILABLE
HRRZ T1,P4 ;GOT THEM - FIRST WORD WITH ZEROES
HLRZ T2,(P) ;LOC OF FIRST WORD OF TABLE
SUBI T1,(T2) ;COMPUTE RELATIVE ADDRESS OF START
IMULI T1,^D36 ;36 BITS PER WORD
HLRZ T2,P4 ;BIT POSITION OF 1ST 0 IN THE WORD
MOVNS T2
ADDI T1,^D36(T2) ;T1= RELATIVE LOC WITHIN THE TABLE
PUSHJ P,SETOS ;MARK THE BITS AS TAKEN
SKIPA T1,P3 ;SOME FINK SNUCK IN ON US!
AOSA -1(P) ;GOT THEM - WIN RETURN
JRST GETBI1 ;TRY AGAIN TO GET SOME BITS
MOVE T3,P1 ;UPDATED POINTER
JRST T2POPJ## ;RETURN
;HERE IF NOT ENOUGH ARE AVAILABLE
GETBI2: MOVE T1,P2 ;T1=LARGEST HOLE FOUND
PJRST T2POPJ## ;NON-SKIP RETURN
;ROUTINE TO CLEAR BITS FROM A TABLE
;ENTER T1=POSITION, T3=COUNT, T4=TABLE ADR
; POSITION=36 IF BIT0, 1 IF BIT35
;RETURNS POPJ IF BIT ALREADY 0, POPJ1 OTHERWISE
CLRBTS::PUSHJ P,BITMSK ;GENERATE A MASK
PUSHJ P,SETR ;SETUP TABLE ADDRESS
CLRBT1: HRRM T4,-2(P) ;SET INDIRECT WORD
BTSOFF ;CANT INTERRUPT
MOVE T2,@-2(P) ;WORD TO CLEAR BITS FROM
TDC T2,T1 ;ARE THE BITS ALREADY OFF?
TDNE T2,T1
PJRST ONPOPB## ;YES, RESTORE PI AND NON-SKIP
MOVEM T2,@-2(P) ;NO, NOW THEY ARE
BTSON ;RESTORE THE PI
JUMPLE T3,CPOPJ1## ;DONE IF COUNT .LE. 0
PUSHJ P,BITMS2 ;GENERATE MASK FOR NEXT WORD
JRST CLRBT1 ;AND GO CLEAR THOSE BITS
;SUBROUTINE TO FIND N CONSECUTIVE ZEROS IN A TABLE
;ARGS T1=AOBJN POINTER TO TABLE
; T2=PREVIOUS BEST
; T3=HOW MANY, BIT STRTAD=1 IF START ADDR SPECIFIED
;VALUES IF UNSUCCESSFUL, T2=LARGEST HOLE FOUND, NON-SKIP RETURN
; IF SUCCESSFUL, T4=POSITION OF BEGINNING OF HOLE, SKIP RETURN
;THIS ROUTINE CALLS GETZ BUT SATISFIES STANDARD AC CONVENTIONS
CLGETZ::PUSHJ P,SAVE4## ;SAVE GLOBAL ACS
MOVE P1,T1 ;SET ACS FOR GETZ
MOVE P2,T2
MOVE P3,T3
PUSHJ P,GETZ ;GET THE BITS
CAIA ;NOT ENOUGH AVAILABLE
AOS (P) ;OK, SET FOR SKIP RETURN
MOVE T1,P1 ;RESTORE T-ACS WITH ANSWERS
MOVE T2,P2
MOVE T3,P3
MOVE T4,P4
POPJ P, ;TAKE WIN OR LOSE RETURN
;SUBROUTINE TO SET BITS IN A TABLE
;ARGS T3=HOW MANY
; T4=POSITION OF FIRST, RH=ADDR, LH=POSITION, 36=BIT 0,1=BIT 35
;THIS ROUTINE CALLS SETOS BUT SATISFIES STANDARD AC CONVENTIONS
CSETOS::PUSHJ P,SAVE4## ;SAVE P1-P4
MOVE P3,T3 ;SET ACS FOR SETOS
MOVE P4,T4
PUSHJ P,SETOS ;SET THE BITS
STOPCD CPOPJ##,DEBUG,BNZ, ;++BIT NOT ZERO
POPJ P, ;OK, RETURN
;INTERFACE ROUTINE TO GETZ/SETOS WHICH ALLOWS THEM TO BE CALLED WITH AN
; EXTENDED ADDRESS AND A AOBJN POINTER RELATIVE TO A BIT TABLE
;CALLING SEQUENCE:
; MOVE R,ADDRESS OF THE BIT TABLE
; MOVE P1,AOBJN POINTER RELATIVE TO THE TABLE
; TLO P3,RELABP ;INDICATE THIS FORM OF CALL
; PUSHJ P,SETR ;MUST BE IN A NON-ZERO SECTION IF RELABP IS ON
;ALWAYS RETURN CPOPJ, -2(P) IS AN INSTRUCTION FORMAT INDIRECT WORD TO BIT TABLE
SETR: PUSH P,R ;SAVE R, SOME CALLERS MAY WANT IT RETURNED
MOVSI R,400000+R ;LOCAL INSTRUCTION FORMAT INDIRECT WORD
EXCH R,-1(P) ;SAVE IT ON THE STACK, GET RETURN ADDRESS
MOVEM R,1(P) ;TO CALL THE CALLER
IFN FTXMON,<
TLNN P3,RELABP ;RELATIVE AOBJN POINTER SPECIFIED?
JRST SETR1 ;NO, OLD CALL
TLNN R,(SECMSK) ;MUST BE IN A NON-ZERO SECTION IF RELABP IS ON
STOPCD SETR2,DEBUG,NNS,;++NOT IN A NON-ZERO SECTION
>
TLNN P3,RELABP ;NEW CALL?
SETR1: TDZA R,R ;NO, NO RELOCATION
MOVE R,(P) ;YES, GET RELOCATION
PUSHJ P,@1(P) ;CALL CALLER AS A COROUTINE
CAIA ;NON-SKIP RETURN
AOS -2(P) ;PROPAGATE SKIP
SETR2: POP P,R ;RESTORE R
POP P,(P) ;POP OFF JUNK
POPJ P, ;AND RETURN
COREND: END