Google
 

Trailing-Edge - PDP-10 Archives - bb-d868a-bm - 3-sources/cspmem.mac
There are 4 other files named cspmem.mac in the archive. Click here to see a list.
TITLE	CSPMEM -- Memory Interface for "Friends of QUASAR"
SUBTTL	Chuck O'Toole	20 Apr 76


	SEARCH	QSRMAC		;PARAMETER FILE

	PROLOGUE(QSRMEM)	;GENERATE THE NECESSARY SYMBOLS



;COPYRIGHT (C) 1977 BY
;DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;
;
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
;ONLY  IN  ACCORDANCE  WITH  THE  TERMS  OF  SUCH LICENSE AND WITH THE
;INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE OR ANY  OTHER
;COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
;OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF THE  SOFTWARE  IS  HEREBY
;TRANSFERRED.
;
;
;THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT  NOTICE
;AND  SHOULD  NOT  BE  CONSTRUED  AS A COMMITMENT BY DIGITAL EQUIPMENT
;CORPORATION.
;
;DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY  OF  ITS
;SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.


COMMENT\

	Entry points found in CSPMEM

M$INIT	Initialization entry point
M$ACQP	Acquire a page from the page map
M$RELP	Return page 'AP' to the page map
M$IPSN	Notification that IPCF send of page 'AP' is about to occur
M$NXPG	Get a non-existant page for an IPCF receive
M$IPRC	Notification that IPCF receive of a page has occurred
M$IPRM	Make room for IPCF page we couldn't fit in core
M$AQNP	Acquire N contiguous pages from the map
M$RLNP	Release pages acquired from M$AQNP
M$CLNC	Clean Core For Cusps About To Go Dormant

	STOPCDs found in CSPMEM

ASE	ADDRESSING SPACE EXHAUSTED
BPN	BAD PAGE NUMBER
CCP	CANNOT CREATE PAGE
CFN	CANNOT FIND N CONTINUOUS PAGES
CGA	CANNOT GIVE ACCESS TO PAGE
CRC	CANNOT REDUCE CORE
FCE	FREE COUNT EXCEEDS FREINI
FCN	FREE COUNT NEGATIVE
NTS	NOTHING TO SWAP OUT
PAF	PAGE ACCESS CHECK FAILED
PDF	PAGE DESTROY FAILED
PIF	PAGE IN FAILURE
POF	PAGE OUT FAILURE
RFP	RELEASING FREE PAGE
RNP	RECEIVED NON-EXISTANT PAGE
UPF	UNKNOWN PAGE FAULT TYPE

\
SUBTTL	Initialization Entry Point

;CALLED BY CSPINI AT FIRST START-UP TO INITIALIZE THE MEMORY MANAGER
;ALL REGISTERS ARE AVAILABLE AT THIS TIME

	INTERN	M$INIT

M$INIT:	HLRZ	AP,.JBSA##		;SIZE OF LOW SEGMENT
	ADDI	AP,777			;ROUND TO A PAGE BOUNDRY
	ADR2PG	AP			;COMPUTE FIRST AVAILABLE PAGE
	MOVEM	AP,PAGSTA		;STORE FOR PAGE SEARCHING LOOPS
	MOVEI	S1,^D512		;NOW COMPUTE THE REMAINING ADDRESS SPACE
	SUB	S1,AP			;OFFSET FOR LOW SEGMENT CODE
	HRRZ	AP,.JBHRL##		;LAST LOCATION IN THE HIGH SEGMENT
	ADR2PG	AP			;WORKS ONLY FOR TRADITIONAL ONES
	SKIPE	AP			;IS THERE A HIGH SEGMENT
	  SUBI	AP,377			;YES, COMPUTE NUMBER OF PAGES THERE
	SUB	S1,AP			;OFFSET FOR HIGH SEGMENT CODE
	MOVEM	S1,FREPGS		;SAVE FOR M$NXPG CHECK
	MOVEM	S1,FREINI		;SAVE INITIAL VALUE FOR CHECKS
	ZERO	PAGTBL			;START WITH A CLEAR PAGE MAP
	MOVE	S1,[PAGTBL,,PAGTBL+1]	;SET UP FOR THE BLT
	BLT	S1,PAGTBL+^D511		;CLEAR THE WHOLE THING
	JUMPE	AP,INIT.1		;DONE IF NO HIGH SEGMENT
	MOVX	S1,PT.USE		;GET THE USE BIT
	MOVEM	S1,PAGTBL+377(AP)	;SET FOR EACH PAGE IN THE HIGH SEGMENT
	SOJG	AP,.-1			;TO PREVENT USAGE, PAGING
INIT.1:

IFN FTUUOS,<	;TOPS10 INITIALIZATION

	MOVE	S1,[PFHEND,,PFHBGN]	;PAGE FAULT HANDLER POINTERS
	MOVE	S2,PFHBGN		;TOUCH THE FIRST LOCATION AND THE LAST
	MOVE	S2,PFHEND		;TO GUARANTEE PFH IS IN CORE
	MOVEM	S1,.JBPFH##		;NOW SET UP OUR OWN HANDLER
	MOVE	S1,[.STTVM,,^D5000]	;SET VIRTUAL TIME TRAP
	SETUUO	S1,			;SET TO GIVE A PAGE FAULT
	  JFCL				;OH WELL, WE'LL JUST RUN A LITTLE SLOWER
	MOVE	AP,PAGSTA		;GET THE STARTING PAGE NUMBER
	DECR	AP			;IT GETS AOS'ED LATER
	MOVEM	AP,SWPSTA		;START OF THE SWAPPING TABLE
	PG2ADR	AP			;CONVERT TO ADDRESS
	MOVEI	AP,777(AP)		;LAST LOCATION WE KNOW ABOUT
	CORE	AP,			;DON'T CARE ABOUT ANYTHING ELSE
	  STOPCD(CRC,FATAL)		;++CANNOT REDUCE CORE
	SETZM	INMEMF			;CLEAR A FLAG

>  ;END OF IFN FTUUOS

	POPJ	P,			;AND RETURN
SUBTTL	Page Management Subroutines

;ROUTINE TO ACQUIRE 'N' CONTIGUOUS PAGES FROM THE MAP
;CALL	S1 = NUMBER REQUESTED (MAY BE 1 BUT NOT 0)
;	PUSHJ	P,M$AQNP
;	  RETURNS AP = THE FIRST OF 'N'
;DESTROYS S1
;CALLS M$ACQP (ENTERS VIA ACQP.1)

	INTERN	M$AQNP

M$AQNP:	JUMPE	S1,S..CFN		;GIVE AN ERROR IF WANTS 0
	CAIN	S1,1			;WANT ONLY 1
	  PJRST	M$ACQP			;YES, USE ACQP INSTEAD
	PUSHJ	P,PFHOFF		;DON'T ALLOW TIMER TRAPS
	PUSHJ	P,.SAVE3##		;SAVE A COUPLE FIRST
	MOVEI	P1,(S1)			;GET THE NUMBER REQUESTED
	MOVE	AP,PAGSTA		;FIRST PAGE TO TRY FOR
	MOVEI	P2,-1(P1)		;COPY THE COUNT FOR THE LOOP BELOW
	PUSHJ	P,AQNP.3		;GET ONE
AQNP.1:	MOVEI	P3,(AP)			;SAVE THAT NUMBER
	PUSHJ	P,AQNP.4		;GET ANOTHER
	CAIE	AP,1(P3)		;ARE THEY CONTIGUOUS?
	  MOVEI	P2,(P1)			;NO, RESET LOOP COUNT
	SOJG	P2,AQNP.1		;GET MORE IF REQUIRED
AQNP.2:	PUSHJ	P,ACQP.1		;CREATE PAGE "AP"
	SOJLE	P1,.POPJ##		;RETURN IF ALL DONE
	SOJA	AP,AQNP.2		;ELSE BACK DOWN TO THE NEXT ONE

AQNP.3:	CAIL	AP,^D512		;ONLY WANT PAGES THAT ARE UNUSED
	  STOPCD(CFN,FATAL)		;++CANNOT FIND N CONTINUOUS PAGES
	LOAD	S1,PAGTBL(AP),PT.USE	;THIS ONE USED
	PJUMPE	S1,.POPJ##		;NO, TAKE THIS ONE
AQNP.4:	AOJA	AP,AQNP.3		;TRY ANOTHER

;ROUTINE TO RELEASE 'N' CONTIGUOUS PAGES (NORMALLY ONES FROM M$AQNP)
;CALL	S1 = NUMBER TO RELEASE
;	AP = THE FIRST PAGE
;	PUSHJ	P,M$RLNP
;DESTROYS S2, AP
;CALLS M$RELP

	INTERN	M$RLNP

M$RLNP:	MOVEI	S2,(S1)			;M$RELP WILL KLUNK S1
RLNP.1:	PUSHJ	P,M$RELP		;RELEASE PAGE 'AP'
	SOJLE	S2,.POPJ##		;RETURN IF DONE
	AOJA	AP,RLNP.1		;ELSE RELEASE THE NEXT ONE
;ROUTINE TO ACQUIRE A FRESH PAGE FROM THE PAGE MAP
;CALL	PUSHJ	P,M$ACQP
;	  RETURNS AP = PAGE NUMBER
;DESTROYS S1
;CALLS FNDPAG, PGSOUT, PGSDES, ANYOUT

	INTERN	M$ACQP

M$ACQP:	PUSHJ	P,PFHOFF		;DON'T ALLOW TIMER TRAPS
	PUSHJ	P,FNDPAG		;FIND THE BEST AVAILABLE PAGE
	SKIPN	AP			;SKIP IF ONE FOUND
	  STOPCD(ASE,FATAL)		;++ADDRESSING SPACE EXHAUSTED

IFN FTJSYS,<

ACQP.1:	MOVX	S1,PT.USE!PT.WRK!PT.ADR	;GET ALL THE BITS
	IORM	S1,PAGTBL(AP)		;INCLUDE THEM
	PJRST	REDUCE			;REDUCE COUNT OF FREE CORE AND RETURN

>  ;END OF IFN FTJSYS

IFN FTUUOS,<

ACQP.1:	PUSHJ	P,REDUCE		;REDUCE COUNT OF FREE PAGES
	MOVX	S1,PT.USE		;GET THE INUSE BIT
	IORB	S1,PAGTBL(AP)		;SET IN USE, GET THE OTHERS
	TXNE	S1,PT.ADR		;IS IT ADDRESSABLE
	  POPJ	P,			;YES, RETURN (MAY PAGE FAULT IT IN LATER)
	PUSHJ	P,.SAVE3##		;SAVE P1-P3
ACQP.2:	MOVEI	P3,(AP)			;ARGUMENT FOR CREATE A PAGE
	MOVEI	P2,1			;ONLY 1 ARGUMENT
	MOVE	P1,[.PAGCD,,P2]		;FUNCTION CREATE/DESTROY,,ARGUMENTS
	PAGE.	P1,			;TRY THE CREATE
	  JRST	ACQP.3			;ANALYZE THE ERROR
	MOVX	S1,PT.WRK!PT.ADR	;IN THE WORKING SET, ADDRESSABLE
	IORM	S1,PAGTBL(AP)		;INCLUDE THE FLAG
	POPJ	P,			;AND RETURN
ACQP.3:	PUSH	P,AP			;SAVE THE PAGE WE'RE TRYING TO CREATE
	CAIE	P1,PAGNS%		;OUT OF SWAPPING SPACE
	  JRST	ACQP.4			;NO, LOOK AGAIN
	MOVEI	AP,5			;TAKE A QUICK NAP FIRST
	SLEEP	AP,			;IN CASE SOME FREES UP
	PUSHJ	P,PGSDES		;FREE SOME SWAPPING SPACE
	POP	P,AP			;RESTORE AP
	JRST	ACQP.2			;AND RETRY THE CREATE
ACQP.4:	CAIE	P1,PAGLE%		;MY LIMIT EXCEEDED
	  STOPCD(CCP,FATAL)		;++CANNOT CREATE PAGE
	PUSHJ	P,ANYOUT		;SWAP OUT ANYTHING
	POP	P,AP			;RESTORE AP
	JRST	ACQP.2			;RETRY THE CREATE

>  ;END OF IFN FTUUOS
;ROUTINE TO ACQUIRE A FRESH (UNADDRESSABLE) PAGE FROM THE PAGE MAP FOR IPCF
;CALL	PUSHJ	P,M$NXPG
;	  RETURNS AP = THE PAGE NUMBER AVAILABLE FOR IPCF RECEIVE
;			0 IF NONE AVAILABLE (NO CORE AVB)
;		NORMALLY, A CALL TO M$IPRC FOLLOWS THE RECEIVE AND THE PAGE IS INCLUDED
;			IN FACT, THE CALL TO M$IPRC IS REQUIRED TO KEEP FREPGS STRAIGHT
;DESTROYS S1
;CALLS FNDPAG, PGSOUT, PGSDES

	INTERN	M$NXPG

M$NXPG:	PUSHJ	P,PFHOFF		;DON'T ALLOW TIMER TRAPS
	MOVE	S1,FREPGS		;GET FREE CORE LEFT
	CAIL	S1,^D5			;INSURE IPCF WON'T FILL OUR SPACE
	  JRST	NXPG.1			;GO TRY TO GET ONE
NXPG.0:	ZERO	AP			;RETURN A ZERO
	POPJ	P,			;THAT WILL SHUT IT OFF

IFN FTJSYS,<			;TOPS20 WILL REPLACE ANY EXISTING PAGE WITH THE MESSAGE

NXPG.1:	PUSHJ	P,FNDPAG		;ESSENTUALLY DUPLICATE M$ACQP
	PJUMPE	AP,.POPJ##		;RETURN 0 IF CANT GET ONE NOW
	MOVX	S1,PT.USE		;SET THE TEMP STATE
	IORM	S1,PAGTBL(AP)		;OF INUSE BUT NOT ADDRESSABLE
	POPJ	P,			;AND RETURN

>  ;END OF IFN FTJSYS

IFN FTUUOS,<			;TOPS10 REQUIRES A NON-EXISTANT PAGE

NXPG.1:	PUSHJ	P,NXPG.3		;FIND A COMPLETELY MISSING PAGE
	JUMPN	AP,NXPG.2		;TAKE THIS ONE
	PUSHJ	P,.SAVE3##		;SAVE P1-P3
	PUSHJ	P,PGSDES		;DESTROY ALL I CAN
	PUSHJ	P,NXPG.3		;NOW TRY TO FIND ONE
	PJUMPE	AP,.POPJ##		;RETURN 0 IF CANT GET ONE NOW
NXPG.2:	MOVX	S1,PT.USE		;SET THE TEMP STATE
	IORM	S1,PAGTBL(AP)		;OF INUSE BUT NOT ADDRESSABLE
	POPJ	P,			;AND RETURN

NXPG.3:	MOVE	AP,PAGSTA		;START AT THE FIRST AVAILABLE PAGE
NXPG.4:	CAIL	AP,^D512		;END OF THE ADDRESSING SPACE
	  JRST	NXPG.0			;YES, RETURN A ZERO
	MOVE	S1,PAGTBL(AP)		;GET THE TABLE ENTRY
	TXNN	S1,PT.USE!PT.WRK!PT.ADR	;IS THIS PAGE THERE
	  POPJ	P,			;NO BITS MEANS NON-EXISTANT
	AOJA	AP,NXPG.4		;WELL, TRY THE NEXT

>  ;END OF IFN FTUUOS
;ROUTINE TO RETURN A PAGE TO THE PAGE MAP
;CALL	AP = PAGE NUMBER
;	PUSHJ	P,M$RELP
;DESTROYS S1

	INTERN	M$RELP

M$RELP:	PUSHJ	P,VALPAG		;CONSISTENCY CHECK 'AP'
	MOVE	S1,PAGTBL(AP)		;GET THE FLAGS
	TXZN	S1,PT.USE		;CLEAR IN USE
	  STOPCD(RFP,FATAL)		;++RELEASING FREE PAGE
	TXNE	S1,PT.ADR		;IS THIS THE ONE IPCF'ED AWAY
	  JRST	RELP.1			;NO, GO FIX THE COUNTS
	ZERO	PAGTBL(AP)		;CLEAR THE ENTRY
	POPJ	P,			;AND RETURN
RELP.1:	MOVEM	S1,PAGTBL(AP)		;STORE NEW SETTINGS
	PJRST	INCLUD			;BUMP FREE PAGE COUNT AND RETURN

;ROUTINE TO SET NOTIFICATION OF A PAGE BEING IPCF'ed FROM OUR ADDRESSING SPACE
;CALL	AP = PAGE NUMBER
;	PUSHJ	P,M$IPSN
;DESTORYS S1

	INTERN	M$IPSN

M$IPSN:	PUSHJ	P,VALPAG		;CONSISTENCY CHECK 'AP'
	MOVX	S1,PT.WRK!PT.ADR	;CLEAR IN THE WORKING SET, ADDRESSABLE
	ANDCAM	S1,PAGTBL(AP)		;SO THAT WE DON'T GET CONFUSED
	PJRST	INCLUD			;BUMP FREE PAGE COUNT AND RETURN
;ROUTINE TO INCLUDE A PAGE RECEIVED BY IPCF INTO OUR ADDRESSING SPACE
;CALL	AP = THE PAGE NUMBER
;	PUSHJ	P,M$IPRC
;DESTROYS S1,S2

	INTERN	M$IPRC

IFN FTUUOS,<	;NOW NEED TO KNOW IF THE PAGE IS IN THE WORKING SET

M$IPRC:	PUSHJ	P,VALPAG		;CONSISTENCY CHECK 'AP'
	MOVEI	S2,(AP)			;FOR PAGE 'AP'
	HRLI	S2,.PAGCA		;CHECK ITS ACCESS BITS
	PAGE.	S2,			;SEE IF THE PAGE IS SWAPPED OUT
	  STOPCD(PAF,FATAL)		;++PAGE ACCESS CHECK FAILED
	MOVX	S1,PT.WRK!PT.ADR	;IN THE WORKING SET, ADDRESSABLE
	TXNE	S2,PA.GNE		;PAGE DOESN'T EXIST
	  STOPCD(RNP,FATAL)		;++RECEIVED NON-EXISTANT PAGE
	TXNE	S2,PA.GPO		;IS IT PAGED OUT
	  TXZ	S1,PT.WRK		;YES, CLEAR IN THE WORKING SET
	IORM	S1,PAGTBL(AP)		;INCLUDE THE FLAG(S)
	PJRST	REDUCE			;REDUCE COUNT OF FREE PAGES AND RETURN

>  ;END OF IFN FTUUOS

IFN FTJSYS,<

M$IPRC:	PUSHJ	P,VALPAG		;CONSISTENCY CHECK 'AP'
	MOVX	S1,PT.WRK!PT.ADR	;IN THE WORKING SET, ADDRESSABLE
	IORM	S1,PAGTBL(AP)		;INCLUDE THE FLAGS
	PJRST	REDUCE			;REDUCE COUNT OF FREE PAGES AND RETURN

>  ;END OF IFN FTJSYS
;ROUTINE TO SEARCH THE PAGE MAP FOR THE BEST PAGE FOR M$ACQP TO USE
; "BEST" IS THE FIRST OF 
;			AN INCORE FREE PAGE
;		OR	A SWAPPED OUT FREE PAGE
;		OR	A NON-EXISTANT PAGE

;CALL	PUSHJ P,FNDPAG
;	  RETURNS AP = THE PAGE OR 0 IF OUT OF ADDRESSING SPACE
;DESTROYS S1,S2

FNDPAG:	MOVE	AP,PAGSTA		;FIRST AVAILABLE PAGE
	ZERO	S2			;LH = NON-EXIST , RH = SWAPPED OUT
FNDP.1:	CAIL	AP,^D512		;OFF THE END
	  JRST	FNDP.2			;YES, DIDN'T FIND OUR FIRST CHOICE
	MOVE	S1,PAGTBL(AP)		;GET THE TABLE ENTRY
	TXNE	S1,PT.USE		;THIS ONE IN USE
	  AOJA	AP,FNDP.1		;YES, DON'T EVEN BOTHER
	TXCN	S1,PT.WRK!PT.ADR	;FLIP, P.S. DOES THIS PAGE EXIST
	 TLNE	S2,-1			;NO, BUT HAVE I ALREADY FOUND ONE
	  SKIPA				;EXISTS OR ONE OF THAT TYPE FOUND ALREADY
	   HRLI	S2,(AP)			;REMEMBER NON-EXISTANT PAGE FOR LATER
	TXCN	S1,PT.WRK!PT.ADR	;BACK, P.S. IS IT INCORE AND FREE
	  POPJ	P,			;CAN'T GET ANY BETTER THAN THAT
	TXNE	S1,PT.ADR		;IS IT ADDRESSABLE
	  HRRI	S2,(AP)			;YES, REMEMBER THAT TOO
	AOJA	AP,FNDP.1		;AND LOOP
FNDP.2:	MOVEI	AP,(S2)			;GET 2ND BEST TYPE
	PJUMPN	AP,.POPJ##		;RETURN IF THERE WAS ONE
	HLRZ	AP,S2			;GET LAST CHOICE
	POPJ	P,			;RETURN ANYWAY


;CONSISTENCY CHECKS ON THE NUMBER OF FREE PAGES IN OUR ADDRESSING SPACE
;"REDUCE" DECREMENTS THE FREE PAGE COUNT , "INCLUD" ADDS A FREE PAGE
;
;INCLUD DESTROYS S1

REDUCE:	SOSGE	FREPGS			;DECREMENT COUNT OF FREE PAGES
	  STOPCD(FCN,FATAL)		;++FREE COUNT NEGATIVE
	POPJ	P,			;RETURN IF OK

INCLUD:	AOS	S1,FREPGS		;ADD A FREE PAGE
	CAMLE	S1,FREINI		;MORE THAN WE STARTED OUT WITH
	  STOPCD(FCE,FATAL)		;++FREE COUNT EXCEEDS FREINI
	POPJ	P,			;RETURN IF OK STILL

;CONSISTENCY CHECK ON 'AP', THE PAGE NUMBER ARGUMENT TO
;	M$RELP, M$IPSN, M$IPRC

VALPAG:	CAIG	AP,^D511		;OVER THE TOP OF THE WORLD
	 CAMGE	AP,PAGSTA		;OR UNDER THE INITIAL VALUE
	  STOPCD(BPN,FATAL)		;++BAD PAGE NUMBER
	POPJ	P,			;RETURN, 'AP' IS IN RANGE
SUBTTL	The Page Fault Handler

;THIS IS THE ROUTINE CALLED BY THE TOPS10 SYSTEM SO THAT A USER MAY PROCESS
;HIS OWN PAGE FAULTS.  .JBPFH CONTAINS THE STARTING ADDRESS OF THE ROUTINE
;AND IS CALLED WHEN EITHER A FAGE FAULT OCCURS OR THE .STTVM TIMER HAS EXPIRED

IFN FTUUOS,<	;THIS CODE EXISTS ONLY FOR THE TOPS10 MONITOR

PFHBGN:	JRST	PFHSTA			;ENTERED HERE
PFH.PC:	0				;PC AT TIME OF TRAP
PFH.PN:	0				;PAGE FAULT WORD
PFH.TI:	0				;VIRTUAL AGE OF THE PAGE FAULT HANDLER
PFH.RA:	0				;CURRENT PAGING RATE
	BLOCK	4			;ROOM FOR FUTURE EXPANSION

PFHSTA:	MOVEM	P,PFHS.P		;SAVE SOMEBODY'S P
	MOVE	P,[IOWD PF.PSZ,PF.PDL]	;GET MY OWN PDL
	PUSH	P,P1			;BEGIN TO SAVE SEVERAL REGISTERS
	PUSH	P,P2			;CAUSE I'M GOING TO CALL SUBROUTINES
	PUSH	P,P3			;FOR SWAPPING AND SEARCHING
	PUSH	P,AP			;AND THESE ARE THE ARGUMENTS
	LOAD	P2,PFH.PN,PF.HFC	;THE FAULT TYPE
	CAIG	P2,PFHDCT		;RANGE CHECK
	  JRST	PFHDSP(P2)		;DISPATCH THE FAULT
PFHDSP:	JRST	PFHILL			;PAGE FAULT CODE = 0 OR TOO BIG
	JRST	PFHGVA			;.PFHNA = 1 = NO ACCESS
	JRST	PFHSWI			;.PFHNI = 2 = NOT IN CORE
	JRST	PFHSWI			;.PFHUU = 3 = NOT IN CORE FOR UUO
	JRST	PFHTIM			;.PFHTI = 4 = VM TIMER TRAP
PFHDCT==.-PFHDSP-1			;DISPATCH LENGTH (0-n)

PFHILL:	STOPCD	(UPF,FATAL)		;++UNKNOWN PAGE FAULT TYPE

PFHSWI:	LOAD	P3,PFH.PN,PF.HPN	;GET THE PAGE THAT CAUSED THE FAULT
	MOVEI	P2,1			;ONLY 1 PAGE
	MOVE	P1,[.PAGIO,,P2]		;FUNCTION PAGE IO,,ARGUMENT BLOCK
	PAGE.	P1,			;SWAP IT IN
	  JRST	PFHSWF			;FAILED, SEE WHY
	MOVX	P1,PT.WRK		;THE WORKING SET BIT
	IORM	P1,PAGTBL(P3)		;PAGE IS NOW IN CORE
	JRST	PFHXIT			;DISMISS THE FAULT
PFHSWF:	CAIE	P1,PAGLE%		;IS MY CORE LIMIT EXCEEDED
	  STOPCD(PIF,FATAL)		;++PAGE IN FAILURE
	PUSHJ	P,ANYOUT		;SWAP OUT SOMETHING (ANYTHING)
	JRST	PFHSWI			;TRY THE SWAPIN NOW

;;;CODE IS CONTINUED ON THE NEXT PAGE AND STILL UNDER FTUUOS CONDITIONAL
;HERE TO GIVE ACCESS TO A PAGE (CAN ONLY HAPPEN IF LOADED VIA GET.SHR)

PFHGVA:	LOAD	P3,PFH.PN,PF.HPN	;GET THE PAGE NUMBER WE CAN'T ACCESS
	TXO	P3,1B0			;SET TO ALLOW ACCESS
	MOVEI	P2,1			;ONLY ONE ARG
	MOVE	P1,[.PAGAA,,P2]		;GIVE ACCESS,,ARGS
	PAGE.	P1,			;SET ACCESS ALLOWED ON THAT PAGE
	  STOPCD(CGA,FATAL)		;++CANNOT GIVE ACCESS TO PAGE
	JRST	PFHXIT			;AND EXIT FROM THE PAGE FAULT HANDLER

;HERE ON A TIMER TRAP, SEE IF WE CAN CLEAN UP SOME CORE

PFHTIM:	SKIPN	INMEMF			;SOMEBODY FOOLING WITH THE PAGE TABLE
	  PUSHJ	P,PGSDES		;NO, DESTROY ANY JUNK PAGES
PFHXIT:	POP	P,AP			;RESTORE AP
	POP	P,P3			;...
	POP	P,P2			;...
	POP	P,P1			;...
	MOVE	P,PFHS.P		;RESTORE THE OLD AC P
	JRSTF	@PFH.PC			;DISMISS THE FAULT

PFHS.P:	BLOCK	1			;SAVED P
PF.PDL:	BLOCK	^D12			;PDL FOR USE IN THE PAGE FAULT HANDLER
PF.PSZ==.-PF.PDL			;SIZE OF THE LIST

;ROUTINE TO DESTROY AS MANY PAGES THAT ARE SWAPPED OUT OR UNUSED
;CALL	PUSHJ	P,PGSDES
;	RETURNS AFTER DESTROYING AS MANY AS POSSIBLE
;DESTORYS AP,P1-P3 WITHOUT SAVING

	INTERN	M$CLNC

M$CLNC:	PUSHJ	P,.SAVE3##		;SAVE P1-P3
	SAVE	AP			;SAVE AP AND FALL INTO PGSDES
PGSDES:	MOVE	AP,PAGSTA		;THE FIRST AVAILABLE PAGE
PGSD.1:	CAIL	AP,^D512		;OFF THE END OF THE WORLD
	  POPJ	P,			;YES, RETURN
	MOVE	P1,PAGTBL(AP)		;GET THE TABLE ENTRY
	TXC	P1,PT.ADR		;NEED CHECK FOR BOTH SO FLIP
	TXNN	P1,PT.USE!PT.ADR	;USED OR NOT ADDRESSABEL
	  PUSHJ	P,DESTRY		;DESTROY THE PAGE (COULD BE PAGED OUT)
	AOJA	AP,PGSD.1		;AND CONTINUE LOOPING

DESTRY:	MOVEI	P3,(AP)			;WANT IT IN P3
	TXO	P3,1B0			;SET TO DESTROY
	MOVEI	P2,1			;1 ARGUMENT
	MOVE	P1,[.PAGCD,,P2]		;CREATE/DESTROY,,ARGUMENT
	PAGE.	P1,			;TRY TO DESTROY IT
	  STOPCD(PDF,FATAL)		;++PAGE DESTROY FAILED
	ZERO	PAGTBL(AP)		;CLEAR THE PAGE MAP ENTRY
	POPJ	P,			;RETURN


;;;CODE IS CONTINUED ON THE NEXT PAGE AND STILL UNDER FTUUOS CONDITIONAL
;ROUTINE TO SWAP OUT ANYTHING POSSIBLE SO THAT A PAGEIN CAN OCCUR
;CALL	PUSHJ	P,ANYOUT
;	RETURNS AFTER A PAGE HAS BEEN SUCCESSFULLY PAGED OUT
;DESTROYS AP, P1-P3 WITHOUT SAVING
;COULD EXIT THROUGH DESTRY

	INTERN	M$IPRM

M$IPRM:	PUSHJ	P,.SAVE3##		;SAVE P1-P3
	SAVE	AP			;AND AP AND FALL INTO ANYOUT
ANYOUT:	MOVE	AP,PAGSTA		;FIRST MAKE A PASS LOOKING FOR ANY FREE
ANYO.1:	PUSHJ	P,ANYO.4		;PAGES THAT CAN BE DESTROYED
	JUMPE	AP,ANYO.2		;NONE, PAGE SOMETHING OUT
	TXNE	P1,PT.USE		;IS THIS IN-CORE PAGE USED
	  AOJA	AP,ANYO.1		;YES, LOOK FOR ANOTHER
	PJRST	DESTRY			;NO, DESTROY IT NOW AN SAVE A SWAP
ANYO.2:	AOS	AP,SWPSTA		;START WHERE WE LEFT OFF
	PUSHJ	P,ANYO.4		;FIND A SWAPPED IN PAGE
	JUMPN	AP,ANYO.3		;SWAP IT OUT
	MOVE	AP,PAGSTA		;RE-START AT THE FIRST
	PUSHJ	P,ANYO.4		;TRY NOW
	JUMPN	AP,ANYO.3		;FOUND ONE, SWAP IT OUT
	STOPCD	(NTS,FATAL)		;++NOTHING TO SWAP OUT
ANYO.3:	MOVEM	AP,SWPSTA		;REMEMBER FOR LATER
	MOVEI	P3,(AP)			;COPY THE PAGE NUMBER
	TXO	P3,1B0			;SET TO SWAP OUT INSTEAD OF SWAP IN
	MOVEI	P2,1			;ONLY 1 PAGE FOR NOW
	MOVE	P1,[.PAGIO,,P2]		;FUNCTION SWAP,,ARGUMENT BLOCK
	PAGE.	P1,			;OUT IT GOES
	  STOPCD(POF,FATAL)		;++PAGE OUT FAILURE
	MOVX	P1,PT.WRK		;GET THE WORKING SET BIT
	ANDCAM	P1,PAGTBL(P3)		;NOT THERE ANY MORE
	POPJ	P,			;AND RETURN FOR ANY RETRIES

ANYO.4:	CAIL	AP,^D512		;OVER THE TOP
	  JRST	ANYO.5			;YES, RETURN A ZERO
	MOVE	P1,PAGTBL(AP)		;GET THE STATUS FLAGS
	TXNE	P1,PT.ADR		;IS IT ADDRESSABLE
	 TXNN	P1,PT.WRK		;YES, IS IT IN THE WORKING SET
	  AOJA	AP,ANYO.4		;TRY THE NEXT PAGE
	POPJ	P,			;YES, A CANDIDATE FOR SWAP OUT
ANYO.5:	ZERO	AP			;RETURN 0 IF NONE FOUND
	POPJ	P,			;RETURN

SWPSTA:	BLOCK	1			;PAGE NUMBER FOR START OF SWAP OUT SEARCH

PFHEND:		;THE LAST LOCATION WITHIN THE PAGE FAULT HANDLER


;;;CODE IS CONTINUED ON THE NEXT PAGE AND STILL UNDER FTUUOS CONDITIONAL
;CO-ROUTINE TO SET FLAG DISALLOWING PAGE FAULT TIMER TRAPS
;	THE FLAG INDICATES THAT SOME ROUTINE IS GOING TO RELY ON
;	THE SETTINGS OF THE PAGE TABLE FLAGS AND THAT PGSDES SHOULD NOT
;	BE CALLED BY THE PAGE FAULT HANDLER.

PFHOFF:	SKIPE	INMEMF			;RE-CURSIVE CALL
	  POPJ	P,			;YES, WAIT FOR ORIGINAL CALLER TO RETURN
	POP	P,INMEMF		;REMOVE CALL, SET FLAG NON-ZERO
	PUSHJ	P,@INMEMF		;CALL THE CALLER
	 SKIPA				;NON-SKIP RETURN
	  AOS	(P)			;PROPOGATE THE SKIP RETURN
	SETZM	INMEMF			;ALLOW TRAPS NOW
	POPJ	P,			;AND RETURN

INMEMF:	BLOCK	1			;FLAG INDICATING INSIDE MEMORY MANAGER

>  ;END OF IFN FTUUOS

IFN FTJSYS,<		;SOME THINGS NOT NEEDED ON TOPS20

M$CLNC::		;DON'T NEED TO CLEAN CORE OF UNUSED PAGES
PFHOFF:			;NO PAGE FAULTS TO WORRY ABOUT
	POPJ	P,	;TURN THEM INTO NOP'S

>  ;END OF IFN FTJSYS
SUBTTL	Constants and Other Things

	XLIST		;FORCED OUT LITERAL POOL HERE
	LIT
	LIST
	SALL

FREPGS:	BLOCK	1	;COUNT OF FREE PAGES LEFT IN ADDRESSING SPACE
FREINI:	BLOCK	1	;THE INITIAL VALUE OF FREPGS FOR CONSISTENCY CHECKS
PAGSTA:	BLOCK	1	;THE STARTING POINT FOR PAGSRC SEARCHES
PAGTBL:: BLOCK	^D512	;THE PAGE MAP

	END