Trailing-Edge
-
PDP-10 Archives
-
decuslib20-04
-
decus/20-0131/alcor.mac
There are 10 other files named alcor.mac in the archive. Click here to see a list.
TITLE .ALCBF ALLOCATE DYNAMIC I/O BUFFERS
SEARCH UUOSYM
ENTRY .ALCBF,.FREBF
TWOSEG
RELOC 400000
T1= 1
T2= 2
T3= 3
T4= 4
P1= 5
P2= 6
P3= 7
P4= 10
P= 17
;.ALCBF -- ALLOCATE DYNAMIC I/O BUFFERS
;CALL: MOVE T1,[XWD NBUF,BUFSIZ]
; MOVE T2,[XWD OPNBLK,BFHDR]
; PUSHJ P,.ALCBF
; *RETURN*
;ACS: T1-3
.ALCBF::PUSHJ P,.SAVE3## ;SAVE P1-3
MOVE P1,T1 ;COPY NBUF,,BUFSIZ
PUSH P,T2 ;REMEMBER BUFFER HEADER ADDRESS
HLRZ T1,T2 ;GET OPEN BLOCK ADDRESS
MOVE T2,.OPDEV(T1) ;GET THE DEVICE NAME
DEVTYP T2, ;SEE WHAT IT IS
JRST ABFERR ;SHOULD NEVER HAPPEN
DEVSIZ T1, ;SEE WHAT DEFAULTS ARE FOR THIS DEV
JRST ABFERR ;SHOULD NEVER HAPPEN
TLNN P1,-1 ;IS NBUF THERE?
HLL P1,T1 ;NO--USE THE DEFAULT
TLNE T2,(TY.VAR) ;CAN DEVICE HAVE VARIABLE BUFFER SIZE?
TRNN P1,-1 ;YES--IS IT SPECIFIED?
HRRI P1,-3(T1) ;NO--USE DEFAULT
ADDI P1,3 ;COMPUTE ACTUAL BUFFER SIZE
HLRZ P2,P1 ;GET # BUFFERS
HRRZ P3,(P) ;GET "LAST BUFFER" SET UP
ALCBF1: HRRZ T1,P1 ;GET CORE BLOCK SIZE
PUSHJ P,.ALCOR## ;GET THE BLOCK
AOS T1 ;ADDRESS THE BUFFER LINK POINTERS
HRRM T1,(P3) ;FORM A RING
MOVEI T2,-2(P1) ;SIZE OF DATA AREA
HRLM T2,(T1) ;STORE IN BUFFER
MOVE P3,T1 ;MOVE ALONG THE RING
SOJG P2,ALCBF1 ;MAKE ALL REQUIRED
POP P,T2 ;GET BUFFER HEADER ADDRESS
MOVSI T3,(1B0) ;GET NOT USED BIT
HLLM T3,(T2) ;SET IT IN THE BUFFER
HRRZ T2,(T2) ;FIRST BUFFER ADDRESS
HRRM T2,(T1) ;COMPLETE THE RING
POPJ P, ;RETURN
ABFERR: OUTSTR [ASCIZ\?ABFDUF DEVSIZ/TYP UUO FAILED\]
EXIT 1,
JRST .-1 ;NO CONTINUE HERE!
;.FREBF -- RETURN BUFFERS TO FREE CORE
;CALL: MOVE T1,BUFHDR ADDRESS
; PUSHJ P,.FREBF
; *RETURN*
;ACS: T1-2
.FREBF::PUSHJ P,.SAVE2##
MOVE P1,T1 ;SAVE BUFFER HEADER ADDRESS
HRRZ P2,(P1) ;GET FIRST UFFER
HLLM P2,(P1) ;CLEAR LH OF BUFFER RING HEADER
FREBF1: MOVEI T1,-1(P2) ;ADDRESS THE CORE
HRRZ P2,(P2) ;MOVE TO NEXT BUFFER
PUSHJ P,.DECOR## ;FREE THIS BUFFER
CAME P2,(P1) ;DONE FREEING THE BUFFER?
JRST FREBF1 ;NO--DO SOME MORE
SETZM (P1) ;YES--CLEAR THE BUFFER HEADER ADDRESS
POPJ P, ;RETURN
NOSYM
PRGEND
TITLE .ALCOR DYNAMIC CORE ALLOCATION
SEARCH JOBDAT
ENTRY .ALCOR,.DECOR,.RECOR
TWOSEG
RELOC 400000
T1= 1 ;TEMPORARY
T2= 2
T3= 3
T4= 4
P1= 5 ;PRESERVED
P2= 6
P3= 7
P4= 10
P= 17
MINSIZ==3 ;MINIMUM CORE BLOCK SIZE
IFNDEF KOUNT,KOUNT==0 ;NON-ZERO FOR LOOP COUNTS
COMMENT \THE CORE IS ALLOCATED WITH A LINK WORD AT -1(T1). THE LEFT
HALF CONTAINS A WORD COUNT AND SHOULD NOT BE TOUCHED. ALL CORE
ALLOCATED BY .ALCOR WILL BE PRE-ZEROED.
\
;.ALCOR -- ALLOCATE A CORE BLOCK
;CALL: MOVE T1,WORDS
; PUSHJ P,.ALCOR
; *RETURN,T1 HAS ADDRESS*
;ACS: RETURNS ADDRESS OF CORE BLOCK IN T1
.ALCOR::JUMPLE T1,.POPJ## ;WATCH OUT FOR FUNNY CALLS
PUSHJ P,.SAVE2## ;SAVE THE PROTECTED REGISTER
PUSHJ P,.PSH4T## ;SAVE T1-4 ALSO
MOVEI P1,1(T1) ;ALLOW FOR THE LINK WORD
SKIPN SAVJFF ;HAS RECORE BEEN CALLED?
PUSHJ P,.RECOR ;NO, DO AN IMPLICIT CALL
IFN KOUNT,AOS KACALL ;COUNT THIS CALL TO ALCOR
SKIPE T4,FRE.DY ;IS THE LIST EMPTY?
JRST ALCOR1 ;NO--SKIP AHEAD
PUSHJ P,GETCOR ;YES--START THE LIST
MOVEM T4,FRE.DY ;SAVE FOR FUTURE REFERENCE
ALCOR1: MOVEI T4,FRE.DY ;INIT THE POINTER
ALCOR2: MOVE T3,T4 ;REMEMBER FROM WHENCE WE CAME
IFN KOUNT,AOS KALOOP ;COUNT LOOP THRU
HRRZ T4,(T4) ;CHAIN TO THE NEXT BLOCK
JUMPE T4,ALCOR3 ;JUMP IF AT THE END OF THE LIST
HLRZ T2,(T4) ;NO--GET BLOCK SIZE
CAML T2,P1 ;HOW DOES IT LOOK ON ME?
JRST GOTBLK ;FINE SO FAR
JRST ALCOR2 ;A LITTLE SMALL
;GET HERE WHEN NO BLOCK IS BIG ENOUGH
ALCOR3: PUSHJ P,GETCOR ;GET MORE CORE
HRRM T4,(T3) ;LINK IT INTO THE LIST
HLRZ T2,(T4) ;PICK UP THE BLOCK SIZE
HLRZ T1,(T3) ;GET THE END BLOCK SIZE
ADDI T1,(T3) ;COMPUTE END OF BLOCK
CAIE T1,(T4) ;IS IT ON THE END OF CORE?
JRST GOTBLK ;NO--SKIP AROUND
SUBI T1,(T3) ;YES--GET SIZE AGAIN
ADDI T1,(T2) ;COMPUTE SIZE OF NEW LARGER BLOCK
HRLZM T1,(T3) ;STORE SIZE AND ZERO LINK
JRST ALCOR1 ;NOW GO FIND THE NEW BLOCK
;HERE WITH A GOOD BLOCK
GOTBLK: SUB T2,P1 ;GET SIZE DIFFERENCE
IFGE MINSIZ,<CAILE T2,MINSIZ> ;CHECK FOR BLOCK TOO SMALL
JUMPN T2,TOOBIG ;JUMP IF THE BLOCK IS TOO LARGE
HRRZ T2,(T4) ;NO, IT FITS FINE, UNLINK FROM FREE LIST
HRRM T2,(T3) ;STORE LINK INTO PREVIOUS BLOCK
JRST ZERBLK ;GO CLEAR IT AND RETURN
;THE BLOCK WE FOUND WAS TOO BIG, ADJUST ALL POINTERS
TOOBIG: HRL T2,(T4) ;FORM NEW POINTER (SWAPPED)
HRLZM P1,(T4) ;STORE NEW LINK WORD (SIZE)
ADD T4,P1 ;POINT AT THE FRAGMENT
MOVSM T2,(T4) ;STORE THE LINK WORD FOR THE FRAGMENT
HRRM T4,(T3) ;STORE PTR TO FRAGMENT IN PREVIOUS BLOCK
SUB T4,P1 ;GET TO THE BLOCK AGAIN
IFN KOUNT,AOS KFRGB ;COUNT A FRAGMENTED ALLOCATION
ZERBLK: AOS T4 ;SKIP THE LINK WORD
SOS P1 ;UNCOUNT IT
MOVE T1,T4 ;SET ADDRESS FOR RETURN TO USER
SETZM (T1) ;CLEAR THE FIRST WORD
HLLZS -1(T1) ;ENSURE THAT RH OF MY WORD IS CLEAR
SOJLE P1,ACRXIT ;JUMP IF ONLY ONE WORD
HRLZ T2,T4 ;NO--FORM BLT CONTROL WORD
HRRI T2,1(T4) ;...
ADD P1,T4 ;COMPUTE END OF THE BLOCK
BLT T2,(P1) ;CLEAR THE BLOCK
ACRXIT: MOVE P1,T1 ;SAVE OVER .POP4T
PUSHJ P,.POP4T## ;RESTORE T1-4
MOVE T1,P1 ;POSITION ANSWER
POPJ P, ;RETURN TO CALLER
;CALL HERE TO GET CORE
;RETURN .POPJ WITH CORE BLOCK ADDRESS IN T4
GETCOR: MOVE T1,.JBFF ;GET END OF CORE
ADD T1,P1 ;COMPUTE WHAT WE NEED
CORE T1, ;ASK MON FOR IT
JRST NOCORE ;GO DIE
MOVE T1,.JBREL ;GET END OF CORE BOUNDARY
AOS T1 ;PUT .JBFF IN THE BOONIES (CLAIM THE WHOLE BLOCK)
MOVE T4,.JBFF ;GET CURRENT END OF CORE (START OF BLOCK)
MOVEM T1,.JBFF ;STORE NEW END OF CORE
SUB T1,T4 ;COMPUTE CHUNK SIZE
HRLZM T1,(T4) ;STORE LINK WORD FOR THIS NEW BLOCK
POPJ P, ;TAKE 'GOT NEW CORE' RETURN
NOCORE: OUTSTR [ASCIZ\?ACRNEC NOT ENOUGH CORE\]
EXIT 1, ;EXIT QUIETLY
JRST GETCOR ;GO TRY AGAIN ON CONTINUE
;.RECOR -- RESET CORE ALLOCATION
;CALL: PUSHJ P,.RECOR
; *RETURN*
;ACS: T1
.RECOR::SKIPE T1,SAVJFF ;FIRST CALL?
JRST RESCOR ;NO, GO RESET CORE
MOVE T1,.JBFF ;GET START OF FREE CORE
MOVEM T1,SAVJFF ;REMEMBER IT FOR CORE SHRINKING
RCRXIT: SETZM FRE.DY ;CLEAR THE FREE-LIST
IFN KOUNT,<
SETZM KF.ZER ;CLEAR THE COUNTERS
SKIPA T1,.+1 ;
KF.ZER,,KF.ZER+1
BLT T1,KE.ZER
>;END IFN KOUNT
POPJ P, ;RETURN TO CALLER
RESCOR: CAMG T1,.JBREL ;IF WE NEED TO,
CORE T1, ;GIVE BACK SOME CORE
JFCL ;(SHOULD NEVER HAPPEN)
MOVE T1,SAVJFF ;GET ORIG CORE ALLOC
MOVEM T1,.JBFF ;RESET IT
JRST RCRXIT ;GO CLEAR LIST AND RETURN
;.DECOR -- GIVE BACK A CORE BLOCK
;CALL: MOVE T1,CORBLK
; PUSHJ P,.DECOR
; *RETURN*
;ACS: T1-2
.DECOR::PUSHJ P,.SAVE3## ;SAVE P1-3
IFN KOUNT,AOS KDCALL ;COUNT CALL TO .DECOR
MOVEI P1,-1(T1) ;POINT AT BLOCK LINK WORD
MOVEI P2,FRE.DY ;START AT THE BEGINNING
DECOR1: MOVE P3,P2 ;REMEMBER WHERE WE WERE
HRRZ P2,(P2) ;CHAIN ALONG THE LIST
IFN KOUNT,AOS KDLOOP ;COUNT THE LOOK
JUMPE P2,DECOR2 ;JUMP IF WE REACHED THE END
CAMGE P2,P1 ;PASSED IT IN CORE ADDRESSES?
JRST DECOR1 ;NO--MOVE ALONG THE LIST
DECOR2: HLRZ T1,(P1) ;GET CORE BLOCK SIZE
ADDI T1,(P1) ;COMPUTE END OF NEW BLOCK
CAME T1,P2 ;IS P2 RIGHT AFTER ME?
JRST [
HRRM P2,(P1) ;NO--POINT ME AT IT
JRST DECOR3 ;AND CHECK LOWER BOUND
]
HLRZ T1,(P1) ;YES--GET CORE BLOCK SIZES
HLRZ T2,(P2) ;OF BOTH BLOCKS
ADD T1,T2 ;COMPUTE NEW LARGER FREE BLOCK SIZE
HRL T1,(P2) ;FORM NEW POINTER (SWAPPED)
MOVSM T1,(P1) ;STORE NEW BLOCK POINTER
DECOR3: HLRZ T1,(P3) ;GET SIZE OF PREDECESSOR BLOCK
JUMPE T1,[
HRRM P1,(P3) ;MUST BE FIRST BLOCK--STORE LINK
POPJ P, ;ALL DONE HERE
]
ADD T1,P3 ;FIND END OF PREDECESSOR
CAME T1,P1 ;IS IT IMMEDIATE PREDECESSOR?
JRST [ ;NO--STORE LINK AND RETURN
HRRM P1,(P3) ;...
POPJ P, ;ALL DONE
]
HLRZ T1,(P3) ;YES--GET SIZE OF PREDECESSOR
MOVS P1,(P1) ;GET FREED BLOCK DATA WORD SWAPPED
ADDI T1,(P1) ;COMPUTE SIZE OF NEW LARGER BLOCK
HLL T1,P1 ;FORM SWAPPED POINTER WORD
MOVSM T1,(P3) ;STORE NEW BLOCK POINTER WORD
POPJ P, ;ALL DONE
RELOC 0 ;LOCAL STORAGE
FRE.DY::BLOCK 1 ;START OF FREE CORE LIST
SAVJFF: BLOCK 1 ;ORIGINAL CORE ALLOCATION
IFN KOUNT,<
KF.ZER:
KACALL: BLOCK 1 ;# CALLS TO .ALCOR
KALOOP: BLOCK 1 ;# LOOPS IN .ALCOR
KDCALL: BLOCK 1 ;# CALLS TO .DECOR
KDLOOP: BLOCK 1 ;# LOOPS IN .DECOR
KFRGB: BLOCK 1 ;# FRAGMENTED BLOCKS ALLOCATED
KE.ZER==.-1
>;END IFN KOUNT
RELOC
NOSYM
END