Google
 

Trailing-Edge - PDP-10 Archives - BB-X140B-BB_1986 - 10,7/703mon/swpser.mac
There are 6 other files named swpser.mac in the archive. Click here to see a list.
TITLE SWPSER - HANDLES I/O FOR SWAPPER - V1174
SUBTTL	SWPSER   R.KRASIN/AW/CMF/AF/DJB/DAL  26 NOV 85
	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 VSWPSR,1174

ENTRY SWPSER
SWPSER::
	EXTERN	JBYSUN,JBYLKN


;THIS CODE SERVES AS AN INTERFACE BETWEEN THE SWAPPER (SCHED1) AND
;I/O CODE FOR SWAPPING DEVICES (FILSER)


IDLEUN==1	;LOOKING FOR AN IDLE UNIT IF 0
;HERE TO START PAGING/SWAPPING I/O IN A MONITOR WHICH INCLUDES VM

SQIN::
SQOUT::	MOVEI	F,SWPDDB##	;SWAPPING DDB
	AOS	DEVDMP##(F)	;INSURE DEVDMP NON-ZERO SO ERROR RECOVERY WILL HAPPEN
	AOS	T1,SQREQ	;COUNT UP THE NUMBER OF PAGING/SWAPPING I/O REQUESTS
	SOJE	T1,SWAPIO##	;START SWAPPING/PAGING I/O IF NOT ALREADY GOING
	PJRST	DOPOPJ##	;I/O IN PROGRESS, GO AWAY

;HERE WHEN PAGING/SWAPPING I/O IS DONE IN A MONITOR WHICH INCLUDES VM
SWPINT::SOSGE	SQREQ		;COUNT DOWN THE NUMBER OF PAGING/SWAPPING I/O
				; REQUESTS OUTSTANDING
	STOPCD	CPOPJ##,DEBUG,SWN,;++SQREQ WENT NEGATIVE
	PUSHJ	P,SAVE2##	;SAVE P1,P2
	MOVE	P2,(P1)		;P2 = THE SWPLST ENTRY
	SUBI	P1,SWPLST##	;P1 = RELATIVE ADDRESS INTO SWPLST OF ENTRY
	TLC	P2,(SL.SIO+SL.IPC) ;JUST SWAP OUT THE "IN" QUEUE?
	TLCN	P2,(SL.SIO+SL.IPC)
	JRST	SWPI4A		;YES, JUST GO FINISH UP
	HRRZ	J,SW3LST##(P1)	;SEGMENT NUMBER SWAPPING/PAGING IS DONE FOR
	TLNE	P2,(SL.SIO)	;SWAPPING I/O?
	JRST	SWPIN2		;YES
	TLNN	P2,(SL.DIO)	;PAGE OUT?
	JRST	[PUSHJ P,ZERSLE## ;NO, RETURN THE DISK SPACE
		JRST	SWPIN1]	;PROCEED
	PUSHJ	P,SVEUB##	;MAKE THE UPMP ADDRESSABLE
	MOVSI	T1,(UP.PGB)	;INDICATE PAGES OUT BUT NOT GIVEN BACK TO
	IORM	T1,.USBTS	; FREE CORE YET
SWPIN1:	MOVE	T1,J		;PAGING I/O, JOB NUMBER TO T1 STPIOD
	PUSHJ	P,STPIOD##	;PUT JOB INTO PAGE I/O SATISFIED STATE
	JRST	SWPIN6		;PROCEED
SWPIN2:	TLNN	P2,(SL.DIO)	;SWAP OUT?
	CAILE	J,JOBMAX##	;NO, HIGH SEGMENT SWAP IN?
	JRST	SWPIN3		;YES, PROCEED
	HRRZ	T2,JBTUPM##(J)	;ADDRESS OF THE PAGE ALLOCATED TO THE UPMP
	SE1ENT			;MUST BE IN SECTION 1 TO REFERENCE PAGTAB
	SSX	T2,MS.MEM	;PAGTAB SECTION

	LDB	T1,[POINT SL.SPN,SWPLST##(P1),<^L<SL.PPN>+SL.SPN-1>] ;ASSUME NOT FRAGD
	SKIPL	T3,SWPLST##(P1)	;FRAGMENTED?
	SKIPA	T2,PAGTAB(T2)
	LDB	T1,[POINT SL.SPN,1(T3),<^L<SL.PPN>+SL.SPN-1>] ;UPT IS SECOND ENTRY OF FRAGMENT IF IT IS
	CAIE	T1,(T2)		;SWAPPING IN THE UPMP?
	JRST	SWPIN3		;NO
	MOVE	T3,.CPMAP##
	HRRZ	T1,JBTUPM##(J)
	TLO	T1,(<PM.DCD>B2+PM.WRT+PM.PUB+IFE FTMP,<PM.CSH>)
	MOVE	T2,JBTSWP##(J)	;PAGE WE LEFT OFF AT
	TLO	T2,(<PM.DCD>B2+PM.WRT+PM.PUB+IFE FTMP,<PM.CSH>)
	MOVEM	T1,.ECKSM/PAGSIZ##(T3)

	CLRPGT	(0)		;FLUSH THE HARDWARE P.T.
IFN FTKL10&FTMP,<
	SKIPN	[M.CPU##-1]	;SINGLE KL-10 MONITOR
	TDO	T1,[PM.CSH]	;YES, CACHE THE UPMP
>
	TLO	T1,(PM.COR)
	MOVEM	T1,.ECKSM+.UMUPT
	MOVEM	T2,.ECKSM+.UMJDT
	MOVE	T2,T1		;SAVE STATE OF THE CACHE BIT
	TLO	T1,(PM.CSH)
	MOVEM	T1,.ECKSM+.UMUUP
	SSX	T1,MS.MEM	;PAGTAB SECTION
	HRR	T2,PAGTAB(T1)
	TLO	T2,(PM.COR)
	MOVEM	T2,.ECKSM+.UMUPM
	TLO	T2,(PM.PUB+PM.CSH) ;USER MAP WILL DECIDE PUBLIC/CONCEALED
	MOVEM	T2,.ECKSM+SECTAB

	JRST	SWPIN7
SWPIN3:	SKIPGE	JBTSWP##(J)	;RUN OUT OF CORE BLOCKS DURING FRAGMENTED SWAP IN?
	TLNE	P2,(SL.DIO)	;(ONLY IF SWAPIN)
	JRST	SWPI3A		;NO, GET ADDRESS OF SEGMENT
	CAIG	J,JOBMAX##	;THIS CASE CAN ONLY COME UP FOR A LOW SEG
	JRST	SWPIN7		;YES, SWAP IN NEXT FRAGMENT
SWPI3A:	MOVE	T1,JBTADR##(J)
SWPIN4:	TLNN	P2,(SL.DIO)	;IF INPUT
	SOSL	SINCNT##	;DECREMENT SWAPPING INPUTS IN PROGRESS
SWPI4A:	SOSGE	SPRCNT##	;DECREMENT SWAP IN PROGRESS COUNT
	STOPCD	CPOPJ##,DEBUG,SNI,	;++SWAPPING NOT IN PROGRESS
	TLNE	P2,(SL.ERR+SL.CHN+SL.CHK+SL.IPC) ;I/O ERROR OR "IN" QUEUE SWAP OUT?
	JRST	SWPIN5		;YES
	PUSHJ	P,GETCHK##	;MAKE THE CHECKSUM ADDRESSABLE
	HRRZS	T1		;CLEAR POSSIBLE JUNK

	MOVE	T1,(T1)		;GET THE CHECKSUM WORD
	TLNE	P2,(SL.DIO)	;SWAPPING OUT?
	JRST	[MOVEM	T1,JBTCHK##(J)	;YES, STORE THE CHECKSUM WORD
		 JRST	SWPIN5]	;AND PROCEED
	MOVSI	T2,(SL.CHK)	;ASSUME AN ERROR OCCURED
	CAME	T1,JBTCHK##(J)	;CHECKSUM THE SAME AS ON THE WAY OUT?
	JRST	[IORM	T2,SWPLST##(P1)	;NO, INDICATE AN ERROR
		 JRST	SWPIN5]	;CONTINUE
	LDB	T1,NZSSCN##	;# OF NZS MAPS
	JUMPE	T1,SWPIN5
	PUSHJ	P,SVEUB##	;MAP JOB
	SKIPGE	T1,.USBTS	;REALLY BIG YET?
	TLNN	T1,(UP.NZS)	;AND NEED TO CALL BISLST?
	JRST	SWPIN5		;NO
	AOS	SINCNT
	AOS	SPRCNT		;READJUST COUNTS
	JRST	SWPN7A		;CALL BISLST YET AGAIN
SWPIN5:	MOVSI	T1,(SL.DFM)	;ALLOW FNDSLE TO FIND THIS ENTRY
	ANDCAB	T1,SWPLST##(P1)	;SWPCNT AND SWPLST AGREE
	TLC	T1,(SL.FRG!SL.DIO)
	TLCN	T1,(SL.FRG!SL.DIO) ;WAS THIS FRAGMENTED OUTPUT?
	TLNE	T1,(SL.IPC)	;AND NOT THE PAGING QUEUE OR IPCF?
	JRST	SWPINA		;NO
	PUSHJ	P,SVEUB##	;POINT TO JOB
	SKIPE	T2,.USLPS	;RETURN VIRTUAL POINTER IF IT EXISTS
	PUSHJ	P,RTNVPN##	;(CAN'T ZERO SLOT AS IT'S NON-ZERO ON DISK)
SWPINA::
	AOS	SWPCNT##	;FLAG FOR CLOCK-LEVEL
SWPIN6:	MOVE	S,DEVIOS(F)	;SWAPPING DDB STATUS
	SKIPN	SQREQ		;STILL MORE SWAPPING OR PAGING I/O TO DO?
	TRZ	S,IOACT		;NO, THE DDB IS NO LONGER I/O ACTIVE
	PUSHJ	P,STOIOS##	;REMEMBER THAT IN THE DDB
	PJRST	NJBTST##	;START THE SCHEDULAR IF THE NULL JOB IS RUNNING


SWPIN7:	PUSHJ	P,SVEUB##	;MAKE JOB ADDRESSABLE
SWPN7A:	CAMN	J,.USJOB	;RIGHT JOB?
	TDZA	P2,P2		;YES
	MOVSI	P2,(SL.CHK)	;NO, SWAP READ ERROR
	IOR	P2,SWPLST##(P1)	;RESTORE P2 WITH POSSIBLE ERROR BIT
	TLNN	P2,(SL.ERR+SL.CHN+SL.CHK) ;DON'T CLEAR SL.SIO IF ERROR
	TLZ	P2,(SL.SIO)	;CLEAR A BIT SO DLTSLE
	MOVEM	P2,SWPLST##(P1)	; WON'T SOS SWPCNT
	TLNE	P2,(SL.ERR+SL.CHN+SL.CHK)	;I/O ERRORS?
	JRST	SWPIN4		;SET I/O DONE SO ERROR WILL BE NOTICED
	PUSHJ	P,ZERSLE##	;RETURN THE DISK SPACE
	S0PSHJ	DLTSLE##	;DELETE THE SWPLST ENTRY
	PUSHJ	P,BISLST##	;SETUP MEMTAB FOR LOW SEGMENT SWAP IN
	AOS	SQREQ		;ONE MONE SWAPPING REQUEST TO DO
	POPJ	P,		;RETURN TO FILIO

	RELABP==40000
;SUBROUTINE TO FIND SPACE ON SWAPPING DEVICE
;ARG	U=NUMBER 1K BLOCKS NEEDED
;CALL	MOVEI	U,1K BLOCKS NEEDED, PG.SLO=1 IF SWAP IN SLOW SWAP SPACE
;	PUSHJ	P,SWPSPC
;	ERROR RETURN - SPACE NOT AVAILABLE
;	OK RETURN - DEV ADDR STORED IN LH JBTSWP(J) AND IN T1
;	DEV ADDR WILL NOT BE STORED IN JBTSWP(J) IF J=0

SWPSPC::PUSHJ	P,SAVE4##	;SAVE GLOBAL ACS
IFN FTXMON,<
	PUSHJ	P,SSEC1##	;MUST BE IN A NON-ZERO SECTION TO ADDRESS SATS
	PUSH	P,R		;RELOCATION (SECTION NUMBER)
	HRRZS	J		;MAKE SURE NO BITS
>
	MOVE	P2,U		;P2=NUMBER 1K BLOCKS NEEDED
	HLRZ	U,NXTSUN##	;GET ADDR OF NEXT UNIT FOR SWAPPING
	HRRZ	P4,SWPUN2##	;CLASS WHICH "SLOW" SWAPPING UNITS BELONG TO
	SKIPN	P4		;IF "SLOW" UNITS ARE IN CLASS 0
	TLZ	P2,(PG.SLO)	; IGNORE REQUEST FOR "SLOW" SPACE
	HLLZ	P4,P2		;REMEMBER PG.SLO
	TLZE	P2,(PG.SLO)	;SLOW (DISK) SWAP SPACE WANTED?
	HLRZ	U,SWPUN2##	;YES, GET UNIT OF FIRST SLOW DISK IN ASL


;LOOP TO SCAN NEXT CLASS OF SWAPPING UNIT

GT1:	SETZB	P3,T3
	LDB	P1,UNYCFS##	;GET CLASS FOR SWAPPING
	HRL	P1,U		;SAVE ADDR WHERE WE STARTED

;LOOP TO SCAN NEXT UNIT IN ACTIVE SWAPPING LIST IN THIS CLASS

GT2:	LDB	T2,UNYCFS##	;GET CLASS FOR SWAPPING OF THIS UNIT
	CAIE	T2,(P1)		;SKIP IF STILL SAME CLASS
	JRST	GT5		;NO
	TLNN	T3,IDLEUN	;IF 1ST TIME
	SKIPN	UNISTS##(U)	; USE UNIT IF IDLE
	CAMLE	P2,UNIFKS##(U)	;SKIP IF ENOUGH ROOM ON THIS UNIT
	JRST	GT4		;FORGET IT FOR NOW
	MOVE	T1,P2		;T1 = NUMBER 1K BLOCKS NEEDED
	PUSHJ	P,GXSAT		;SEE IF CONTIGUOUS SPACE AVAILABLE
	  JRST	GT3		;NO
	JRST	FOUND		;YES

;HERE IF ENOUGH ROOM ON THIS UNIT, BUT NOT CONTIGUOUS

GT3:	TLNE	T3,IDLEUN
	CAML	P3,UNIFKS##(U)	;SKIP IF THIS UNIT HAS MOST ROOM
	JRST	GT4		;SOMEBODY BETTER IN THIS CLASS
	MOVE	P3,UNIFKS##(U)	;REMEMBER SPACE ON BEST UNIT
	HRR	T3,U		;AND ITS ADDR
;HERE TO CHECK NEXT UNIT IN THIS CLASS

GT4:	HLRZ	U,UNISWP##(U)	;NEXT UNIT FOR SWAPPING
	MOVSS	P1		;UNIT SCAN WAS STARTED AT
	TLNE	T3,IDLEUN	;IF NOT FIRST PASS,
	CAIE	U,(P1)		;DON'T LOOK FUTHER IF ALL UNITS IN THIS CLASS SCANNED
	JUMPN	U,[MOVSS P1	;PUT CURRENT CLASS BACK IN THE RH
		   JRST GT2]	;LOOK AT NEXT UNIT FOR SWAPPING
	MOVSS	P1		;CURRENT CLASS
GT5:	TLOE	T3,IDLEUN	;1ST PASS?
	JRST	GT6		;NO. NO CONTIGUOUS SPACE
	PUSHJ	P,FNDFUC	;YES, RESET U
	JRST	GT2		; AND SETTLE FOR ANY UNIT

;HERE IF END OF THIS CLASS AND NO UNIT HAD CONTIGUOUS SPACE

GT6:	HRRZ	U,T3		;SET U TO ADDR OF UNIT WITH MOST ROOM
	CAMG	P2,P3		;SKIP IF NOT ENOUGH ROOM ON UNIT WITH MOST ROOM
	JRST	FOUND1		;WE HAVE A WINNER
	PUSHJ	P,FNDFUC	;RESET ADDR OF 1ST UNIT THIS CLASS

;HERE TO SEE IF BY DELETING DORMANT SEGMENTS WE CAN CREATE ENOUGH
;SPACE ON A UNIT IN THE CURRENT CLASS

GT7:	LDB	T1,UNYCFS##	;GET CLASS FOR SWAPPING OF THIS UNIT
	CAIE	T1,(P1)		;SEE IF STILL SAME CLASS
	JRST	GT1		;NO
	PUSHJ	P,IFDELE##	;FIND OUT IF BY DELETING DORMANT SEGS CAN DO IT
	  JRST	GT8		;NO
	PUSHJ	P,DODELE##	;RIGHT ON!
	  JRST	GT8		;THERE WAS JUST ROOM!

;HERE IF HAD TO DELETE DORMANT SEGMENTS - MAY NOW HAVE CONTIGUOUS SPACE

	MOVE	T1,P2		;T1=1K BLOCKS NEEDED
	PUSHJ	P,GXSAT		;SEE IF CONTIGUOUS SPACE AVAILABLE
	  JRST	FOUND1		;NO
	JRST	FOUND		;YES!

;HERE IF DELETING DORMANT SEGMENTS DOESN'T HELP THIS UNIT

GT8:	HLRZ	U,UNISWP##(U)	;TRY NEXT
	JUMPN	U,GT7
	HLRZ	U,SWPUNI##	;NO GOOD, MUST FRAGMENT ACROSS UNITS
	PUSHJ	P,DODELE##	;DELETE ALL DORMANT SEGS ON 1ST UNIT
	  JFCL			;PROBABLY WONT MAKE IT
	JRST	FOUND1		;GET AS MUCH AS POSSIBLE ON THIS UNIT.
				;FOUND1 WILL MOVE TO NEXT UNIT IF NECESSARY

;SUBROUTINE TO RESET U TO THE FIRST UNIT IN CLASS (P1)

FNDFUC:	MOVEI	U,SWPUNI##-UNISWP##
FNDFU1:	HLRZ	U,UNISWP##(U)	;NEXT UNIT IN ASL
	LDB	T2,UNYCFS##	;SWAPPING CLASS
	CAIE	T2,(P1)		;FIRST UNIT IN THIS CLASS?
	JRST	FNDFU1		;NO, LOOK AT THE NEXT UNIT
	POPJ	P,		;YES, RETURN U
;HERE IF CONTIGUOUS SPACE AVAILABLE ON UNIT WHOSE ADDR IS IN U
;T2  = FIRST LOGICAL PAGE NUMBER, P2=T1=NUMBER NEEDED

FOUND:	CAILE	P2,777		;ONLY 9 BITS TO STORE # BLOCKS IN SWPLST
	JRST	FOUND1		;SO FRAGMENT REQUEST IF MORE NEEDED
	PUSH	P,T2
	PUSHJ	P,FNDU		;FIND U IN SWPTAB
	.CREF	JBTSWP
	DPB	T2,[POINT 3,(P),17] ;STORE IT
	.CREF	JBYSUN
	LDB	T2,[POINT 18,(P),35] ;K NUMBER
	.CREF	JBYLKN
	PUSHJ	P,MRKALC	;MARK AS ALLOCATED
	JRST	SPCEX		;SET T1 AND OK RETURN FROM SWPSER
;HERE IF ROOM BUT HAVE TO FRAGMENT

FOUND1:	MOVEI	T2,1
	CAIE	P2,1		;CAN'T FRAGMENT 1 PAGE
	PUSHJ	P,GET4WD##	;GET 4 FREE LOCS
IFE FTXMON,<
	  POPJ	P,		;CANT - ABORT
>
IFN FTXMON,<
	JRST	RPOPJ##		;ABORT
>
	SETZM	3(T1)		;ENSURE THAT THE LINK-WORD IS 0
	MOVE	P3,T1		;P3=ADDR OF CORE BLOCKS
	TLO	T1,FRGSEG	;MARK AS FRAGMENTED
	PUSH	P,T1		;SAVE ADDR
	HRLI	P3,-4		;KEEP POINTER TO FREE CORE
FND11:	MOVE	T3,P2		;T3=SPACE STILL NEEDED
	MOVE	T1,T3
	PUSHJ	P,FNDU		;FIND U IN SWPTAB
	HRR	P4,T2		;SAVE INDEX IN P4, DON'T WIPE OUT LH BITS
FND12:	CAILE	T1,777		;ONLY GET 777 PAGES IN 1 REQUEST
	MOVEI	T1,777		; SINCE ONLY 9 BITS IN SWPLST
	PUSHJ	P,GXSAT
	  JRST	FND14		;DIDN'T MAKE IT, T1=SPACE AVAILABLE
FND13:	SETZM	(P3)		;CLEAR JUNK
	DPB	T1,FRGCP3##	;AMOUNT ALLOCATED
	DPB	T2,FRGAP3##	;FIRST LOGICAL PAGE NUM
	PUSHJ	P,MRKALC	;MARK AS ALLOCATED
	DPB	P4,FRGUP3##	;SET UNIT
	PUSHJ	P,BMPAC3
	SUBB	T3,T1		;DECREMENT AMOUNT NEEDED, PUT IN T1
	JUMPG	T1,FND12	;STILL NEED MORE
	SETZM	(P3)		;END UP WITH A ZERO
SPCEX:	HLRZ	U,UNISWP##(U)	;NEXT UNIT IN LIST
	TLNE	P4,(PG.SLO)	;SLOW SWAPPING ALLOCATION?
	JRST	SPCEX1		;YES, LEAVE JXTSUN AS IS
	LDB	T1,UNYCFS##	;CLASS TO WHICH THE UNIT BELONGS
	SKIPE	U		;END OF THE CHAIN?
	CAILE	T1,(P1)		;NO, IF NEXT UNIT IS IN A HIGHER CLASS, OR
	HLRZ	U,SWPUNI##	; OR END OF CHAIN, START OVER NEXT TIME
	HRLM	U,NXTSUN##	;STORE FOR NEXT ALLOCATOR
SPCEX1:	POP	P,T1		;RESET T1 FOR EXIT
	SKIPLE	J		;STORE IN JBTSWP TOO?
	MOVEM	T1,JBTSWP##(J)
IFN FTXMON,<
	POP	P,R		;RESTORE R
>
	JRST	CPOPJ1##

FND14:	JUMPE	T1,NXUN		;JUMP IF NO MORE ROOM THIS UNIT
FND15:
	PUSHJ	P,GXSAT		;GET THAT MUCH SPACE
	  STOPCD	.,STOP,SSD,	;++SWAP SPACE DISAPPEARED
	JRST	FND13
;HERE IF FILLED CURRENT UNIT AND NEED MORE SPACE
; (ONLY IF FORCED TO FRAGMENT OVER UNITS)

NXUN:	HLRZ	U,UNISWP##(U)	;NEXT SWAPPING UNIT
	SKIPN	U
	STOPCD	.,STOP,SRO,	;STOP IF NO MORE UNITS - SPACE RAN OUT
	MOVE	P2,T3		;P2=NUMBER 1K BLOCKS STILL NEEDED
	PUSHJ	P,DODELE##	;DELETE AS MUCH AS YOU CAN
	  JFCL			;MAY NOT BE ENOUGH YET
	JRST	FND11		;RIGHT ON

;SUBROUTINE TO FIND ADDR CONTAINED IN U IN SWPTAB
;ARGS	U=ADDRESS OF A UNIT DATA BLOCK
;CALL	MOVEI	U,ADDR
;	PUSHJ	P,FNDU
;	RETURN - T2 SET UP.  ADDR MUST BE IN THE TABLE
;VALUE	T2=INDEX IN SWPTAB OF UNIT IN U

FNDU:	SETZ	T2,
	CAME	U,SWPTAB##(T2)
	AOJA	T2,.-1
	POPJ	P,
;SUBROUTINE TO MARK BLOCKS ALLOCATED IN A UNIT'S SWAPPING AREA
;ARGS	T1=HOW MANY TO ALLOCATE
;	T2=1ST TO ALLOCATE
;PRESERVES T3,T1

MRKALC:	PUSH	P,T1
	PUSH	P,T3
	SUBM	T1,UNIFKS##(U)	;DECREMENT FREE J FOR SWAPPING
	MOVNS	UNIFKS##(U)	;COMES OUT NEGATIVE THAT WAY
	IDIVI	T2,^D36		;T2=FULL WORDS, T3=BITS IN PARTIAL WORD
	HRRZ	T4,UNIPTR##(U)
	ADD	T4,T2		;COMPUTE ADDR OF 1ST BIT
	MOVEI	T2,^D36
	SUB	T2,T3		;36-POSITION IN WORD=DESIRED QUANTITY
	HRL	T4,T2		; IN LH OF T4
	MOVE	T3,T1		;T3=HOW MANY
IFN FTXMON,<
	LDB	R,UNYSNS##	;SECTION NUMBER CONTAINING THE SATS
	MOVSS	R		;MAKE AN ADDRESS
	TLO	T3,RELABP	;ADDRESS IS RELATIVE TO THE SAT
>
	PUSHJ	P,CSETOS##	;MARK ONES
	POP	P,T3
	JRST	TPOPJ##		;RESTORE T1 AND RETURN

;SUBROUTINE TO STEP P3 TO NEXT LOCATION OF TABLE BEING BUILT


BMPGET:	MOVEI	T2,1
	PUSHJ	P,GET4WD##	;GET 4 MORE CELLS
	  SOJA	P3,UNDD		;ABORT
	SETZM	3(T1)		;CLEAR THE LINK-WORD
	HRLI	P3,-4
	CAIN	T1,(P3)		;ARE THEY CONTIGUOUS ?
	JRST	BMPACX		;YES, RETURN.
	MOVE	T2,-1(P3)	;NO, CONVERT LAST GOOD LOCATION
	HRROM	T1,-1(P3)	; TO A POINTER TO NEXT PART OF TABLE
	MOVEM	T2,(T1)		;STORE GOOD DATA IN FIRST WORD OF NEW PART
	HRR	P3,T1		;NEW TABLE LOC
	JRST	BMPACL
BMPAC3:	PUSH	P,T1
	PUSH	P,T3
BMPACL:	AOBJP	P3,BMPGET	;COUNT WORD AND RETURN
	JRST	BMPACX

UNDD:	LDB	T1,FRGAP3##	;RETURN LAST CHUNK OF SWAP SPACE
	LDB	U,FRGCP3##
	SETZM	(P3)		;AND CLEAR
	PUSHJ	P,FXSAT1	; END OF LIST MARKER
	MOVE	T1,-3(P)	;JBTSWP WORD
	PUSHJ	P,FXSAT		;RETURN SWAPPING SPACE
	POP	P,T1		;***THROW AWAY SO THAT EXIT EXITS SWAPPER
	POP	P,(P)		;MORE JUNK
IFN FTXMON,<
	MOVE	R,-2(P)		;RESTORE R IN CASE SOMEONE CARES
	POP	P,(P)		;MORE JUNK
>
BMPACX:	POP	P,T3
	JRST	TPOPJ##		;EXIT
;SUBROUTINE "GXSAT" IS CALLED TO FIND A SERIES OF CONSECUTIVE FREE BLOCKS ON 
; THE DISK TO SWAP SOME JOB OUT ONTO.  IT IS CALLED AT CLOCK LEVEL.

;ARGS	U=ADDRESS OF UNIT DATA BLOCK TO CHECK
;	T1=NUMBER 1K BLOCK NEEDED
;VALUES	T1=NUMBER 1K BLOCKS CAN ALLOCATE (BIGGEST HOLE IF LESS THAN REQUEST)
;	T2=1ST LOGICAL PAGE NUM IF REQUEST CAN BE SATISFIED
;CALLING SEQUENCE ---
;	MOVEI	T1,1K BLOCKS NEEDED
;	MOVEI	U,ADDR
;	PUSHJ	P,GXSAT
;	ERROR EXIT -- THE DISK IS FULL, NO SWAPPING SPACE AVAILABLE.
;	NORMAL EXIT
;ACCUMULATORS T4, T1, T2 ARE DESTROYED BY THIS SUBROUTINE.

GXSAT::	PUSH	P,T3		;THIS ROUTINE SAVES AND RESTORES ACCUMULATOR "T3".
	MOVE	T3,T1
	MOVE	T1,UNIPTR##(U)	;AOBJN POINTER TO SWAPPING SAT TABLES
	SETZ	T2,
	MOVE	T4,UNIUST##(U)	;IF NO NEW ACCESSES FOR THIS UNIT,
	TLNE	T4,UNPNNA##+UNPRSS##
	JRST	GXSAT1		;CANT GET ANY SPACE ON IT

IFN FTXMON,<
	LDB	R,UNYSNS##	;GET SECTION NUMBER FOR SATS
	MOVSS	R		;MAKE INTO A RELOCATION ADDRESS
	TLO	T3,RELABP	;SAT POINTER IS RELATIVE TO THE SECTION
>
	PUSHJ	P,CLGETZ##	;CALL ROUTINE IN FILSER TO SEARCH FOR 0 BITS
	  JRST	GXSAT1		;NOT ENOUGH
	AOS	-1(P)		;OK, SKIP RETURN
IFN FTXMON,<
	HRRZS	T3		;CLEAR RELABP
>
	HRRZ	T1,UNIPTR##(U)	;COMPUTE LOGICAL PAGE NUM FROM POSITION IN TABLE
	MOVEI	T2,1(T4)
	SUB	T2,T1		;FULL WORDS FROM BEGINNING OF TABLE+1
	IMULI	T2,^D36		;TIMES 36 BITS
	HLRZ	T1,T4
	SUB	T2,T1		;-POSITION IN WORD
	SKIPA	T1,T3
GXSAT1:	MOVE	T1,T2
	JRST	T3POPJ##	;RESTORE T3
;SUBROUTINE "FXSAT" IS CALLED TO RETURN A SERIES OF CONSECUTIVE DISK BLOCKS TO
; THE FREE STORAGE POOL, THUS MAKING THEM AVAILABLE FOR RE-USE IN HANDLING
; FUTURE SWAPPING REQUESTS.  IT IS CALLED AT CLOCK LEVEL.
;CALLING SEQUENCE ---
;	PUSHJ	P,FXSAT
;	NORMAL EXIT
;ENTRY CONDITIONS ---
;	C(T1) = LOGICAL BLOCK NUMBER OF THE FIRST DISK BLOCK IN THE 
;		SERIES WHICH IS TO BE MADE AVAILABLE.
;	C(U) = NUMBER OF CONSECUTIVE 1K BLOCKS OF DISK SPACE WHICH 
;		ARE TO BE MADE AVAILABLE.
;EXIT CONDITIONS ---
;	THE REQUESTED BITS IN THE SWAPPING SPACE AVAILABILITY TABLE  
;		(NAMELY, SWPTAB) HAVE BEEN CLEARED TO ZERO.
;ACCUMULATORS U, T1, T2, ARE DESTROYED BY THIS SUBROUTINE.


FXSAT::	TLZN	T1,FRGSEG	;FRAGMENTED ?
	JRST	FXSAT1		;NO, NO HASSLE HERE
	PUSHJ	P,SAVE2##	;SAVE P1
FRAGBK:	HRRZ	P2,T1		;YES, LOC OF TABLE IN P1
FRGBK1:	HRRZ	P1,P2
	SKIPG	(P1)		;NEXT POINTER?
	JRST	FRGBK2		;OR DONE?
	LDB	T1,FRGAP1##	;GET ADDRESS
	LDB	U,FRGCP1##	;AND SIZE
	PUSHJ	P,FXSAT1	;GIVE UP THE DISK SPACE FOR THIS PART
	AOBJP	P2,FRGBK1	;COUNT WORD OF TABLE, GET NEXT
FRGBK2:	HRRZ	T2,P2		;LOC OF TABLE
	HLRZ	T1,P2		;T1=NUMBER OF WDS IN TABLE
	SUB	T2,T1		;T2=1ST WORD OF BLOCK
	LSH	T1,-2		;T1=NUMBER WORDS-1
	AOS	T1		;CONVERT TO NUMBER OF 4 WORD BLOCKS
	MOVE	P2,(P1)
	PUSHJ	P,GIV4WD##	;GIVE UP FREE CORE
	SKIPE	T1,P2		;END OF TABLE ?
	JRST	FRAGBK		;NO, GO CHASE NEXT PART
	POPJ	P,		;YES, DONE

FXSAT1::SKIPN	T2,U		;T2=NUMBER 1K BLOCKS TO RETURN
	POPJ	P,		;THERE AREN'T REALLY ANY (DUMMY SWPLST ENTRY
				;FOR NZS)
	LDB	U,SSUNT1##	;GET INDEX OF UNIT IN SWPTAB
	SKIPG	U,SWPTAB##(U)	;GET ADDR OF UNIT DATA BLOCK
	POPJ	P,		;UNIT WAS REMOVED

	EXCH	T1,T2		;T1=HOW MANY, T2=START LOC
	HRRZS	T2		;CLEAR OUT UNIT INDEX
	.CREF	SSUNT1		;(REFERENCE UNIT VALUE)
;	PJRST	CSETZS		;CLEAR BITS AND INCREMENT UNIFKS
;SUBROUTINE TO MARK 0'S IN SWAPPING SAT TABLE
;ARGS	T1=HOW MANY
;	T2=1ST LOGICAL PAGE NUMBER
;CLOBBERS T3,T4

CSETZS:
	MOVE	T3,UNIUST##(U)	;IF NO NEW ACCESSES FOR THIS UNIT (GOING DOWN SOON),
	TLNN	T3,UNPNNA##+UNPRSS##  ; DONT CHANGE UNIFKS (=0)

	ADDM	T1,UNIFKS##(U)	;INCREMENT COUNT OF FREE PAGES FOR SWAPPING
	IDIVI	T2,^D36		;GET FULL WORDS IN TABLE
	HRLS	T2		;BOTH HALVES
	ADD	T2,UNIPTR##(U)	;POINTER TO FIRST WORD TO MODIFY
IFE FTXMON,<
	PJRST	SETZRS##
>
IFN FTXMON,<
	PUSHJ	P,SSEC1##	;CAN'T ADDRESS SWAPPING SATS IN SECTION 0
	PUSH	P,R		;SOMEONE MAY CARE
	PUSH	P,P3		;TO INDICATE AOBJN POINTER RELATIVE TO TABLE
	MOVSI	P3,RELABP	;(R) + (T2)
	LDB	R,UNYSNS##	;SECTION NUMBER FOR SWAPPING SATS
	MOVSS	R		;RELOCATION BY ADDRESS WITHIN SECTION
	PUSHJ	P,SETZRP##	;ZERO THE BITS TABLE RELATIVE
	POP	P,P3		;RESTORE P3
	POP	P,R		;AND R
	POPJ	P,		;RETURN
>


;DATA ASSOCIATED WITH THE SWPSER LOGIC ---

	$LOW

SQREQ::	Z		;C(LH)=NEGATIVE OF SIZE OF READ/WRITE
			; C(RH)=LOCATION OF FIRST WORD TO READ/WRITE

	$HIGH


	$LIT

SWPEND:	END