Google
 

Trailing-Edge - PDP-10 Archives - decuslib10-08 - 43,50501/frecor.mac
There are 5 other files named frecor.mac in the archive. Click here to see a list.
	TITLE	FRECOR	DATA STORAGE IN FREE CORE FOLLOWING USER MEMORY
	SUBTTL	ERNIE PETRIDES, WESLEYAN UNIVERSITY, JANUARY, 1979


;IMPORTANT INFORMATION FOR THE USER:
;		IF HIGH SEGMENT DATA STORAGE IS USED FOR SHARABLE
;	PROGRAMS, THE PROGRAMMER MUST BUILD IN A STORAGE MODIFI-
;	CATION INTERLOCK TO PREVENT MORE THAN ONE JOB EXECUTING
;	THESE ROUTINES SIMULTANEOUSLY !!!  ALSO, THESE ROUTINES
;	REQUIRE A MINIMUM USEABLE STACK DEPTH OF 5 AND CAN USE A
;	MAXIMUM OF UP TO 11 LEVELS.  FOLLOWING IS A DESCRIPTION OF
;	THE ARGUMENTS PASSED IN AC 16:
;
;	ROUTINE		SENT				RETURNED
;	 SAV	DATA LENGTH,,DATA ADDRESS	DATA LENGTH,,STORAGE ADR
;	 SHR	DATA LENGTH,,DATA ADDRESS	DATA LENGTH,,STORAGE ADR
;	 DEL	(IGNORED),,STORAGE ADDRESS	0,,SIZE OF DELETED SPACE
;	 ZER	DO HIGH CORE,,DO LOW CORE	DELETIONS IN HIGH,,IN LOW


	SUBTTL	DEFINITIONS AND PARAMETERS

	TWOSEG
	SALL

	ENTRY	FC$SAV,FC$SHR,FC$DEL,FC$ZER
	EXTERN	.JBREL,.JBHRL,.JBFF,.JBHGH,.JBHRN

	T1==1		;GETS RIGHT ARG (ALWAYS PRESERVED)
	T2==2		;GETS LEFT ARG (ALWAYS PRESERVED)
	T3==3		;SCRATCH AC (ALWAYS PRESERVED)
	A==16		;ARGUMENT PASSER (NEGATIVE RETURN ==> ERROR)
	P==17		;PUSH DOWN STACK POINTER


	SUBTTL	INTERNAL STORAGE

LFCP::	EXP	0	;LOW SEGMENT FREE-CORE POINTER
SHARED:	EXP	0	;FLAG TO SHOW LOW OR HIGH SEGMENT WORK

	RELOC	400000	;ALL THE REST GOES IN THE HIGH SEGMENT

HFCP::	EXP	0	;HIGH SEGMENT FREE-CORE POINTER
	SUBTTL	SUBROUTINE ENTRY PROCEDURE AND ERROR HANDLING

;THIS SETUP IS DONE FOR EACH FC SUBROUTINE ENTRY
SETUP:	EXCH	T3,(P)			;SAVE TEMP AND GET ROUTINE RTRN ADR
	PUSH	P,T2			;SAVE A SECOND TEMP
	PUSH	P,T1			;SAVE THE FIRST TEMP
	HRRZ	T1,A			;PICK UP RIGHT HALF OF ARGUMENT
	HLRZ	T2,A			;AND PICK UP LEFT HALF
	PUSHJ	P,(T3)			;DO THE APPROPRIATE ROUTINE
	POP	P,T1			;RESTORE THE FIRST TEMP
	POP	P,T2			;THE SECOND ONE
	POP	P,T3			;AND THE THIRD ONE
	POPJ	P,			;RETURN TO USER'S PROGRAM


DEFINE	ERRMAC
	<ITEM	CEF,<Core expansion failure>
	ITEM	ISA,<Illegal to store from accumulator>
	ITEM	ZLD,<Attempt to store zero length data>
	ITEM	IDA,<Illegal delete address>
	ITEM	DFZ,<Internal delete failure on "zero">>

DEFINE	ITEM (PFX,MSG)
<PFX'ERR: JSP	A,ERRORS
	ASCIZ/? FCR'PFX  MSG in free-core routines/>
	ERRMAC		;SET UP TABLE OF ERROR BRANCHES AND MESSAGES

;HERE ON ALL ERRORS
ERRORS:	HRROI	A,(A)		;LOAD POINTER TO MESSSAGE AND ERROR MARKER
	POPJ	P,		;AND RETURN TO SUBROUTINE ENTRY PROCEDURE
	SUBTTL	FREE-CORE ROUTINES -- SAV,SHR

;HERE TO PUT DATA IN LOW SEGMENT FREE-CORE FOR SAVING
FC$SAV:	PUSHJ	P,SETUP			;FIRST DO THE SETUP ROUTINE
	SETZM	SHARED			;SHOW WE'RE WORKING ON LOWSEG
	MOVEI	A,LFCP			;LOAD ADDRESS OF INITIAL FC PNTR
	JRST	FCPUT			;DO SAME PUT ROUTINE AS SHR

;HERE TO PUT DATA IN HIGH SEGMENT FREE-CORE FOR SHARING
FC$SHR:	PUSHJ	P,SETUP			;DO THE STANDARD SETUP
	SETOM	SHARED			;SHOW WE'RE WORKING ON HISEG
	MOVEI	A,HFCP			;LOAD ADDRESS OF INITIAL FC PNTR
					;FALL THROUGH TO PUT ROUTINE

;HERE TO PUT DATA IN FREE-CORE ON SAV OR SHR
FCPUT:	CAIGE	T1,20			;IF DATA ADDRESS IS IN AC'S,
	  JRST	ISAERR			;  THEN IT'S AN ILLEGAL ADR
	JUMPLE	T2,ZLDERR		;ERROR IF ZERO LENGTH DATA
	HRRZ	T3,(A)			;IF THERE'S NO FIRST LINK,
	JUMPE	T3,FCNEW		;  THEN ADD A NEW ENTRY
;HERE TO SEARCH THROUGH LINKED LIST (A POINTS TO LAST ENTRY)
FCSEA:	HRRZ	A,(A)			;LOAD LINK TO NEXT FREE-CORE ENTRY
	HLRE	T3,(A)			;LOAD THE ENTRY'S LENGTH FROM LEFT
	ADDI	T3,(T2)			;ADD IN THE REQUESTED DATA LENGTH
	JUMPLE	T3,FCOLD		;RECLAIM ENTRY IF BIG ENOUGH DELETION
	HRRZ	T3,(A)			;ELSE LOAD ITS LINK TO NEXT ENTRY
	JUMPN	T3,FCSEA		;AND CONTINUE SEARCH IF IT EXISTS
;HERE TO MAKE NEW FREE-CORE ENTRY AT END OF LIST (A POINTS TO LAST ENTRY)
FCNEW:	PUSHJ	P,FCGET			;GET T2+1 END SPACE AND RETURN LOC
	HRRM	T3,(A)			;LINK NEW ENTRY TO FORMER ENTRY
	MOVEI	A,(T3)			;PUT OUR NODE ADDRESS IN A
	HRLZM	T2,(A)			;LOAD ENTRY SIZE AND ZERO LINK
	JRST	FCSTR			;TRANSFER DATA SAME AS BELOW ROUTINE
;HERE TO INSERT DATA IN DELETED ENTRY SPACE (A POINTS TO DELETED ENTRY)
FCOLD:	AOJG	T3,FCOLD1		;NO ENTRY DIVISION IF SIZES MATCH
	PUSH	P,A			;ELSE SAVE NODE POINTER ON STACK
	PUSH	P,(A)			;AND SAVE OUR NODE HEADER WORD
	ADDI	A,1(T2)			;CALCULATE ADR OF CREATED NODE
	POP	P,(A)			;PUT OUR NODE HEADER THERE
	HRLM	T3,(A)			;BUT USE ITS OWN LENGTH (<=0)
	HRRZM	A,@(P)			;PUT LINK TO CREATED NODE IN OURS
	POP	P,A			;RESTORE OUR NODE POINTER TO A
FCOLD1:	HRLM	T2,(A)			;LOAD OUR DATA LENGTH INTO NODE
					;FALL THROUGH TO STORE THE DATA
;HERE TO STORE DATA INTO FREE-CORE ENTRY POINTED TO BY A
FCSTR:	HRLI	A,(T2)			;PUT DATA LENGTH INTO RETURN ARG
	ADDI	T2,(A)			;CALCULATE FINAL DATA ADR
	AOJ	A,			;POINT TO START OF DATA
	HRLZS	T1			;PUT RETRIEVAL ADR IN LEFT
	HRRI	T1,(A)			;AND DESTINATION IN RIGHT
	BLT	T1,(T2)			;BLOCK TRANSFER THE STUFF
	POPJ	P,			;AND RETURN TO EXIT ROUTINE


;SUBROUTINE TO ACQUIRE FREE SPACE AT END OF SEGMENT POSSIBLY EXPANDING CORE
;CALL WITH:
;	SETXM	SHARED		;TO TELL IF HIGH OR LOW SEGMENT
;	MOVE	T2,<LENGTH OF REQUEST - 1>
;	PUSHJ	P,FCGET
;	RETURN IS HERE WITH STORAGE LOCATION IN T3
;	(NEVER RETURNS IF ERROR ON CORE UUO)
;
FCGET:	SKIPE	SHARED			;IF THIS IS A HISEG REQUEST,
	  JRST	FCGET2			;  THEN DO SPECIAL OTHER STUFF
	HRRZ	T3,.JBFF		;LOAD ADR OF FIRST FREE IN LOWSEG
	ADDI	T3,1(T2)		;CALCULATE REQUESTED FRIRST FREE
	CAMG	T3,.JBREL		;SEE IF THERE'S ENOUGH ROOM IN CORE
	  JRST	FCGET1			;YES--NO NEED TO EXPAND
	CORE	T3,			;NO--ASK MONITOR TO EXPAND LOWSEG
	  JRST	FCGET5			;(CORE ERROR)
	HRRZ	T3,.JBFF		;RELOAD THE FIRST FREE ADR
	ADDI	T3,1(T2)		;AND RE-CALCULATE REQUESTED
FCGET1:	EXCH	T3,.JBFF		;STORE NEW VALUE IN JOB DATA
	POPJ	P,			;AND RETURN WITH OLD IN T3
FCGET2:	HLRZ	T3,.JBHGH+.JBHRN	;LOAD HIGH SEGMENT LENGTH
	ADDI	T3,.JBHGH+1(T2)		;CALCULATE NEEDED FIRST FREE
	PUSH	P,T3			;SAVE REQUEST ON THE STACK
	HRRZ	T3,.JBHRL		;LOAD MOST RECENT WE KNOW ABOUT
	CAML	T3,(P)			;SEE IF ALREADY ENOUGH ROOM
	  JRST	FCGET3			;YES--NO NEED TO EXPAND
	HRLZ	T3,(P)			;NO--LOAD REQUESTED VALUE
	CORE	T3,			;ASK MONITOR TO EXPAND HISEG
	  JRST	FCGET4			;(TOO BAD)
FCGET3:	POP	P,T3			;RESTORE REQUESTED FIRST FREE
	SUBI	T3,.JBHGH		;CONVERT ADR TO SEGMENT LENGTH
	HLL	T3,.JBHGH+.JBHRN	;LOAD PREVIOUS HISEG LENGTH
	HRLM	T3,.JBHGH+.JBHRN	;STORE NEW VALUE IN JOB DATA
	HLRZS	T3			;PUT OLD LENGTH IN RIGHT
	ADDI	T3,.JBHGH		;AND CONVERT BACK TO ADR
	POPJ	P,			;RETURN WITH STORAGE ADR IN T3
FCGET4:	POP	P,(P)			;HERE ON HISEG EXPANSION FAILURE
FCGET5:	POP	P,(P)			;HERE ON LOWSEG EXPANSION FAILURE
	JRST	CEFERR			;RESET STACK POINTER AND DO ERROR
	SUBTTL	FREE-CORE ROUTINES -- DEL

;HERE TO DELETE ENTRY FROM FREE-CORE
FC$DEL:	PUSHJ	P,SETUP			;DO THE SETUP PROCEDURE
	MOVEI	A,LFCP			;ASSUME WE'LL DO LOWSEG
	CAIL	T1,.JBHGH		;BUT IF IT'S A HISEG ADR,
	  MOVEI	A,HFCP			;  THEN DO THE HISEG DELETE
FCDEL1:	MOVEI	T3,(A)			;HERE TO CONTINUE LIST SCAN
	HRRZ	A,(A)			;LOAD ADDRESS OF NEXT NODE
	JUMPE	A,IDAERR		;ERROR IF NO MORE IN LIST
	CAIE	A,-1(T1)		;SEE IF NODE ADR IS THAT OF DATA
	  JRST	FCDEL1			;LOOP BACK IF NOT FOUND YET
;HERE WHEN FOUND NODE TO DELETE (POINTED TO BY A)
	HLRE	T1,(A)			;LOAD NODE'S LENGTH FROM LEFT
	JUMPLE	T1,IDAERR		;ERROR IF ZERO OR ALREADY DELETED
	PUSH	P,T3			;SAVE ADDRESS OF PRECEDING NODE
	MOVNS	T1			;NEGATE ENTRY'S LENGTH SPEC
	HRLZI	T2,(T1)			;ALSO PUT INTO LEFT OF T2
	HRRI	T2,1(A)			;AND MAKE AN AOBJ POINTER
	SETZM	(T2)			;CLEAR OUT DELETED DATA
	AOBJN	T2,.-1			;LOOP UNTIL ALL WORDS DONE
;HERE TO CHECK FOR FORWARD CONCATENATION
	HRRZ	T2,(A)			;LOAD ADR OF NEXT LINK
	JUMPE	T2,FCDEL2		;NOTHING CAN DO IF NOT THERE
	HLRE	T3,(T2)			;LOAD ITS STORAGE SPEC
	JUMPG	T3,FCDEL2		;CAN'T DO IT IF IT'S GOT DATA
	MOVEI	T3,(T2)			;RELOAD NEXT LINK'S ADR
	ADD	T3,T1			;ADD OUR NEGATIVE LENGTH
	CAIE	T3,1(A)			;IF WE'RE NOT CONTIGUOUS,
	  JRST	FCDEL2			;  THEN SKIP FORWARD ATTEMPT
	MOVE	T3,(T2)			;ELSE LOAD ITS HEADER WORD
	SETZM	(T2)			;AND CLEAR ITS HEADER HEADER
	HRRM	T3,(A)			;USE ITS LINK FOR OURS
	HLRES	T3			;GET ITS NEGATIVE LENGTH
	ADD	T1,T3			;TOTAL OUR NEGATIVE LENGTH
	SOJ	T1,			;INCLUDING GAINED HEADER WORD
FCDEL2:	HRLM	T1,(A)			;PUT LENGTH IN OUR HEADER
;HERE TO CHECK FOR BACKWARD CONCATENATION
	POP	P,T2			;UNLOAD ADR OF PRECEDING NODE
	CAIE	T2,LFCP			;IF IT'S THE LOW FC POINTER,
	CAIN	T2,HFCP			;OF IT'S THE HIGH FC POINTER,
	  JRST	FCDEL3			;  THEN CAN'T DO IT BACKWARDS
	HLRE	T3,(T2)			;LOAD ITS LENGTH SPECIFICATION
	JUMPG	T3,FCDEL3		;CAN'T DO IT IF HAS DATA IN IT
	ADDI	T3,(A)			;ADD IN ADDRESS OF OUR NODE
	CAIE	T3,1(T2)		;IF WE'RE NOT CONTIGUOUS,
	  JRST	FCDEL3			;  THEN THERE'S NOTHING TO DO
	HRL	A,(A)			;ELSE LOAD OUR LINKAGE POINTER
	HLRM	A,(T2)			;IN PLACE OF ITS LINKAGE POINTER
	SETZM	(A)			;ZERO OUR ENTRY HEADER WORD
	HLRE	T3,(T2)			;RELOAD ITS LENGTH SPEC
	ADD	T1,T3			;TOTAL OUR DELETED LENGTHS
	SOJ	T1,			;AND DON'T FORGET EXTRA HEADER
	HRLM	T1,(T2)			;PUT LENGTH IN ITS HEADER
;HERE TO EXIT FROM FREE-CORE DELETE ROUTINE
FCDEL3:	MOVN	A,T1			;RETURN SIZE FREED BY DELETION
	POPJ	P,			;AND RETURN TO EXIT PROCEDURE
	SUBTTL	FREE-CORE ROUTINES -- ZER

;HERE TO DELETE ALL ENTRIES IN FREE-CORE POSSIBLY CONTRACTING CORE
FC$ZER:	PUSHJ	P,SETUP			;DO THE SETUP PROCEDURE
	SETZM	SHARED			;INIT AS COUNTER AND FLAG
	SKIPE	T2			;IF HISEG ZERO REQUESTED,
	  HRROS	SHARED			;  THEN FLAG FOR LATER
	JUMPE	T1,FCZER1		;DON'T DO LOWSEG IF NOT REQUESTED
	MOVEI	T1,LFCP			;LOAD ADDRESS OF LOWSEG FC PNTR
	PUSHJ	P,FCZSUB		;CALL DELETE SUB FOR STRANGE WORK
	  JRST	FCZER1			;ERROR RETURN MEANS NO STRUCTURE
	HLRE	T1,(T3)			;LOAD NEG LENGTH OF LAST ENTRY
	ADD	T1,.JBFF		;BACK UP ENTRY SIZE FROM END
	CAIE	T1,1(T3)		;IF ENTRY NOT AT END OF LOWSEG,
	  JRST	FCZER1			;  THEN NOTHING WE CAN DO
	HLLZS	(T2)			;ELSE MAKE PREVIOUS LINK LAST
	SETZM	(T3)			;CLEAR THIS HEADER WORD
	MOVEM	T3,.JBFF		;LOAD NEW FIRST FREE INTO JOBDAT
	HRRZ	T2,.JBREL		;LOAD HIGHEST LEGAL LOWSEG ADR
	TRZ	T2,1777			;CALCULATE LOWEST ADR IN LAST K
	CAIG	T2,(T3)			;IF NEW FF IS IN THE LAST CHUNK,
	  JRST	FCZER1			;  THEN AVOID USELESS CORE UUO
	CORE	T3,			;OTHERWISE, CONTRACT THE LOWSEG
	  JFCL				;IGNORE ANY ERRORS
;HERE WHEN DONE CHECKING LOW SEGMENT
FCZER1:	HLLZ	T1,SHARED		;LOAD HISEG ZERO INDICATOR
	HRLZS	SHARED			;SWAP AND INIT DELETION COUNTS
	JUMPE	T1,FCZER2		;DON'T ZERO HISEG IF NOT REQUESTED
	MOVEI	T1,HFCP			;ELSE LOAD ADR OF HISEG FC PNTR
	PUSHJ	P,FCZSUB		;DO SUB FOR DELETES AND END SEARCH
	  JRST	FCZER2			;ERROR RETURN MEANS NO STRUCTURE
	HLRE	T1,(T3)			;LOAD NEG LENGTH OF LAST ENTRY
	HLRZ	A,.JBHGH+.JBHRN		;LOAD CURRENT HISEG LENGTH
	ADDI	A,.JBHGH(T1)		;BACK UP ENTRY SIZE FROM END
	CAIE	A,1(T3)			;IF ENTRY NOT AT END OF HISEG,
	  JRST	FCZER2			;  THEN NOTHING WE CAN DO
	HLLZS	(T2)			;ELSE MAKE PREVIOUS LINK LAST
	SETZM	(T3)			;CLEAR THIS HEADER WORD
	MOVEI	T2,-.JBHGH(T3)		;PUT NEW HISEG LENGTH IN T2
	HRLM	T2,.JBHGH+.JBHRN	;AND STORE IT INTO HISEG JOBDAT
	HLRZ	T2,.JBHRL		;LOAD MOST RECENT HISEG LIMIT
	TRZ	T2,1777			;CALCULATE LOWEST ADR IN LAST K
	CAIG	T2,(T3)			;IF OUR NEW FF IS IN SAME K,
	  JRST	FCZER2			;  THEN DON'T DO USELESS UUO
	HRLZS	T2			;OTHERWISE, PUT VALUE IN LEFT
	CORE	T2,			;AND CONTRACT CORE
	  JFCL				;IGNORING ERRORS
;HERE TO EXIT FROM ZER ROUTINE
FCZER2:	MOVS	A,SHARED		;LOAD DELETION COUNTS FROM FLAG
	POPJ	P,			;AND RETURN TO EXIT ROUTINE


;SUBROUTINE TO DELETE FREE-CORE STRUCTURE WITH INITIAL POINTER IN T1
;	COUNTING SUCCESSFUL DELETIONS BY INCREMENTING "SHARED", AND
;	THEN TO SEARCH FOR END OF LIST LEAVING ADDRESS OF LAST LINK
;	IN T3 AND THE ADR OF ITS PREVIOUS LINK IN T2.  NEVER RETURNS
;	IF A DELETION ERROR IS DETECTED.
;CALL WITH:
;	MOVEI	T1,XFCP
;	PUSHJ	P,FCZSUB
;	  RETURN HERE IF NO STRUCTURE
;	RETURN HERE WITH INFO IN T3 AND T2 (AND "SHARED" MODIFIED)
;	(NEVER RETURNS ON A DELETION ERROR)
;
FCZSUB:	MOVEI	T2,(T1)			;LOAD ADDRESS OF INITIAL FC PNTR
FCSUB1:	HRRZ	T2,(T2)			;CONTINUE SCAN THROUGH LIST
	JUMPE	T2,FCSUB2		;OUT IF END OF FC LIST
	HLRE	T3,(T2)			;LOAD THIS ENTRY'S LENGTH
	JUMPLE	T3,FCSUB1		;IGNORE IT IF ALREADY DELETED
	MOVEI	A,1(T2)			;OTHERWISE, LOAD DATA ADR IN A
	PUSHJ	P,FC$DEL		;DO THE STANDARD DELETE ROUTINE
	JUMPL	A,FCSUB6		;CHECK FOR DELETION FAILURES
	AOS	SHARED			;BUMP DELETE COUNT IF OKAY
	JRST	FCZSUB			;LOOP BACK FOR RESCAN
;HERE WHEN ALL IS DELETED FOR FINAL END SEARCH
FCSUB2:	MOVEI	T2,(T1)			;RELOAD INITIAL FC PNTR ADR
	HRRZ	T3,(T2)			;LOAD ITS LINK TO NEXT ENTRY
	JUMPE	T3,FCSUB5		;NO STRUCTURE IF NOT THERE
FCSUB3:	HRRZ	A,(T3)			;LOAD NEXT NODE'S LINK TO NEXT
	JUMPE	A,FCSUB4		;DONE WHEN FOUND END OF LIST
	MOVEI	T2,(T3)			;SHIFT BACK PREVIOUS NODE
	MOVEI	T3,(A)			;SHIFT BACK THIS NODE
	JRST	FCSUB3			;CONTINUE SCAN FOR END
;HERE ARE THE EXITS FROM SUBROUTINE "FCZSUB"
FCSUB4:	AOS	(P)			;SKIP RETURN FOR SUCCESS
FCSUB5:	POPJ	P,			;PLAIN RETURN FOR NO STRUCTURE
FCSUB6:	POP	P,(P)			;NON-RETURN IF DELETION FAILURE
	JRST	DFZERR			;UNLOAD RETURN AND DO ERROR


	END