Trailing-Edge
-
PDP-10 Archives
-
de-10-omona-v-mc9
-
queser.mac
There are 11 other files named queser.mac in the archive. Click here to see a list.
TITLE QUESER -- ENQUEUE/DEQUEUE SERVICE FACILITY - V2036
SUBTTL S. BLOUNT 21 MAR 78
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.
;
;COPYRIGHT (C) 1974,1975,1976,1977,1978 BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
XP VQUESR,2036
ENTRY QUESER ;LOAD THIS MODULE IF NEEDED
QUESER::
;ENQ/DEQ PROVIDES A QUEUEING FACILITY WHICH CAN BE USED
; TO INSURE MUTUAL EXCLUSION OF PROCESSES OPERATING ON
; A COMMON DATA BASE.
SALL
SUBTTL DATA BASE DEFINITIONS
REPEAT 0,<
;Q-BLOCK FORMAT
+-------------------------+-------------------------+
!.QBLJQ: !.QBNJQ: !
! BACK POINTER TO ! FORWARD POINTER TO !
! LAST Q-BLOCK FOR JOB ! NEXT Q-BLOCK FOR JOB !
+-------------------------+----------+--------------+
!.QBJOB: !.QBCHN: !.QBFLG: !
! ! CHANNEL ! !
! JOB NUMBER ! NUMBER ! FLAGS !
+-------------------------+----------+--------------+
!.QBLQ: !.QBNQ: !
! POINTER TO LAST ! POINTER TO NEXT !
! QUEUE ENTRY ! QUEUE ENTRY !
+-------------------------+-------------------------+
!.QBLQR: !.QBNQR: !
! POINTER TO LAST ! POINTER TO NEXT !
! MULTIPLE Q-BLOCK ! MULTIPLE Q-BLOCK !
+-------------------------+-------------------------+
!.QBRID: !.QBNRP: !
! ! !
! REQUEST I.D. ! # REQUESTED FROM POOL !
+-------------------------+-------------------------+
!.QBGRP: !.QBLB: !
! GROUP ! POINTER TO !
! NUMBER ! LOCK-BLOCK !
+-------------------------+-------------------------+
;LOCK-BLOCK FORMAT
+-------------------------+-------------------------+
!.LBLHS: !.LBNHS: !
! BACK POINTER TO LAST ! POINTER TO NEXT !
! LOCK-BLOCK ON HASH CHAIN! LOCK-BLOCK ON HASH CHAIN!
+-------------------------+-------------------------+
!.LBLEN: !.LBFLG: !
! LENGTH OF LOCK-BLOCK ! FLAGS !
! ! !
+-------------------------+-------------------------+
!.LBLQ: !.LBNQ: !
! POINTER TO LAST ! POINTER TO NEXT !
! Q-BLOCK IN CHAIN ! Q-BLOCK IN CHAIN !
+-------------------------+-------------------------+
!.LBLVL: !.LBACC: !
! LEVEL NUMBER ! ADDRESS OF !
! ! ACCESS BLOCK !
+-------------------------+-------------------------+
!.LBPUL: !.LBAVL: !
! ! !
! # IN POOL ! # AVAILABLE !
+-------------------------+-------------------------+
!.LBTIM: !
! TIME-STAMP !
! !
+---------------------------------------------------+
!.LBTXT: ASCIZ STRING !
! OR !
! 500000 + USER CODE !
+---------------------------------------------------+
> ;END OF REPEAT 0
SUBTTL STRUCTURE MACRO DEFINITIONS
;DEFINE DATA STRUCTURE
; NAM - NAME OF STRUCTURE AS USED IN CODE
; LOCN - ADDRESS OF DATA
; POS - POSITION OF DATA WITHIN WORD (RIGHTMOST BIT NUMBER)
; SIZ - SIZE OF DATA WITHIN WORD
DEFINE DEFSTR(NAM,LOCN,POS,SIZ)<
RADIX 10
.TSTSZ(POS,SIZ)
DEFST1(\..TYP,NAM,LOCN,POS,SIZ)
RADIX 8>
DEFINE DEFST1(TYP,NAM,LOCN,POS,SIZ)<
DEFINE NAM(OPS,AC,Y)<
..C==0
IRP OPS,<
IFE TYP-..C,<
STOPI
IFN 3-..C,<
OPS AC,LOCN''Y>
IFE 3-..C,<
OPS AC,[POINT SIZ,LOCN''Y,POS]>>
..C=..C+1>>>
DEFINE .TSTSZ(POS,SIZ)<
..TYP==3
IFE SIZ-36,<..TYP=0>
IFE SIZ-18,<
IFE POS-35,<..TYP=1>
IFE POS-17,<..TYP=2>>>
;LOAD, STORE.
; AC - AC OPERAND
; STR - STRUCTURE NAME
; Y - (OPTIONAL) LOCATION OF DATA IF NOT AS ORIGINALLY SPECIFIED
DEFINE LOAD(AC,STR,Y)<
STR(<MOVE,HRRZ,HLRZ,LDB>,AC,Y)>
DEFINE STOR(AC,STR,Y)<
STR(<MOVEM,HRRM,HRLM,DPB>,AC,Y)>
SUBTTL DATA STRUCTURE DEFINITIONS
;DATA STRUCTURE DEFINITIONS
;Q-BLOCK STRUCTURES
DEFSTR(.QBLJQ,0,17,18) ;POINTER TO LAST ENTRY IN JOB-Q
DEFSTR(.QBNJQ,0,35,18) ;POINTER TO NEXT ENTRY IN JOB-Q
DEFSTR(.QBJOB,1,17,18) ;JOB NUMBER OF THIS USER
DEFSTR(.QBCHN,1,26,9) ;CHANNEL NUMBER
DEFSTR(.QBFLG,1,35,9) ;FLAGS FOR THIS Q-ENTRY
DEFSTR(.QBLQ,2,17,18) ;POINTER TO LAST ENTRY IN QUEUE
DEFSTR(.QBNQ,2,35,18) ;POINTER TO 1ST ENTRY IN QUEUE
DEFSTR(.QBLQR,3,17,18) ;POINTER TO PREVIOUS ENTRY IN THIS REQUEST
DEFSTR(.QBNQR,3,35,18) ;POINTER TO NEXT ENTRY IN THIS REQUEST
DEFSTR(.QBRID,4,17,18) ;REQUEST ID FOR THIS ENTRY
DEFSTR(.QBNRP,4,35,18) ;NUMBER OF RESOURCES REQUESTED FROM POOL
DEFSTR(.QBGRP,5,17,18) ;GROUP NUMBER FOR THIS USER
DEFSTR(.QBLB,5,35,18) ;POINTER TO LOCK BLOCK
QBSIZE==6 ;SIZE OF Q-BLOCK
;LOCK-BLOCK STRUCTURES
DEFSTR(.LBLHS,0,17,18) ;POINTER TO LAST ENTRY IN HASH CHAIN
DEFSTR(.LBNHS,0,35,18) ;POINTER TO NEXT ENTRY IN HASH CHAIN
DEFSTR(.LBLEN,1,17,18) ;LENGTH IN WORDS OF THIS LOCK-BLOCK
DEFSTR(.LBFLG,1,35,12) ;FLAGS
DEFSTR(.LBLQ,2,17,18) ;POINTER TO LAST ENTRY IN QUEUE
DEFSTR(.LBNQ,2,35,18) ;POINTER TO 1ST ENTRY IN QUEUE
DEFSTR(.LBLVL,3,17,18) ;LEVEL NUMBER OF THIS RESOURCE
DEFSTR(.LBACC,3,35,18) ;ACCESS BLOCK ADDRESS/-1/-2/-3
DEFSTR(.LBPUL,4,17,18) ;NUMBER OF RESOURCES IN POOL
DEFSTR(.LBAVL,4,35,18) ;NUMBER OF RESOURCES AVAILABLE
DEFSTR(.LBPWD,4,35,36) ;ENTIRE POOLED RESOURCE WORD
DEFSTR(.LBTIM,5,35,36) ;TIME-STAMP WHEN LOCK WAS LAST LOCKED
DEFSTR(.LBTXT,6,35,36) ;USER CODE/TEXT STRING
LBSIZE==6 ;SIZE OF LOCK-BLOCK (MINUS TEXT)
O.TEXT==6 ;OFFSET OF START OF TEXT
SUBTTL PARAMETER DEFINITIONS
;ENQ FUNCTION CODES:
.ENQBL==0 ;ENQ BLOCK OPTION
.ENQAA==1 ;ENQ ALLOCATE ONLY IF AVAILABLE
.ENQSI==2 ;ENQ SOFTWARE INTERRUPT OFTION
.ENQMA==3 ;ENQ MODIFY ACCESS
;DEQ FUNCTION CODES
.DEQDR==0 ;DEQ RESOURCE
.DEQDA==1 ;DEQ ALL
.DEQID==2 ;DEQ REQUEST I.D.
;ENQC FUNCTION CODES:
.ENQCS==0 ;RETURN STATUS
.ENQCG==1 ;GET USER'S ENQ QUOTA
.ENQCC==2 ;CHANGE USER'S ENQ QUOTA
.ENQCD==3 ;DUMP DATA BASE
;MAXIMUM FUNCTION CODES ALLOWED
EQMXFC==3 ;HIGHEST ENQ FUNCTION CODE
DQMXFC==2 ;HIGHEST DEQ CODE
QCMXFC==3 ;ENQC MAX CODE
;FLAGS DEFINED IN LEFT HALF OF 1ST WORD OF USER LOCK SPEC
EN%SHR==(1B0) ;THIS LOCK IS SHARABLE
EN%BLN==(1B1) ;BYPASS LEVEL NUMBER SEQUENCING
;FLAGS RETURNED TO USER IN LEFT HALF OF STATUS WORD FOR ENQC. UUO:
EN%QCE==(1B0) ;ERROR OCCURED
EN%QCO==(1B1) ;THIS USER IS THE OWNER
EN%QCQ==(1B2) ;THIS USER HAS ISSUED AN ENQ FOR THIS RESOURCE
EN%QCX==(1B3) ;OWNER HAS EXCLUSIVE ACCESS
;FLAGS RETURNED ON DATA-BASE DUMP OPTION OF ENQC.:
EN%QCL==(1B0) ;THIS IS A LOCK BLOCK DUMP
EN%QCT==(1B2) ;THIS LOCK HAS TEXT
EN%QCB==(1B4) ;THIS PROCESS IS BLOCKED
;SOME VARIOUS DEFINITIONS
LOKSIZ==3 ;SIZE OF LOCK SPEC IN RESOURCE BLOCK
HDRSIZ==2 ;SIZE OF HEADER IN RESOURCE BLOCK
EQMXCH==:^D30 ;MAXIMUM STRING SIZE
;FLAGS IN Q-BLOCK
QBOWNR==1B35 ;THIS IS THE LOCK OWNER
QBEXCL==1B34 ;EXCLUSIVE REQUEST
QBPSI==1B33 ;USER WANTS INTERRUPT (CODE WAS 2)
QBWAIT==1B32 ;USER WANTS TO BLOCK (CODE WAS 0)
QBCOD1==1B31 ;FUNCTION CODE WAS %ENQAA
QBINVS==1B30 ;THIS ENTRY IS "INVISIBLE"
QBLKBK==1B29 ;THIS IS A LOCK-BLOCK (ALWAYS ZERO)
;FLAGS IN LOCK-BLOCK
LBTEXT==1B35 ;THIS BLOCK HAS TEXT INSTEAD OF USER CODE
LBLKBK==1B29 ;THIS IS A LOCK-BLOCK (Q-BLOCKS MUST HAVE THIS BIT ZERO)
SUBTTL ERROR CODES RETURNED TO USER
ENQRU%==1 ;SOME RESOURCE(S) REQUEST WERE UNAVAILABLE
ENQBP%==2 ;ILLEGAL # OF RESOURCES REQUESTED (POOLED RESOURCES)
ENQBJ%==3 ;BAD JOB NUMBER
ENQBB%==4 ;BAD BYTE SIZE IN TEXT STRING
ENQST%==5 ;STRING TOO LONG
ENQBF%==6 ;BAD FUNCTION CODE
ENQBL%==7 ;ILLEGAL ARGUMENT BLOCK LENGTH
ENQIC%==10 ;ILLEGAL NUMBER OF LOCKS SPECIFIED
ENQBC%==11 ;BAD CHANNEL NUMBER
ENQPI%==12 ;OPERATOR/JACCT PRIVILEGE REQUIRED
ENQNC%==13 ;NO CORE AVAILABLE
ENQFN%==14 ;FILE NOT OPEN ON SPECIFIED CHANNEL, OR DEVICE NOT A DISK
ENQIN%==15 ;INDIRECT OR INDEXED BYTE POINTER NOT ALLOWED
ENQNO%==16 ;NO RESOURCES WERE OWNED
ENQLS%==17 ;LEVEL SEQUENCING ERROR (LEVEL # TOO LOW)
ENQCC%==20 ;CAN'T CHANGE ACCESS
ENQQE%==21 ;QUOTA EXCEEDED
ENQPD%==22 ;# OF RESOURCES IN POOL NOT SAME AS IN LOCK
ENQDR%==23 ;DUPLICATE REQUEST FOR RESOURCE (LOCK ALREADY REQUESTED)
ENQNE%==24 ;NOT ENQ'ED ON THIS LOCK
ENQLD%==25 ;LEVEL # IN REQUEST DOES NOT MATCH LOCK
ENQED%==26 ;ENQ/DEQ PRIVILEGES REQUIRED
SUBTTL ENQ--ENQ A RESOURCE REQUEST
;
;
;
ENTRY ENQ, DEQ, ENQC
ENQ: PUSHJ P,SAVE4## ;SAVE P1-P4
AOS %ENQTE## ;BUMP TOTAL NUMBER OF ENQ'S
MOVEI T2,EQMXFC ;SET UP MAX FUNCTION CODE
PUSHJ P,SETUP ;DO PRELIMINARY THINGS
POPJ P, ;ERROR, GIVE ERROR CODE
PUSHJ P,CHKBLK ;CHECK OUT THE PARAMETER BLOCK
JRST STOTAC## ; ERROR RETURN
HRRZ T1,FCODE ;GET SAVED FUNCTION CODE
CAIE T1,.ENQMA ;IS THIS A "MODIFY ACCESS"?
PUSHJ P,PRVJC## ;OR, IS THIS GUY PRIVILEGED?
JRST ENQ1 ;YES, DON'T CHECK QUOTAS FOR HIM
HLRZ T1,LOCKCT ;GET # OF LOCKS IN THIS REQUEST
MOVE T2,.PDEQQ##(W) ;AND QUOTA OF SAME
TLON T2,EQ.HBS## ;QUOTA ALREADY BEEN SET?
HRR T2,%ENQDF## ;NO, SET DEFAULT QUOTA
MOVEM T2,.PDEQQ(W) ;STORE QUOTA BACK AGAIN
ADD T1,REQCNT ;ADD # OF OUTSTANDING LOCKS
CAILE T1,(T2) ;TOO MANY REQUESTS?
JRST ENQER3 ;YES, ABORT UUO
ENQ1: PUSHJ P,GETLOK ;GET A LOCK SPEC
PUSHJ P,DOIT ;PERFORM APPROPRIATE FUNCTION
JRST BACKUP ;ERROR--UNWIND PREVIOUS STUFF
PUSHJ P,CHKCNT ;MORE LOCKS TO GO?
JRST ENQ1 ;YES, CYCLE BACK FOR MORE
HRRZ T2,FCODE ;GET STORED FUNCTION CODE
CAIE T2,.ENQMA ;IS IT "MODIFY ACCESS"?
JRST ENQ2 ;NO, FINISH UP
SKIPN T1,NQERRF ;YES, WAS THERE AN ERROR?
JRST CPOPJ1## ;NO, GIVE SKIP RETURN
JRST STOTAC## ;RETURN ERROR CODE TO USER
;COME HERE WHEN ALL ENQ REQUESTS HAVE BEEN PERFORMED
ENQ2: HLRZ T1,P4 ;GET SAVED ADDRESS OF LAST Q
PUSHJ P,QSKD ;SCHEDULE IT
SKIPA ;NOT ALL WERE FREE
JRST GUDXIT ;EVERYTHING WAS OK
;COME HERE IF ONE OR MORE OF THE RESOURCES WERE BUSY
HLRZ T1,P4 ;GET ADDRESS OF LAST ENQ'ED BLOCK
LOAD T2,.QBFLG,(T1) ; AND IT'S FLAGS
TRNE T2,QBWAIT ;SHOULD HE BE BLOCKED?
JRST BLKHIM ;YES, GO BLOCK HIM
MOVEI T1,ENQRU% ;SET UP ERROR CODE
TRNN T2,QBPSI ;IS HE USING SOFT. INTERRUPT SYS?
JRST BACKUP ;NO, WE MUST RELEASE HIS REQUEST
JRST STOTAC## ;YES, JUST RETURN AN ERROR CODE TO HIM
;HERE TO BLOCK USER ON A FUNCTION CODE OF "0"
BLKHIM: PUSH P,P4 ;SAVE POINTER TO LAST Q-BLOCK
PUSH P,NQERRF ;SAVE ERROR FLAG
MOVEI T1,0 ;TELL HIBER WHAT TO DO
PUSHJ P,HIBER## ;HIBERNATE HIM
JFCL
POP P,NQERRF ;GET ERROR FLAG BACK
POP P,P4 ;GET BACK P4
JRST ENQ2 ;GO TRY AGAIN
;COME HERE IF AN ENQ REQUEST FAILED FOR SOME REASON
; THE ENTIRE CHAIN OF REQUESTS (IF ANY) MUST
; BE REMOVED FROM THE QUEUES. THE POINTER TO THE
; LAST MEMBER OF THE CHAIN IS KEPT IN THE
; LEFT HALF OF P4.
;
;ON ENTRY, THE ERROR CODE IS IN T1
BACKUP: HLRZ T3,P4 ;GET ADDRESS OF LAST Q'ED ENTRY
JUMPE T3,STOTAC## ;THERE WAS NONE--EXIT
MOVEM T1,NQERRF ;SAVE ERROR CODE
SKIPA T1,T3 ;MOVE THIS ADDRESS TO USE AS PTR
BACK2: MOVE T1,T2 ;GET ADDRESS OF LAST BLOCK
LOAD T2,.QBLQR,(T1) ;GET PREVIOUS Q-BLOCK'S LOCATION
PUSHJ P,DEQIT ;REMOVE THE CURRENT BLOCK
JFCL ;DON'T CARE IF Q IS FLUSHED
CAIE T2,(T1) ;HAVE WE GONE IN CIRCLE?
JRST BACK2 ;NO
MOVE T1,NQERRF ;YES, GET ERROR CODE
JRST STOTAC## ;GIVE HIM ERROR CODE
SUBTTL SUBROUTINE TO PERFORM AN ENQ FUNCTION
;SUBROUTINE TO PERFORM ONE ENQ FUNCTION FOR A GIVEN RESOURCE.
;THIS ROUTINE (EXCEPT IN THE CASE OF A "MODIFY ACCESS")
; CHECKS THE LEVEL #, POOL COUNT, AND WHETHER THIS
; USER ALREADY HAS AN ENTRY QUEUED. IF ALL THESE CHECKS
; ARE OK, THE USER IS QUEUED FOR THE RESOURCE.
;
;ENTER:
; P1-P4 SET UP BY GETLOK
; PUSHJ P,DOIT
;
;RETURNS:
; +1 ERROR RETURN
; +2 NORMAL RETURN
;
;CLOBBERS ALL T'S
DOIT: HRRZ T2,FCODE ;GET SAVED FUNCTION CODE
CAIN T2,.ENQMA ;IS IT A MODIFY ACCESS?
JRST DOFC3 ;YES, DO SPECIAL STUFF
LDB T2,[POINT 9,P1,17] ;GET LEVEL #
HRRE T3,HILEVL ; AND THE STORED HIGHEST LEVEL #
HRRZ T4,P1 ;GET TYPE OF REQUEST
CAIN T4,-3 ;IS THIS A MONITOR REQUEST?
HLRE T3,HILEVL ;YES, USE HIGHEST MONITOR LEVEL #
CAMLE T2,T3 ;IS THE LEVEL NUMBER OK?
JRST DOIT1 ;YES
TLNN P1,EN%BLN ;NO, DOES HE WANT TO BYPASS IT?
JRST ENQER1 ;NO, FLUSH HIM
MOVEI T2,ENQLS% ;YES, REMEMBER THAT THIS HAPPENED
MOVEM T2,NQERRF ; IN THE ERROR FLAG
DOIT1: PUSHJ P,LOCKOK ;CHECK OTHER THINGS ABOUT THE LOCK
POPJ P, ; ERROR FOUND
HRRE T2,P1 ;GET CHANNEL #
JUMPL T2,DOIT2 ;NOT A CHANNEL NUMBER
MOVE T2,USRJDA##(P1) ;GET DDB ADDRESS
MOVE T3,DEVMOD(T2) ;AND DEVICE BITS
TLNE T3,DVDSK ;IS THIS A DISK?
TLNN T2,LOOKB+ENTRB ; AND HAS THE FILE BEEN 'LOOKED-UP'...
JRST HDRER9 ;NO, ERROR
DOIT2: PUSHJ P,CHPRIV ;DOES THIS GUY HAVE THE PRIVILEGES?
POPJ P, ;NO, ERROR
PUSHJ P,CHLOCK ;DOES LOCK EXIST?
JRST DOIT3 ;NO, WE MUST CREATE IT
LOAD T2,.LBLVL,(T1) ;GET LEVEL #
LDB T3,[POINT 9,P1,17] ;AND NUMBER FOR NEW REQUEST
TLNE P1,EN%BLN ;DON'T CHECK IF HE DOESN'T CARE
JRST DOIT2A ;SKIP OVER CHECK
CAIE T2,(T3) ; SAME?
JRST DOERR0 ;NO, ERROR RETURN
DOIT2A: HLRZ T3,P3 ;GET # IN POOL
LOAD T2,.LBPUL,(T1) ; AND CORRECT # IN POOL
CAIE T2,(T3) ;AND THEY THE SAME?
JRST DOERR2 ;NO, POOL REQUEST ERROR
PUSHJ P,CHECKQ ;IS THIS GUY IN THE Q?
JRST DOERR3 ;YES, ERROR
JRST DOIT4 ;NO, GO PUT HIM IN IT
;COME HERE IF THIS IS A NEW LOCK, TO SET UP THE APPROPRIATE
; BLOCKS AND LINKAGES
DOIT3: MOVE T1,EQTMP4 ;GET HASH BACK AGAIN
MOVEI T2,LBLKBK ;FLAGS="LOCK-BLOCK"
LDB T3,[POINT 3,P2,2]
CAIE T3,5 ;IS THIS A USER CODE?
TRO T2,LBTEXT ;NO, SET "TEXT" FLAG IN LOCK BLOCK
PUSHJ P,BLDLOK ;BUILD A LOCK BLOCK
POPJ P, ;ERROR (NO CORE,BAD STRING,ETC.)
IFN FTTRACKS,<
MOVEM T1,LSTLOK ;REMEMBER LAST LOCK ADDRESS
>;END IFN FTTRACKS
AOS %ENQNQ## ;BUMP THE NUMBER OF QUEUES
TLNE P3,-1 ;IF THIS IS A POOLED RESOURCE..
AOS %ENQNP## ; BUMP THE TOTAL OF THEM TOO
DOIT4: HLRZ T2,P4 ;GET MULTIPLE REQUEST ADDRESS
SETZ T3,
SKIPL P1 ;IS THE "SHARED" BIT ON?
MOVEI T3,QBEXCL ;NO, SET EXCLUSIVE BIT IN BLOCK
MOVE T4,FCODE ;GET STORED FUNCTION CODE
XCT [TRO T3,QBWAIT
TRO T3,QBCOD1
TRO T3,QBPSI](T4) ;SET BIT IN FLAG WORD
PUSHJ P,QHIM ;PUT HIM ON Q
JRST DOERR6 ;NO MORE CORE LEFT
IFN FTTRACKS,<
MOVEM T1,LASTQ ;REMEMBER LAST Q-BLOCK ADDRESS
>;END IFN FTTRACKS
HRL P4,T1 ;SAVE ADDRESS OF THIS ENTRY
PJRST CPOPJ1## ;SKIP RETURN
;COME HERE IF USER WANTS TO MODIFY ACCESS
DOFC3: PUSHJ P,LOCKOK ;IS THE LOCK SPEC OK?
JRST MARETN ;NO, ERROR FOUND
PUSHJ P,CHLOCK ;DOES THE LOCK EXIST?
JRST DOERR4 ;NO, GIVE USER ERROR
PUSHJ P,CHECKQ ;IS HE ALREADY IN Q?
SKIPA ;YES
JRST DOERR4 ;NO, FLAG IT AS ERROR
LOAD T2,.QBFLG,(T1) ;FETCH FLAGS
TRNN T2,QBEXCL ;EXCLUSIVE?
JRST [TLNN P1,EN%SHR ;NO, BUT IS HE ASKING FOR A CHANGE?
JRST DOERR5 ;YES--CAN'T CHANGE ACCESS TO EXCL
JRST CPOPJ1] ;NO, IGNORE THIS LOCK
TLNN P1,EN%SHR ;DOES HE WANT TO MAKE IT SHARABLE?
JRST CPOPJ1## ;NO, IGNORE THIS LOCK
TRZ T2,QBEXCL ;YES, MAKE IT SHARABLE
STOR T2,.QBFLG,(T1) ;RESTORE FLAGS
LOAD T1,.QBLB,(T1) ;GET LOCK BLOCK ADDRESS
PUSHJ P,LOKSKD ;SCHEDULE THIS LOCK
PJRST CPOPJ1## ;RETURN FROM "DOIT"
SUBTTL DEQ--DEQ A RESOURCE REQUEST
DEQ: PUSHJ P,SAVE4## ;SAVE P1-P4
AOS %ENQTD## ;BUMP TOTAL OF DEQ'S SINCE RELOAD
MOVEI T2,DQMXFC ;SET MAX FUNCTION CODE
PUSHJ P,SETUP ;DO PRELIMINARY THINGS
POPJ P, ;ERROR RETURN
XCT [JRST DEQFC0 ;DISPATCH TABLE FOR DEQ FUNCTION CODE
JRST DEQFC1
JRST DEQFC1](T3)
DEQFC1: PUSHJ P,FNDPDS## ;GET THIS GUY'S PDB
HRRZ T1,.PDEQJ##(W) ;GET START OF JOB Q
JUMPE T1,DERNJQ ;EXIT IF NO JOB Q
HRRZ T3,FCODE ;GET FUNCTION
SETZM DQFLAG ;ASSUME NO LOCKS
DEQ0: LOAD T2,.QBNJQ,(T1) ;GET NEXT JOB IN Q POINTER
LOAD T4,.QBRID,(T1) ;GET REQUEST ID
CAME T4,RBLOCK ;IF SAME AND CODE=2, DEQ
CAIN T3,.DEQDA ; OR IF CODE=1, THEN DEQ
PUSHJ P,DEQIT ;REMOVE CURRENT ONE FROM Q
MOVE T1,T2 ;GET NEXT Q-ENTRY
JUMPN T2,DEQ0 ;KEEP GOING IF THERE IS ONE..
SKIPE DQFLAG ;DID U DEQ ANYTHING?
JRST CPOPJ1## ;SKIP RETURN
JRST DERNJQ ;NO, ERROR
;COME HERE FOR A STANDARD DEQ (FUNCTION CODE=0)
; ENTIRE RESOURCE BLOCK MUST BE SCANNED
; AND CHECKED AND EACH LOCK MUST BE DEQ'ED.
DEQFC0: PUSHJ P,CHKBLK ;CHECK OUT THE USER'S PARAMETER BLOCK
JRST STOTAC## ; ERROR
FC0.2: PUSHJ P,GETLOK ;GET A NEW LOCK
PUSHJ P,LOCKOK ;IS THE LOCK SPEC OK?
JRST FC0ERR ;NO
PUSHJ P,CHPRIV ;ARE THE PRIVILEGES OK?
JRST FC0ERR ;NO
PUSHJ P,CHLOCK ;FIND THIS LOCK IN DATA BASE
JRST FCERR1 ;DOESN'T EXIST
PUSHJ P,CHECKQ ;IS HE IN THE Q?
SKIPA ;YES
JRST FCERR1 ;NO, ITS AN ERROR
TLNN P3,-1 ;IS THIS A POOLED RESOURCE?
JRST FC0.3 ;NO
LOAD T2,.QBNRP,(T1) ;GET NUMBER THIS GUY HAS OUT
CAIN T2,(P3) ;IS HE RETURNING ALL OF THEM?
JRST FC0.3 ;YES, HE'S GIVING THEM ALL BACK
CAIG T2,(P3) ;IS HE RETURNING TOO MUCH?
JRST FCERR0 ;YES, DON'T LET HIM DO IT
SUBI T2,(P3) ;COMPUTE NUMBER HE STILL HAS
STOR T2,.QBNRP,(T1) ;UPDATE HIS TOTAL
LOAD T1,.QBLB,(T1) ;GET LOCK-BLOCK
LOAD T2,.LBAVL,(T1) ;GET # OF FREE RESOURCES
ADDI T2,(P3) ;ADD THOSE HE IS RETURNING
STOR T2,.LBAVL,(T1) ;UPDATE # AVAILABLE
PUSHJ P,LOKSKD ;..AND SCHEDULE LOCK-BLOCK
JRST FC0.4 ;DON'T DEQ THIS Q-BLOCK
FC0.3: PUSHJ P,DEQIT ;DEQ THIS ENTRY
JRST FC0.4 ;DON'T SET ERROR FLAG
FCERR0: SKIPA T1,[ENQBP%] ;TRYING TO GIVE BACK TOO MUCH
FCERR1: MOVEI T1,ENQNE% ;NOT ENQ'ED ON THIS LOCK
FC0ERR: HRRM T1,NQERRF ;REMEMBER THAT THERE WAS AN ERROR
FC0.4: PUSHJ P,CHKCNT ;ARE THERE MORE LOCKS?
JRST FC0.2 ;YES, GO BACK
SKIPN T1,NQERRF ;WAS THERE AN ERROR?
JRST CPOPJ1## ;NO, SKIP RETURN
JRST STOTAC## ;GIVE ERROR RETURN
SUBTTL DEQ A PARTICULAR Q-ENTRY
;SUBROUTINE TO DEQ ONE Q-ENTRY
;
;CALL:
; MOVE T1,Q-ENTRY-ADDRESS
; PUSHJ P,DEQIT
; RETURN HERE ALWAYS
;
;ON RETURN, ALL SCHEDULING FOR THE Q-ENTRY AND THE LOCK-BLOCK
; HAS BEEN DONE
;
;CLOBBERS: NONE ;DQFLAG IS BUMPED ON EXIT
DEQIT: AOS DQFLAG ;REMEMBER THIS
PUSHJ P,SAVT## ;JUST FOR SAFETY
LOAD T3,.QBNJQ,(T1) ;GET NEXT JOB PTR
LOAD T2,.QBLJQ,(T1) ;AND LAST JOB PTR
STOR T3,.QBNJQ,(T2) ;RELINK JOB Q
SKIPE T3 ;THIS MAY BE THE END OF THE JOB Q
STOR T2,.QBLJQ,(T3) ;MAKE NEXT ENTRY POINT TO LAST ONE
LOAD T2,.QBLQ,(T1) ;GET LAST Q-PTR
LOAD T3,.QBNQ,(T1) ; AND NEXT Q-ENTRY
STOR T2,.QBLQ,(T3) ;RELINK THESE Q'S
STOR T3,.QBNQ,(T2) ; SAME
LOAD T2,.QBLQR,(T1) ;GET NEXT LINKED REQUEST
LOAD T3,.QBNQR,(T1) ; POINTERS
STOR T2,.QBLQR,(T3) ;RELINK REQUEST Q
STOR T3,.QBNQR,(T2)
MOVE T2,T1 ;PUT Q-BLOCK ADDRESS IN T2
LOAD T1,.QBLB,(T2) ;GET LOCK BLOCK ADDR
LOAD T3,.LBNQ,(T1) ;GET ADDR OF NEXT Q
CAIN T3,(T1) ;IS Q EMPTY?
JRST FLUSH ;YES, GO FLUSH IT
LOAD T3,.QBFLG,(T2) ;GET FLAGS AGAIN
TRNN T3,QBOWNR ;OWNER?
JRST FLSHQ ;NO, GO FLUSH IT
LOAD T3,.QBNRP,(T2) ;YES, GET ALLOCATION
LOAD T4,.LBAVL,(T1) ;AND # AVAILABLE
ADD T3,T4 ;COMBINE THEM
STOR T3,.LBAVL,(T1) ;PUT BACK IN POOL
JRST FLSHQ ;NOW, GO AND FLUSH Q
;COME HERE TO FLUSH A LOCK BLOCK AND A Q BLOCK FROM THE DATA BASE
FLUSH: LOAD T3,.LBNHS,(T1) ;GET NEXT HASH PTR
LOAD T4,.LBLHS,(T1) ; AND LAST HASH PTR
STOR T3,.LBNHS,(T4) ;RELINK THEM
STOR T4,.LBLHS,(T3) ; SO THIS BLOCK DISAPPEARS
PUSH P,T2 ;SAVE ADDRESS OF Q-BLOCK
MOVE T2,T1 ;GET LOCK BLOCK ADDR
LOAD T3,.LBPUL,(T1) ;GET NUMBER IN RESOURCE POOL
SKIPE T3 ;IS IT POOLED?
SOS %ENQNP## ;YES, DECREMENT THAT TOTAL
LOAD T1,.LBLEN,(T2) ;GET LENGTH
PUSHJ P,GIVWDS## ;GIVE IT BACK
POP P,T2 ;GET Q-BLOCK LOCATION BACK
SOSA %ENQNQ## ;REDUCE NUMBER OF QUEUES AND DON'T RE-SCHED
FLSHQ: PUSHJ P,RSKED ;DO RE-SCHEDULING FOR THIS Q-BLOCK
MOVEI T1,QBSIZE ;SET UP SIZE
PJRST GIVWDS## ;FREE UP THIS SPACE NO RETURN
SUBTTL ENQC QUEUE CONTROLLER UUO
;THIS UUO HAS FOUR FUNCTIONS:
; 0. RETURN STATUS OF LIST OF RESOURCES
; 1. RETURN USER'S LOCK QUOTA
; 2. SET USER'S LOCK QUOTA (PRIVILEGED)
; 3. DUMP OUT QUEUE STRUCTURE INTO USER BUFFER
;FOR OPTION 0, THREE WORDS ARE RETURNED FOR EACH LOCK SPECIFIED BY THE
; USER. THE 1ST WORD HAS THE FOLLOWING FORMAT:
;
; B0 ERROR BIT
; B1 THIS USER IS THE OWNER OF THE LOCK
; B2 THIS USER HAS ISSUED AN ENQ FOR THE LOCK
; B3 THE OWNER OF THE LOCK HAS EXCLUSIVE ACCESS
; B9-17 LEVEL NUMBER OF RESOURCE
; B18-35 JOB NUMBER OF OWNER/ERROR CODE
; THE JOB NUMBER OF THE OWNER MAY BE
; ONLY ONE OF MANY OWNERS IF THE
; LOCK IS SHARED.
;
;THE SECOND WORD IS A 36-BIT TIME-STAMP WHICH REPRESENTS
; THE TIME AT WHICH THE RESOURCE WAS LAST
; "ALLOCATED". THIS PROVIDES A METHOD OF DETERMINING
; IF A USER HAS HELD THE RESOURCE FOR AN EXCESSIVE
; AMOUNT OF TIME.
;
;THE THIRD WORD HAS THE REQUEST-ID IN THE RIGHT HALF.
;IF BIT 2 IN WORD 1 IS ON, THIS IS THE CALLER'S ID
;OTHERWISE, IT'S THE OWNER'S ID.
;
;IF THE LOCK HAS NO CURRENT OWNER, THE STATUS WORD WILL HAVE
; -1 IN THE RIGHT HALF
ENQC:: PUSHJ P,SAVE4 ;SAVE P1-P4
MOVEM M,QSKDT ;SAVE ADDRESS OF AC FOR LATER
MOVEI T2,QCMXFC ;SET UP MAX FUNCTION CODE
PUSHJ P,SETUP ;DO STANDARD STUFF
POPJ P, ;ERROR IN FUNCTION CODE
XCT [JRST QC0 ; DISPATCH TABLE FOR ENQC
JRST QC1
JRST QC2
JRST QC3](T3)
QC0: PUSHJ P,CHKBLK ;CHECK LEGALITY OF RESOURCE BLOCK
JRST STOTAC## ; ERROR FOUND--ABORT
AOS QSKDT ;GET ADDRESS OF AC BACK
HRR M,QSKDT ;GET AC+1
PUSHJ P,GETWDU## ;GET CONTENTS OF AC+1
SOS T1 ;PUTWD1 BUMPS IT
HRRZM T1,QSKDT ;SAVE IT
QC0.0: PUSHJ P,GETLOK ;GET A LOCK
PUSHJ P,LOCKOK ;IS THE LOCK SPEC OK?
JRST QCERR ;NO, RETURN ERROR CODE
PUSHJ P,CHLOCK ;DOES THIS QUEUE EXIST?
JRST [MOVEI P3,-1 ;SET STATUS=-1
SETZB P4,P2 ;CLEAR TIME-STAMP
JRST TELHIM]
PUSHJ P,CHECKQ ;YES, BUT AM I IN IT?
JRST GOTHIM ; YES
SETZB P3,P4 ;CLEAR AC
LOAD T1,.LBNQ,(T3) ;GET FIRST Q-BLOCK IN QUEUE (T3=LOCK)
LOAD P2,.QBRID,(T1) ;REQUEST ID
LOAD T2,.QBFLG,(T1) ;AND FLAGS FOR THIS ENTRY
TRNE T2,QBOWNR ;IS HE THE OWNER?
JRST GOTHM2 ;YES
MOVEI P3,-1 ;SET RH OF STATUS TO -1
JRST TELLVL ;AND GO GET LEVEL #
QCERR: HRLI T1,EN%QCE ;SET ERROR BIT IN STATUS WORD
MOVE P3,T1 ;MOVE ENTIRE WORD TO P3
HRRM P3,NQERRF ;REMEMBER THAT AN ERROR OCCURED
SETZB P2,P4 ;CLEAR OTHER STUFF
JRST TELHIM ;AND GIVE IT BACK TO USER
;COME HERE WHEN THE CURRENT JOB IS IN THE QUEUE
GOTHIM: MOVSI P3,EN%QCQ ;TELL HIM HE'S IN THE QUEUE
LOAD T2,.QBFLG,(T1) ;GET HIS FLAG'S
LOAD P2,.QBRID,(T1) ;GET REQUEST ID.
TRNE T2,QBOWNR ;IS HE THE OWNER?
JRST GOTHM1 ;YES, GO AND SET THE BIT
LOAD T1,.QBLB,(T1) ;NO, GO AND FIND THE OWNER
LOAD T1,.LBNQ,(T1) ;GET FIRST ENTRY IN QUEUE
LOAD T2,.QBFLG,(T1) ;GET Q-BLOCK FLAGS
TRNN T2,QBINVS ;IS IT INVISIBLE?
JRST GOTHM2 ;NO
HRRI P3,-1 ;YES, TELL USER THAT THERE IS NO OWNER
JRST TELLVL
GOTHM1: TLO P3,EN%QCO ;TELL HIM HE'S THE OWNER
GOTHM2: TRNE T2,QBEXCL ;EXCLUSIVE ACCESS?
TLO P3,EN%QCX ;YES, SET THE BIT
LOAD T2,.QBJOB,(T1) ;GET JOB NUMBER
HRR P3,T2 ;MOVE INTO STATUS WORD
TELLVL: LOAD T1,.QBLB,(T1) ;GET LOCK-BLOCK ADDRESS
LOAD T2,.LBLVL,(T1) ; AND LEVEL #
DPB T2,[POINT 9,P3,17] ;STICK IT IN
LOAD P4,.LBTIM,(T1) ;GET TIME-STAMP
TELHIM: MOVE T1,P3 ;MOVE STATUS WORD
HRR M,QSKDT ;GET STATUS BLOCK
PUSHJ P,PUTWD1## ;GIVE WORD TO USER
MOVE T1,P4 ;GET TIME-STAMP
PUSHJ P,PUTWD1## ;PUT IT OUT
MOVE T1,P2 ;GET ID
PUSHJ P,PUTWD1## ;PUT IT OUT
HRRM M,QSKDT ;PUT IT BACK
PUSHJ P,CHKCNT ;MORE LOCKS TO GO?
JRST QC0.0 ;YES
SKIPN T1,NQERRF ;WAS THERE AN ERROR?
JRST CPOPJ1## ;NO, EXIT
JRST STOTAC## ;YES, RETURN ERROR CODE
;COME HERE TO PROCESS ENQC FUNCTION CODE 1 (RETURN USER'S QUOTA)
;
QC1: PUSHJ P,GETQUO ;GET CURRENT QUOTA
JRST STOTAC## ; ERROR
TLZ T1,-1 ;CLEAR PDB FLAGS
JRST GUDXT2 ;SKIP RETURN WITH QUOTA IN AC
;COME HERE TO SET USER'S QUOTA
;
QC2: TLZ M,400000 ;FOR PRVBIT
MOVSI T1,JP.POK
PUSHJ P,PRVBIT## ;AM I [1,2] OR JACCT?
TLOA M,400000 ;YES, IT'S OK
JRST HDRERC ;NO, EXIT
PUSHJ P,GETQUO ;GET CURRENT QUOTA
JRST STOTAC## ; ERROR
TLO T1,EQ.HBS## ;REMEMBER THAT IT'S BEEN SET
HLR T1,P1 ;GET NEW QUOTA
MOVEM T1,.PDEQQ##(W) ;STORE IT AWAY
JRST CPOPJ1## ;.AND EXIT
;SUBROUTINE TO RETURN USER'S QUOTA
;
;CALL:
; PUSHJ P,GETQUO
; ERROR RETURN
; NORMAL RETURN
;
;ON RETURN, T1 = QUOTA
; P1 = HEADER WORD OF EFFECTIVE ADDRESS OF UUO (NEW QUOTA,,JOB #)
;
GETQUO: PUSHJ P,GETWDU## ;GET FIRST WORD
MOVE P2,J ;SAVE CURRENT JOB NUMBER
MOVE P1,T1 ; AND HEADER WORD
HRR J,P1 ;GET NEW JOB NUMBER
PUSHJ P,FNDPDB## ;FIND USER'S PDB
JRST QCERR1 ;BAD JOB NUMBER
MOVE T1,.PDEQQ##(W) ;FETCH USER'S QUOTA
MOVE J,P2 ;RESTORE CURRENT JOB NUMBER
JRST CPOPJ1## ;SKIP RETURN
SUBTTL DATA-STRUCTURE DUMP UTILITY
;THIS OPTION OF THE ENQC. UUO DUMPS THE ENTIRE QUEUE STRUCTURE
; INTO A USER-SPECIFIED PARAMETER BLOCK. THIS FUNCTION IS
; RESTRICTED TO PEEK/SPY PRIVILEGE AND SHOULD BE USEFUL ONLY IN
; EXCEPTION CIRCUMSTANCES.
;
QC3: MOVSI T1,PVSPYM ;GET SPY BIT
PUSHJ P,PRVBIT## ;CAN HE SPY?
SKIPA ;YES, LET HIM THRU
JRST HDRERC ;NO, FLUSH THIS REQUEST
HRRZ T1,RBLOCK ;GET ADDRESS OF HIS BLOCK
PUSHJ P,GETWDU## ;GET LENGTH OF BLOCK
SOJL T1,QCERR2 ;LENGTH MUST BE POSITIVE
MOVEM T1,EQTMP1 ;SAVE IT FOR LATER
MOVEI P1,HSHLEN##-1 ;INIT POINTER TO HASH TABLE
;GET THE NEXT ENTRY IN THE HASH TABLE
QC3.1: HRRZ P2,HSHTAB##(P1) ;GET THIS ENTRY
CAIE P2,HSHTAB##(P1) ;IS IT EMPTY?
JRST QC3.2 ;NO, GO GET LOCK
QC3.1A: SOJGE P1,QC3.1 ;MORE?
PUTEND: SETO T1, ;YES, SET UP INSERT -1 AT END
SOSL EQTMP1 ;IS THERE ROOM?
PUSHJ P,PUTWD1## ;YES, DO IT
JRST CPOPJ1## ;EXIT FROM UUO
;COME HERE TO SEARCH A PARTICULAR CHAIN IN THE HASH TABLE
;
;P1- ENTRY IN HASH TABLE
;P2- LOCK BLOCK ON CHAIN
QC3.1B: LOAD P2,.LBNHS,(P2) ;GET NEXT LOCK-BLOCK ON CHAIN
CAIN P2,HSHTAB##(P1) ;BACK TO HASH TABLE?
JRST QC3.1A ;YES
QC3.2: LOAD T1,.LBLEN,(P2) ;GET LENGTH OF LOCK BLOCK
SUBI T1,LBSIZE-2 ;FIND LENGTH OF STATUS ENTRY
CAMLE T1,EQTMP1 ;IS THERE ROOM IN BLOCK?
JRST PUTEND ;NO, PUT END MARKER IN IT
EXCH T1,EQTMP1 ;YES, UPDATE LENGTH LEFT
SUBM T1,EQTMP1 ;...
LOAD T1,.LBACC,(P2) ;GET ACCESS BLOCK ADDR
LOAD T2,.LBFLG,(P2) ;..AND FLAGS
LOAD T3,.LBLVL,(P2) ;..AND LEVEL
HRL T1,T3 ;PUT LEVEL NUMBER IN WORD
TLO T1,EN%QCL ;THIS IS A LOCK BLOCK
TRNE T2,LBTEXT ;DOES IT HAVE TEXT?
TLO T1,EN%QCT ;YES, SET THE BIT
PUSHJ P,PUTWD1## ;STORE IT AWAY
LOAD T1,.LBPWD,(P2) ;GET POOLED LOCK WORD
PUSHJ P,PUTWD1## ;STORE IT
LOAD T1,.LBTIM,(P2) ;GET TIME-STAMP
PUSHJ P,PUTWD1## ;GIVE IT TO USER
LOAD P3,.LBLEN,(P2) ;GET LENGTH BACK AGAIN
SUBI P3,LBSIZE ;FIND SIZE OF TEXT/CODE
MOVEI P4,O.TEXT(P2) ;SET UP POINTER TO TEXT
QC3.4: MOVE T1,(P4) ;GET WORD OF TEXT
PUSHJ P,PUTWD1## ;STORE IT
AOS P4 ;BUMP POINTER
SOJN P3,QC3.4 ;MORE?
LOAD P3,.LBNQ,(P2) ;GET 1ST Q-BLOCK
;FALL THRU TO NEXT PAGE...
;COME HERE TO DUMP OUT A Q-BLOCK ENTRY
QC3.4A: CAMN P3,P2 ;ARE WE BACK AT LOCK-BLOCK?
JRST QC3.1B ;YES, GET NEXT LOCK IN CHAIN
MOVE T1,EQTMP1 ;GET LENGTH LEFT
SUBI T1,QBSIZE ;UPDATE IT
JUMPL T1,PUTEND ;JUMP IF NO ROOM
MOVEM T1,EQTMP1 ;YES
LOAD T1,.QBJOB,(P3) ;GET JOB NUMBER
LOAD T2,.QBFLG,(P3) ;AND FLAGS
TRNN T2,QBOWNR ;IS HE THE OWNER?
JRST QC3.5 ;NO
TLO T1,EN%QCO ;YES, SET BIT
JRST QC3.6 ;KEEP GOING
QC3.5: TRNE T2,QBWAIT ;NOT OWNER--IS HE WAITING?
TLO T1,EN%QCB ;YES, SET BLOCKED BIT
QC3.6: TRNE T2,QBEXCL ;EXCLUSIVE?
TLO T1,EN%QCX ;YES, SET IT
PUSHJ P,PUTWD1## ;STORE WORD
LOAD T1,.QBRID,(P3) ;GET REQUEST ID
LOAD T2,.LBPUL,(P2) ;GET LOCK-BLOCK POOL COUNT
LOAD T3,.QBGRP,(P3) ;GET GROUP #
SKIPE T2 ;IS IT'S A POOLED RESOURCE,
LOAD T3,.QBNRP,(P3) ;GET # HE WANTS
HRL T1,T3 ;FORM WORD
PUSHJ P,PUTWD1## ;GIVE IT TO USER
LOAD P3,.QBNQ,(P3) ;GET NEXT Q-BLOCK
JRST QC3.4A ;GO CHECK IF WE ARE BACK AT LOCK
;SUBROUTINE TO VALIDATE THE HEADER WORD AND CHECK ALL
; ENTRIES IN THE RESOURCE BLOCK FOR ADDRESS CHECK, ETC.
;
;CALL:
; PUSHJ P,CHKBLK
; HERE IF ERROR DISCOVERED (ERROR CODE IN T1)
; NORMAL RETURN
;
;
;CLOBBERS: T1-T4,P1-P3
;
CHKBLK: HRRZ T1,RBLOCK ;GET PARAMETER BLOCK ADDRESS
PUSHJ P,GETWDU## ;GET THE HEADER WORD
MOVE T3,T1 ;SAVE # OF LOCKS..
HRRI T3,1 ;..AS A COUNTER
MOVEM T3,LOCKCT ;..FOR USE LATER
HLRE T3,T1 ;GET # OF LOCKS
JUMPLE T3,HDRERB ;BAD LOCK COUNT
IMULI T3,LOKSIZ ;COMPUTE WHAT LENGTH SHOULD
ADDI T3,HDRSIZ ; BE
CAIE T3,(T1) ;IS IT RIGHT?
JRST BFERR ;NO, FLAG IT
PUSHJ P,FNDPDS## ;FIND HIS PDB
PUSHJ P,GETLVL ;GET LEVEL # OF HIGHEST LOCK
MOVEM T1,HILEVL ;SAVE IT FOR USE LATER
PUSHJ P,GETWD1## ;GET THE REQUEST ID
MOVEM T1,REQID ;SAVE IT FOR LATER
HDRLUP: PUSHJ P,GETLOK ;GET A LOCK SPEC
HDR3: LDB T2,[POINT 3,P2,2] ;GET ID CODE FROM PTR/CODE
CAIN T2,5 ;IS THIS A USER CODE?
JRST BYTCK6 ;YES, IGNORE THIS ONE
MOVE T1,P2 ;ARGUMENT TO CKSTR
PUSHJ P,CKSTR## ;MAKE SURE STRING IS IN CORE AND LEGAL
JRST HDRER2 ;ADDRESS CHECK
MOVE P2,T1 ;BYTE POINTER TO STRING TO P2
IFN FTKA10,<
TLO P2,U ;SET RELOCATION IN POINTER FOR KA-10
>
BYTCK6: PUSHJ P,CHKCNT ;UPDATE LOCK COUNT AND CHECK IT
JRST HDRLUP ;THERE'S MORE LOCKS TO GO
HRRI T1,1 ;INITIALIZE COUNTER OF USED LOCKS FOR LATER
HRRM T1,LOCKCT ;STORE IT IN LOCK-COUNT WORD
PJRST CPOPJ1## ;SKIP RETURN
SUBTTL QUEUE SCHEDULING SUBROUTINES
;SUBROUTINE TO INITIATE SCHEDULING AFTER ONE DEQ CALL
;
;CALL:
; MOVE T1,LOCK-BLOCK-ADDR
; MOVE T2,Q-BLOCK-ADDR
; PUSHJ P,RSKED
; RETURN HERE ALWAYS
;
;
RSKED: PUSH P,T2 ;SAVE Q-BLOCK ADDRESS
PUSH P,T1 ;SAVE LOCK-BLOCK ADDRESS
LOAD T1,.QBNQR,(T2) ;GET NEXT REQUEST
CAIN T1,(T2) ;IS IT A MULTIPLE REQUEST?
JRST RSKED3 ;NO, DON'T RESCHEDULE THE Q-ENTRY
MOVEM T2,EQTMP4 ;SAVE Q-BLOCK ADDRESS
PUSHJ P,QSKD ;SCHEDULE THIS Q-BLOCK
JRST RSKED3 ;GO ON AND SCHEDULE LOCK
MOVE T2,EQTMP4 ;GET Q-BLOCK ADDRESS BACK
LOAD T4,.QBFLG,(T2) ;GET FLAGS OF OLD REQUEST
JUMPN T1,RSKED1 ;JUMP IF SCHEDULER DID SOMETHING
TRNE T4,QBOWNR ;WAS HE AN OWNER?
JRST RSKED3 ;YES, DON'T GIVE AN INTERRUPT
RSKED1:
IFN FTPI,<
LOAD T1,.QBNQR,(T2) ;GET NEXT REQUEST
TRNN T4,QBPSI ;DOES THIS USER EXPECT AN INTERRUPT?
JRST RSKED2 ;NO, HE IS BLOCKED
PUSH P,J ;SAVE J
LOAD J,.QBJOB,(T2)
PUSHJ P,GENPSI ;YES, GIVE HIM ONE
POP P,J ;RESTORE J
JRST RSKED3 ; AND GO ON TO SCHEDULE LOCK
>;END OF IFN FTPI
RSKED2: LOAD T1,.QBJOB,(T2) ;GET HIS JOB NUMBER
PUSHJ P,WAKJOB## ;GO AND WAKE HIM UP
RSKED3: POP P,T1 ;GET LOCK-BLOCK BACK AGAIN
PUSHJ P,LOKSKD ;SCHEDULE LOCK BLOCK
POP P,T2 ;GET Q-BLOCK ADDRESS BACK
POPJ P,
;SUBROUTINE TO SCHEDULE ONE Q REQUEST CHAIN
;
;CALL:
; MOVE T1,Q-BLOCK-ADDR
; PUSHJ P,QSKD
; RETURN HERE IF REQUEST NOT LOCKED
; HERE IF FULLY LOCKED AND
; T1 = 0 IF ALREADY LOCKED BEFORE THIS CALL
; T1 =-1 IF THIS CALL DID THE LOCKING
;
;
QSKD: SETZM QSKDF ;ASSUME LOCK ALREADY LOCKED
MOVEM T1,QSKDQ ;SAVE THE ADDRESS OF THIS Q-BLOCK
PUSHJ P,SETINV ;SET INVISIBLE BITS
JRST QSKD0 ;GO MAKE SCHEDULING PASS
JRST QSKD3 ;LOCK IS ALREADY LOCKED
QSKD0: MOVE T1,QSKDQ ;GET ADDR OF THIS BLOCK AGAIN
QSKD1: MOVEM T1,QSKDT ;SAVE IT TEMPORARILY
LOAD T2,.QBGRP,(T1) ;GET GROUP NUMBER
MOVEM T2,QSKDG ;SAVE IT
LOAD T2,.QBFLG,(T1) ;GET FLAGS
TRNE T2,QBOWNR+QBINVS ;IS THIS THE OWNER OR IS IT INVISIBLE?
JRST QSKD2 ;YES, CONTINUE SCANNING SIDEWAYS
LOAD T3,.QBNRP,(T1) ;GET # OF RESOURCES WANTED
CHKLK1: LOAD T1,.QBLQ,(T1) ;GET LAST BLOCK ON Q
MOVE T2,QSKDT ;GET Q-BLOCK ADDR
LOAD T2,.QBFLG,(T2) ;GET FLAGS
LOAD T4,.QBFLG,(T1) ;AND FLAGS
TRNE T4,LBLKBK ;IS THIS A LOCK BLOCK?
JRST CHKLK2 ;YES, WE ARE AT TOP OF QUEUE
TRNE T4,QBINVS ;IS IT INVISIBLE?
JRST CHKLK1 ;YES, IGNORE IT ENTIRELY
TRNN T4,QBEXCL ;IS THIS AN EXCLUSIVE REQUEST?
TRNE T2,QBEXCL ;OR IS ORIGINAL REQUEST EXCLUSIVE?
JRST QSKD4 ;YES TO EITHER MEANS NOT LOCKABLE
LOAD T2,.QBGRP,(T1) ;GET GROUP NUMBER
CAME T2,QSKDG ;SAME GROUP AS OWNER?
JRST QSKD4 ;NO, STOP HERE
JRST CHKLK1 ;LOOP BACK UNTIL AT LOCK BLOCK
;QSKD CONTINUES ON NEXT PAGE...
CHKLK2: LOAD T4,.LBAVL,(T1) ;GET # OF RESOURCES AVAILBLE
SUB T4,T3 ;SUBTRACT REQUEST
JUMPL T4,CPOPJ## ;NOT ENOUGH AVAILABLE
STOR T4,.LBAVL,(T1) ;STORE BACK UPDATED TOTAL
MOVE T3,QSKDT ;GET BACK ADDR OF Q-BLOCK
TRO T2,QBOWNR ;SET THE OWNER FLAG
STOR T2,.QBFLG,(T3) ;STORE THE UPDATED FLAGS
LOAD T2,.QBNQ,(T3) ;NOW MOVE THIS Q-BLOCK TO THE HEAD
LOAD T4,.QBLQ,(T3) ; OF THE Q FOR THIS LOCK
STOR T2,.QBNQ,(T4) ;FIRST, REMOVE IT FROM THE Q
STOR T4,.QBLQ,(T2) ;...
LOAD T2,.LBNQ,(T1) ;NOW ADD IT TO THE START OF THE Q
STOR T3,.QBLQ,(T2) ; PTR BACK TO Q-BLOCK FROM Q-2
STOR T3,.LBNQ,(T1) ; PTR TO Q-BLOCK FROM LOCK-BLOCK
STOR T2,.QBNQ,(T3) ; PTR TO SECOND Q-BLOCK
STOR T1,.LBLQ,(T3) ; PTR BACK TO LOCK-BLOCK
MOVE T2,DATE## ;GET DATE-TIME
STOR T2,.LBTIM,(T1) ;PUT IN LOCK-BLOCK
MOVE T1,QSKDQ ;GET BACK ORIGINAL Q-BLOCK ADDR
SETOM QSKDF ;MARK THAT A LOCK WAS LOCKED
PUSHJ P,SETINV ;SET INVISIBILITY
JRST QSKD0 ;NOT FULLY LOCKED YES, TRY AGAIN
JRST QSKD3 ;LOCK IS FULLY LOCKED, GIVE O RETURN
QSKD2: MOVE T2,QSKDT ;GET Q-BLOCK ADR OF PRESENT Q-BLOCK
LOAD T1,.QBNQR,(T2) ;GET NEXT Q-BLOCK IN THIS REQUEST
CAME T1,QSKDQ ;ARE WE BACK AT THE Q-BLOCK YET?
JRST QSKD1 ;NO, GO CHECK IF THIS Q LOCKED
QSKD3: MOVE T1,QSKDF ;GET FLAG
PJRST CPOPJ1## ;SKIP RETURN
QSKD4: MOVE T1,QSKDQ ;RESTORE T1
POPJ P, ;FAIL RETURN
;SUBROUTINE TO SET INVISIBLE BITS FOR A Q-BLOCK ENTRY
;
;CALL:
; MOVE T1,Q-BLOCK-ADDR
; PUSHJ P,SETINV
; HERE IF NOT FULLY LOCKED YET
; HERE IF REQUEST IS NOW FULLY LOCKED
;
;CLOBBERS: T1-T4
;
SETINV: MOVSI T2,1 ;INIT LEVEL NUMBER SCANNER
MOVEM T2,EQTMP2 ;SAVE LEVEL NUMBER FOR LATER
MOVEM T1,EQTMP1 ;SAVE Q-BLOCK ADDR TOO
SETIN1: LOAD T2,.QBLB,(T1) ;GET ADDR OF LOCK BLOCK
LOAD T4,.LBLVL,(T2) ;AND ITS LEVEL
LOAD T3,.QBFLG,(T1) ; AND FLAGS FOR Q-BLOCK
TRNE T3,QBOWNR ;IS THIS THE OWNER OF THE LOCK?
JRST SETIN2 ;YES
CAMG T4,EQTMP2 ;NO, IS THIS A NEW LOW VALUE?
MOVEM T4,EQTMP2 ;YES, REMEMBER LOWEST NON-LOCKED VALUE
SETIN2: LOAD T1,.QBNQR,(T1) ;GET NEXT Q-BLOCK IN THIS REQUEST
CAME T1,EQTMP1 ;ARE WE BACK AT STARTING POINT?
JRST SETIN1 ;NO, LOOP BACK FOR MORE Q-BLOCKS
MOVE T2,EQTMP2 ;GET LEVEL NUMBER
TLNE T2,-1 ;SEE IF AN UNLOCKED WAS SEEN
JRST CPOPJ1## ;NONE SEEN, LOCK IS FULLY LOCKED
SETIN3: LOAD T2,.QBLB,(T1) ;GET LOCK ADDR
LOAD T4,.LBLVL,(T2) ;AND ITS LEVEL
LOAD T3,.QBFLG,(T1) ;GET Q-BLOCK'S FLAGS
CAMG T4,EQTMP2 ;IS LEVEL ABOVE LOWEST UNLOCKED LEVEL?
TRZA T3,QBINVS ;NO, MAKE THIS Q-BLOCK VISIBLE
TRO T3,QBINVS ;YES, MAKE IT INVISIBLE
STOR T3,.QBFLG,(T1) ;STORE FLAGS BACK
LOAD T1,.QBNQR,(T1) ;GET ADDR OF Q-BLOCK IN REQUEST
CAME T1,EQTMP1 ;HAVE WE SEEN ALL Q-BLOCKS?
JRST SETIN3 ;NO, LOOP BACK FOR MORE
POPJ P, ;NON-SKIP RETURN
SUBTTL LOCK SCHEDULING SUBROUTINE
;SUBROUTINE TO SCHEDULE ONE ENTIRE QUEUE FOR A GIVEN LOCK
;
;CALL:
; MOVE T1,LOCK-BLOCK-ADDR
; PUSHJ P,LOKSKD
; RETURN HERE ALWAYS
;
;ON RETURN, ALL PROCESSES HAVE BEEN INTERRUPTED, OR WOKEN UP
;WHICH HAD RESOURCES THAT HAD BECOME AVAILABLE
;
LOKSKD: MOVEM T1,LKTMP1 ;SAVE ADDRESS OF LOCK
MOVEM T1,LKTMP2 ;INIT Q-BLOCK ADDRESS REGISTER
LOAD T2,.LBAVL,(T1) ;GET NUMBER AVAILABLE
MOVEM T2,LKTMP3 ;SAVE IT
LOKSK1: LOAD T1,.LBNQ,(T1) ;GET ADDR OF NEXT Q-BLOCK FOR LOCK
CAMN T1,LKTMP1 ;BACK TO THE LOCK-BLOCK YET?
POPJ P, ;YES, THRU
MOVEM T1,LKTMP2 ;SAVE THIS ADDRESS
LOAD T2,.QBFLG,(T1) ;GET FLAGS FOR THIS ENTRY
TRNE T2,QBINVS ;IS IT INVISIBLE?
JRST LOKSK1 ;YES, IGNORE IT
TRNE T2,QBOWNR ;IS HE THE OWNER?
JRST LOKSK0 ;YES
LOAD T2,.QBNRP,(T1) ;GET NUMBER REQUESTED
MOVE T3,LKTMP3 ;GET NUMBER AVAILABLE
SUB T3,T2 ;GET DIFFERENCE
MOVEM T3,LKTMP3 ;UPDATE # AVAILABLE
JUMPL T3,CPOPJ## ;LEAVE IF SUPPLY EXAUSTED
LOKSK0: PUSHJ P,QSKD ;SCHEDULE THIS Q-BLOCK
JRST LOKSK2 ;IT WASN'T LOCKED
JUMPE T1,LOKSK2 ;IF NOT JUST LOCKED, DON'T INTERRUPT
MOVE T1,LKTMP2 ;GET ADDR OF THIS Q-BLOCK
IFN FTPI,<
LOAD T2,.QBFLG,(T1) ;GET FLAGS
TRNN T2,QBPSI ;IS HE EXPECTING AN INTERRUPT?
JRST LOKSK3 ;NO, HE IS WAITING
PUSH P,J ;SAVE J
LOAD J,.QBJOB,(T1)
PUSHJ P,GENPSI ;GENERATE AN INTERRUPT FOR HIM
POP P,J ;RESTORE J
JRST LOKSK2 ;AND CONTINUE
>;END FTPI
LOKSK3: LOAD T1,.QBJOB,(T1) ;GET THIS GUY'S JOB NUMBER
PUSH P,W ;JUST IN CASE W GETS LOST
PUSHJ P,WAKJOB## ;WAKE HIM UP
POP P,W ;GET IT BACK
LOKSK2: MOVE T1,LKTMP2 ;GET Q-BLOCK ADDR AGAIN
LOAD T2,.QBFLG,(T1) ;GET FLAGS
TRNN T2,QBEXCL ;EXCLUSIVE REQUEST?
JRST LOKSK1 ;NO, LOOP BACK FOR REST OF Q
POPJ P, ;YES, NO NEED TO SCAN FURTHER
SUBTTL SUBROUTINE TO GET A LOCK SPECIFICATION FROM USER SPACE
;SUBROUTINE TO GET ONE 3-WORD LOCK SPEC FROM THE USER'S
; RESOURCE BLOCK
;
;ON ENTRY, THE WORD "LOCKCT" IS SET UP AS FOLLOWS:
; XWD TOTAL # OF LOCKS, # OF LOCK TO GET
;
;CALL:
; PUSHJ P,GETLOK
; NORMAL RETURN ALWAYS
;
;ON EXIT, P1-P3 WILL HAVE A PRECISE COPY OF THE LOCK
; SPECIFICATION AS GIVEN BY THE USER WITH THE FOLLOWING
; CHANGES:
; 1. IF LH OF P2 WAS -1, IT IS CHANGED TO "POINT 7,0"
; 2. THE RH OF P4 HAS THE ACCESS BLOCK ADDRESS IN IT
; (OR -1/-2/-3)
;
;
GETLOK: HRR M,RBLOCK ;GET ADDRESS OF PARAMETERS
HRRZ T1,LOCKCT ;GET THE NUMBER OF THIS LOCK
IMULI T1,LOKSIZ ;MULTIPLY BY SIZE
ADDI M,-2(T1) ;BUMP POINTER
PUSHJ P,GETWD1 ;GET THE 1ST WORD OF THE LOCK SPEC
MOVEM T1,P1 ;SAVE IT IN P1
PUSHJ P,GETWD1 ;GET THE USER CODE/POINTER WORD
MOVEM T1,P2 ;SAVE IT TOO
PUSHJ P,GETWD1 ;GET THE POOL VALUES
MOVEM T1,P3 ;SAVE IT IN P3
HLRE T1,P2 ;GET LEFT HALF OF PTR
AOSN T1 ;IS IT A -1?
HRLI P2,440700 ;YES, MAKE IT INTO A BYTE PTR
HRRE T1,P1 ;GET CHANNEL #/-1/-2/-3
HRRM T1,P4 ;SAVE THIS IN RH OF P4 FOR USE LATER
JUMPL T1,CPOPJ## ;LEAVE NOW IF NOT A FILE LOCK
CAMLE T1,USRHCU## ;INVALID CHANNEL NUMBER
JRST CPOPJ## ;YES. LEAVE NOW
MOVE T1,USRJDA##(T1) ;GET DDB ADDRESS
HRR P4,DEVACC##(T1) ;GET ACCESS BLOCK ADDRESS
POPJ P, ;RETURN
SUBTTL SUBROUTINES TO CHECK PRIVILEGES AND LOCK SPECS
;SUBROUTINE TO CHECK USER PRIVILEGES
;
;ON ENTRY, P1-P4 MUST BE SET UP BY GETLOK
;
;CALL:
; PUSHJ P,CHPRIV
; RETURN HERE IF PRIV. INSUFFICIENT
; USER IS OK
;
CHPRIV: HRRE T1,P1 ;GET CHANNEL #/-1/-2/-3
CAMN T1,[-2] ;IS IT A LOGICAL LOCK?
JRST [MOVSI T1,JP.ENQ ;YES, DOES HE HAVE ENQ PRIV?
PUSHJ P,PRVBIT## ;CHECK PRIVILEGES
JRST CPOPJ1## ;IT'S OK
JRST PRVERR] ;NO, HE'S AN IMPOSTER
CAMN T1,[-3] ;OR, IS IT A [1,2]/JACCT LOCK?
JRST [PUSHJ P,PRVJC## ;YES, IS HE PRIVILEGED?
JRST CPOPJ1## ;YES, ITS OK
JRST HDRER7] ; NO
PJRST CPOPJ1## ;SKIP RETURN
;SUBROUTINE TO CHECK THE BYTE POINTER SIZE, POOL VALUES,
; AND CHANNEL #
;
;ON ENTRY, P1-P4 SET UP BY GETLOK
;
;CALL:
; PUSHJ P,LOCKOK
; ERROR RETURN
; NORMAL RETURN
;
LOCKOK: LDB T2,[POINT 3,P2,2] ;GET STRING IDENTIFIER
CAIN T2,5 ;IS IT A USER CODE?
JRST LKOK2 ;YES, DON'T CHECK BYTE SIZE
LDB T2,[POINT 6,P2,11] ;GET BYTE SIZE
CAIE T2,7 ;ERROR IF NOT ASCII
JRST HDRER1
TLZE P2,37 ;INDEXED OR INDIRECT POINTER?
JRST HDRERA ;YES, ERROR
LKOK2: HRRE T1,P1 ;GET CHANNEL #
CAMG T1,USRHCU## ;IS IT MORE THAN HIGHEST INIT'D CHANNEL?
CAMGE T1,[-3] ;OR LESS THAN -3?
JRST HDRER6 ;YES TO EITHER IS AN ERROR
JUMPL P3,HDRER8 ;NEGATIVE POOL NUMBER IS ILLEGAL
HLRE T2,P3 ;GET POOL VALUES
JUMPE T2,CPOPJ1## ;DON'T CHECK IF NOT A POOLED RESOURCE
TRNE P3,-1 ;DOES HE WANT NONE OF THEM?
CAIGE T2,(P3) ;REQUEST MORE THAN IN POOL?
JRST HDRER8 ;YES, ERROR
PJRST CPOPJ1## ;SKIP RETURN
;SUBROUTINE TO CHECK IF A USER HAS BEEN QUEUE'D FOR A LOCK
;
;CALL:
; MOVE T1,LOCK-BLOCK-ADDR
; PUSHJ P,CHECKQ
; HERE IF HE IS Q'ED
; HERE IF USER NOT Q'D
;
;ON ENTRY, P1-P3 MUST BE SET UP WITH THE LOCK SPEC
;
;ON NON-SKIP RETURN, T1 WILL HAVE THE Q-BLOCK ADDRESS IN IT
;
;
CHECKQ: MOVE T3,T1 ;SAVE LOCK BLOCK ADDR FOR A SEC
CHECK2: LOAD T1,.LBNQ,(T1) ;GET ADDRESS OF NEXT Q-BLOCK
CAIN T1,(T3) ;ARE WE BACK AT START?
JRST CPOPJ1## ;YES, SKIP RETURN
LOAD T2,.QBJOB,(T1) ;GET THIS Q-BLOCK'S JOB NUMBER
CAIN T2,(J) ;IS IT THIS GUY?
POPJ P, ;YES, RETURN WITH ADDR IN T1
JRST CHECK2 ;KEEP GOING
SUBTTL MISCELLANEOUS SUBROUTINES
;SUBROUTINE TO CREATE A LOCK-BLOCK
;
;CALL:
; MOVE T1,HASH-INDEX
; MOVE T2,FLAGS
; PUSHJ P,BLDLOK
; HERE IF ERROR
; NORMAL RETURN
;
;ON RETURN, T1 = ADDRESS OF LOCK-BLOCK
;
BLDLOK: MOVEM T1,EQTMP1 ;SAVE HASH INDEX
MOVEM T2,EQTMP2 ;SAME FOR FLAGS
MOVEI T2,1 ;ASSUME LENGTH OF CODE/TEXT IS ONE
LDB T3,[POINT 3,P2,2] ;GET THE STRING IDENTIFIER
CAIN T3,5 ;IS IT A USER CODE?
JRST GOTLNG ;YES, SO WE ALREADY HAVE THE LENGTH
IFN FTKA10,<
PUSH P,P2 ;SAVE PNTR AS ARGUMENT
PUSHJ P,RELPTR ;SET RELOCATION IN U
POP P,(P) ;REMOVE ARGUMENT
>
MOVE T3,P2 ;GET THE STRING POINTER
MOVEI T2,0 ;INITIALIZE COUNTER
BUILD2: EXCTUX <ILDB T4,T3>
AOS T2 ;BUMP CHARACTER COUNT
JUMPN T4,BUILD2 ;LEAVE LOOP ONLY IF NULL
CAMLE T2,%ENQML## ;TOO MANY CHARACTERS?
JRST HDRER2 ;YES
IDIVI T2,5 ;FIND # OF WORDS NEEDED
SKIPE T3 ;WAS THERE A REMAINDER?
AOS T2 ;YES, WE NEED ANOTHER WORD
GOTLNG: ADDI T2,LBSIZE ;ADD LENGTH OF LOCK BLOCK
MOVEM T2,EQTMP4 ;SAVE IT FOR NOW
PUSHJ P,GETWDS## ;GET SOME FREE CORE FOR IT
JRST DOERR6 ;NONE AVAILABLE
MOVE T2,EQTMP1 ;GET HASH INDEX BACK
MOVEI T2,HSHTAB##(T2) ; AND ACTUAL ADDRESS OF ENTRY
STOR T2,.LBLHS,(T1) ;STORE IT IN HASH CHAIN
HRRZ T3,(T2) ;GET FORWARD POINTER FOR HASH CHAIN
HRRM T1,0(T2)
STOR T3,.LBNHS,(T1) ;NEXT HASH POINTER
STOR T1,.LBLHS,(T3) ;MAKE NEXT ENTRY POINT TO US
STOR T1,.LBNQ,(T1) ;MAKE THIS A NULL-QUEUE
STOR T1,.LBLQ,(T1) ;...SAME
LDB T2,[POINT 9,P1,17] ;GET LEVEL #
STOR T2,.LBLVL,(T1) ;PUT IT INTO LOCK BLOCK
HLRZ T2,P3 ;GET # OF RESOURCES IN REQUEST
STOR T2,.LBPUL,(T1) ;PUT IT IN BLOCK
STOR T2,.LBAVL,(T1) ;WITH SAME AMOUNT AS "AVAILABLE"
STOR P4,.LBACC,(T1) ;STORE ACCESS BLOCK ADDRESS
MOVE T3,EQTMP4 ;GET LENGTH BACK AGAIN
STOR T3,.LBLEN,(T1) ;LENGTH OF LOCK BLOCK
SETZ T2, ;CLEAR TIME STAMP
STOR T2,.LBTIM,(T1) ;STORE IT
MOVE T2,EQTMP2 ;GET FLAGS AGAIN
STOR T2,.LBFLG,(T1) ;PUT THEM AWAY
TRNN T2,LBTEXT ;IS THERE TEXT?
JRST [STOR P2,.LBTXT,(T1) ;NO, STORE USER CODE
JRST CPOPJ1]
MOVE T2,[POINT 7,O.TEXT(T1)] ;SET UP POINTER TO TEXT
BLD1: EXCTUX <ILDB T3,P2> ;START MOVING TEXT INTO BLOCK
IDPB T3,T2 ;KEEP GOING
JUMPN T3,BLD1 ;LOOP UNTIL NULL BYTE
JRST CPOPJ1## ;GIVE SKIP RETURN
;SUBROUTINE TO CREATE A QUEUE-BLOCK AND LINK IT
; INTO THE CHAIN OF QUEUED REQUESTS
;
;CALL:
; MOVE T1,LOCK-BLOCK-ADDR
; MOVE T2,ADDR-OF-Q-BLOCK-IN-MULTIPLE-REQUEST
; MOVE T3,FLAGS
; PUSHJ P,QHIM
; ERROR RETURN
; NORMAL RETURN
;
;ON RETURN, T1 = ADDRESS OF NEW Q-BLOCK ENTRY
;
QHIM: MOVEM T1,EQTMP1 ;SAVE LOCK-BLOCK ADDRESS
MOVEM T2,EQTMP2 ;SAME FOR MULTIPLE REQUEST ADDR
MOVEM T3,EQTMP3 ; AND FOR FLAGS
MOVEI T2,QBSIZE ;GET LENGTH OF Q-BLOCK
PUSHJ P,GETWDS## ;GET SOME FREE SPACE FOR IT
POPJ P, ; NO MORE LEFT!
MOVEM T1,T2 ;SAVE ADDRESS OF BLOCK
HRRZI T2,.PDEQJ##(W) ;ADDRESS OF JOB-Q BEGINNING
STOR T2,.QBLJQ,(T1) ;LINK INTO JOB CHAIN
HRRZ T3,(T2) ;GET FORWARD POINTER
HRRM T1,(T2) ;MAKE JOB Q POINT TO US
STOR T3,.QBNJQ,(T1) ;MAKE US POINT TO START
SKIPE T3 ;CHECK FOR END OF CHAIN
STOR T1,.QBLJQ,(T3) ;ELSE, RELINK BACKWARD POINTERS
MOVE T2,EQTMP1 ;GET LOCK BLOCK ADDR
STOR T2,.QBNQ,(T1) ;PUT US INTO REGULAR CHAIN OF Q-BLOCKS
LOAD T3,.LBLQ,(T2) ;GET POINTER TO LAST Q ENTRY
STOR T3,.QBLQ,(T1) ;PUT US AFTER IT
STOR T1,.QBNQ,(T3) ;MAKE LOCK BLOCK POINT TO US
STOR T1,.LBLQ,(T2) ;WE ARE THE LAST ENTRY IN QUEUE
STOR T2,.QBLB,(T1) ;MAKE POINTER TO LOCK BLOCK
MOVE T4,REQID ;GET THE REQUEST ID
STOR T4,.QBRID,(T1) ;STORE ID IN Q-BLOCK
MOVE T3,EQTMP3 ;FETCH FLAGS
TLNE P3,-1 ;IS THIS A MULTIPLE RESOURCE?
TRZ T3,QBEXCL ;YES, CLEAR THE EXCLUSIVE BIT
STOR T3,.QBFLG,(T1) ;PUT THEM AWAY
STOR P1,.QBCHN,(T1) ;PUT IN Q-BLOCK
SKIPN T2,EQTMP2 ;IS THIS A MULTIPLE REQUEST?
JRST [STOR T1,.QBNQR,(T1) ;YES, SET UP LINKS FOR CHAIN
STOR T1,.QBLQR,(T1) ;MAKE US POINT TO OURSELVES
JRST QHIM2] ;AND FILL IN REST OF BLOCK
LOAD T3,.QBNQR,(T2) ;GET ADDR OF NEXT ENTRY IN CHAIN
STOR T1,.QBNQR,(T2) ;MAKE HIM POINT TO US
STOR T1,.QBLQR,(T3) ;...
STOR T3,.QBNQR,(T1) ;MAKE US POINT TO HIM
STOR T2,.QBLQR,(T1) ;...
QHIM2: STOR J,.QBJOB,(T1) ;STORE JOB NUMBER
SETZ T2, ;SET UP TO CLEAR SOME STRUCTURES
TLNN P3,-1 ;POOLED?
EXCH T2,P3 ;NO
STOR P3,.QBNRP,(T1) ;YES, STORE REQUESTED NUMBER
STOR T2,.QBGRP,(T1) ;CLEAR GROUP NUMBER
JRST CPOPJ1## ; AND EXIT
;SUBROUTINE TO GENERATE AN INTERRUPT FOR A USER
;
;CALL:
; MOVE T1,Q-BLOCK ADDRESS
; PUSHJ P,GENPSI
; RETURN HERE ALWAYS
;
;
IFN FTPI,<
GENPSI:
LOAD T2,.QBRID,(T1) ;GET REQUEST ID FROM Q-BLOCK
SIGNAL C$QUE ;SIGNAL INTERRUPT
EXCTUU <IORM T2,IBKISW##(M)> ;STORE ID IN INTERRUPT BLOCK
POPJ P, ;RETURN
>;END IFN FTPI
;SUBROUTINE TO UPDATE THE CURRENT LOCK COUNTER AND
; DETERMINE IF THERE ARE MORE LOCKS TO BE PROCESSED
;
;CALL:
; PUSHJ P,CHKCNT
; HERE IF THERE ARE MORE LOCKS
; HERE IF ALL THRU
;
;ON ENTRY, THE WORD "LOCKCT" MUST BE SET UP AS FOLLOWS:
; XWD # OF LOCKS,,# OF THE CURRENT LOCK
;
CHKCNT: AOS T3,LOCKCT ;BUMP COUNTER
TLZ T3,-1 ;CLEAR # LOCKS
HLRZ T2,LOCKCT ;GET NUMBER OF TOTAL LOCKS
CAIL T2,(T3) ;MORE TO GO?
POPJ P, ;YES
JRST CPOPJ1## ;NO, GIVE SKIP RETURN
;SUBROUTINE TO HASH TWO NUMBERS TOGETHER
;
;CALL:
; MOVE T1,NUMBER
; MOVE T2,NUMBER
; PUSHJ P,MHASH
; RETURN HERE ALWAYS WITH HASH IN T1
;
MHASH: XOR T1,RANDOM ;GUARD AGAINST 0 IN T1
XOR T2,RANDOM ;SAME
MUL T2,RANDOM ;SCRAMBLE THINGS UP A LITTLE
MUL T1,T2 ;MAKE IT REALLY RANDOM
POPJ P,
RANDOM: EXP 5*5*5*5*5*5*5*5*5*5*5*5*5*5*5 ;THIS IS 5^15
;SUBROUTINE TO HASH A STRING
;
;CALL:
; MOVE T2,STRING-POINTER
; PUSHJ P,STHASH
; RETURN HERE WITH HASH IN T1
;
;
STHASH: MOVEM T2,EQTMP1 ;SAVE POINTER
IFN FTKA10,<
PUSH P,T2 ;SAVE ARGUMENT
PUSHJ P,RELPTR ;SET U TO RELOC FOR HI OR LOW SEG
POP P,(P)
>
SETZM EQTMP2 ;CLEAR ANSWER REGISTER
STHSH1: MOVEI T4,5 ;SET UP COUNTER
MOVE T3,[POINT 7,T2] ; AND BYTE POINTER
SETZ T2, ;CLEAR RECEIVER AC
STHSH2: EXCTUX <ILDB T1,EQTMP1> ;GET A BYTE FROM USER'S STRING
JUMPE T1,STHSH3 ;END OF STRING?
IDPB T1,T3 ;NO, STORE CHARACTER IN T2
SOJG T4,STHSH2 ;LOOP BACK FOR 5 CHARACTERS
LSH T2,-1 ;LOW ORDER BIT IS ALWAYS 0
XORM T2,EQTMP2 ;XOR THIS INTO ANSWER WORD
JRST STHSH1 ;LOOP BACK UNTIL END OF STRING
STHSH3: XORM T2,EQTMP2 ;STORE PARTIAL WORD TOO
MOVE T1,EQTMP2 ;GET ANSWER
POPJ P, ;RETURN
;SUBROUTINE TO CALCULATE AN INDEX INTO THE HASH TABLE
;
;CALL:
; MOVE P1,ACCESS-BLOCK-ADDR/-1/-2/-3
; MOVE P2,USER CODE OR STRING POINTER
; PUSHJ P,HASH
; NORMAL RETURN
;
;
HASH: HRRE T1,P4 ;GET CHANNEL #/-1/-2/-3
CAMN T1,[-1] ;IF ITS' -1...
HRRZ T1,J ; ..MAKE IT INTO JOB # (BETTER HASH)
MOVE T2,P2 ; AND STRING POINTER
LDB T3,[POINT 3,T2,2] ;GET THE IDENTIFIER
CAIN T3,5 ;IS IT A USER CODE?
JRST HASH2 ;YES, DON'T HASH IT
PUSH P,T1 ;SAVE CHANNEL #
PUSHJ P,STHASH ;HASH THE STRING
POP P,T2 ;GET IT BACK AGAIN
HASH2: PUSHJ P,MHASH ;HASH THE ACCESS BLOCK AND CODE/STRING
MOVMS T1 ;MAKE IT POSITIVE
IDIVI T1,HSHLEN## ;DIVIDE BY SIZE OF HASH TABLE
MOVE T1,T2 ;USE THE REMAINDER
POPJ P, ;RETURN
;SUBROUTINE TO FIND A LOCK-BLOCK
;
;CALL:
; SET UP P1-P4 BY GETLOK
; PUSHJ P,CHLOCK
;
; RETURN HERE IF NOT FOUND
; HERE IF FOUND, ADDRESS OF LOCK-BLOCK IN T1
;
;
CHLOCK: LDB T2,[POINT 3,P2,2] ;GET USER CODE IDENTIFIER
CAIN T2,5 ;IS THIS A USER CODE?
JRST FNDLK0 ;YES, DON'T WORRY ABOUT RELOCATION
IFN FTKA10,<
TLO P2,U ;..THEN SET RELOCATION
>
FNDLK0: PUSHJ P,HASH ;HASH LOCK NAME
MOVEM T1,EQTMP4 ;SAVE IT FOR LATER
MOVEI T1,HSHTAB##(T1) ;GET ADDRESS OF ENTRY
MOVEM T1,EQTMP5 ;SAVE T1
FNDLK1: LOAD T1,.LBNHS,(T1) ;ADVANCE TO NEXT LOCK-BLOCK
CAMN T1,EQTMP5 ;HAVE WE EXHAUSTED LIST?
POPJ P, ;YES, BLOCK WAS NOT FOUND
MOVEM T1,EQTMP1 ;REMEMBER THIS ADDRESS
LOAD T2,.LBACC,(T1) ;GET ACCESS BLOCK ADDRESS
CAIE T2,(P4) ;IS THIS A MATCH?
JRST FNDLK2 ;NO, TRY NEXT ENTRY
MOVE T2,P2 ;GET STRING POINTER
PUSHJ P,STRCMP ;COMPARE THE STRINGS
JRST FNDLK2 ;NO MATCH
HRRE T1,P4 ;GET ACCESS BLOCK ADDRESS
AOJN T1,FNDLK3 ;NOT -1, SO IT'S A MATCH
MOVE T1,EQTMP1 ;YES, SO WE HAVE TO CHECK JOB NUMBERS
LOAD T2,.LBNQ,(T1) ;GET 1ST ENTRY IN QUEUE
LOAD T2,.QBJOB,(T2) ; AND IT'S JOB NUMBER
CAIE T2,(J) ;IS IT THIS JOB?
JRST FNDLK2 ;NO, CONSIDER IT A NON-MATCH
FNDLK3: MOVE T1,EQTMP1 ;GET BACK LOCK-BLOCK ADDRESS
PJRST CPOPJ1## ;SKIP RETURN
FNDLK2: MOVE T1,EQTMP1 ;GET LOCK-BLOCK ADDRESS
JRST FNDLK1 ;GO ON
;SUBROUTINE TO COMPARE STRINGS OR USER CODES
;
;CALL:
; MOVE T1,LOCK-BLOCK-ADDRESS
; MOVE T2,STRING-PTR
; PUSHJ P,STRCMP
; HERE IF NO MATCH
; RETURN HERE IF MATCH
;
;
STRCMP: PUSHJ P,SAVE1## ;SAVE P1
LDB T3,[POINT 3,T2,2]
CAIN T3,5 ;IS THIS A USER CODE?
JRST STRCMC ;YES
LOAD T3,.LBFLG,(T1) ;GET THE FLAGS
TRNN T3,LBTEXT ;TEXT?
POPJ P,0 ;NO
IFN FTKA10,<
PUSH P,T2 ;SAVE ARGUMENT
PUSHJ P,RELPTR ;SET U FOR RELOCATION
POP P,(P) ;REMOVE ARG FROM LIST
>
MOVE P1,[POINT 7,O.TEXT(T1)] ;SET UP PTR TO TEXT
STRCM0: EXCTUX <ILDB T3,T2> ;GET A BYTE FROM USER
ILDB T4,P1 ;AND ONE FROM LOCK BLOCK
CAME T3,T4 ;A MATCH?
POPJ P, ;NO, RETURN
JUMPN T3,STRCM0 ;YES, KEEP GOING IF NOT NULL
PJRST CPOPJ1## ;SKIP RETURN
STRCMC: LOAD T3,.LBFLG,(T1) ;GET THE FLAGS FOR THE LOCK BLOCK
TRNE T3,LBTEXT ;IS THIS USER CODE?
POPJ P, ;NO
LOAD T3,.LBTXT,(T1) ;GET USER CODE
CAME T2,T3 ;MATCH?
POPJ P, ;NO
PJRST CPOPJ1## ;YES, SKIP RETURN
;SUBROUTINE TO FIND THE HIGHEST LEVEL # FOR A GIVEN USER
;
;CALL:
; MOVE W,PDB-ADDRESS
; PUSHJ P,GETLVL
; RETURN HERE ALWAYS
;
;
;ON RETURN, T1 = HIGHEST MONITOR LEVEL,,HIGHEST USER LEVEL
; REQCNT = # OF OUTSTANDING REQUESTS FOR THIS USER
;
;
GETLVL: SETO T1, ;ASSUME THE QUEUE IS EMPTY
SETZM REQCNT ;CLEAR REQUEST COUNT
HRRZ T2,.PDEQJ##(W) ;GET START OF JOB Q
LVL2: JUMPE T2,CPOPJ## ;EXIT IF NO Q
LOAD T3,.QBLB,(T2) ;GET LOCK BLOCK
LOAD T4,.LBLVL,(T3) ; AND ITS LEVEL #
AOS REQCNT ;BUMP COUNT OF REQUESTS
LOAD P2,.LBACC,(T3) ;YES, GET FILE ID/-1/-2/-3
CAIE P2,-3 ;IS THIS A PRIVILEGED LOCK?
JRST LVL3 ;NO, CHECK IT AGAINST HIGH USER LEVEL
HLRE T3,T1 ;GET HIGHEST MONITOR LEVEL #
CAMLE T4,T3 ;A NEW HIGH?
HRL T1,T4 ;YES, UPDATE MONITOR LEVEL #
JRST LVL4 ; AND KEEP GOING
LVL3: HRRE T3,T1 ;GET HIGHEST USER'S LEVEL
CAMLE T4,T3 ;A NEW HIGH?
HRR T1,T4 ;YES
LVL4: LOAD T2,.QBNJQ,(T2) ;RETURN ADDRESS OF Q-BLOCK
JRST LVL2 ;NO, MORE TO GO
;SUBROUTINE TO PERFORM COMMON SETUP FUNCTIONS
;
;CALL:
; MOVE T2,MAX-FUNCTION-CODE
;
; PUSHJ P,SETUP
; ERROR RETURN (ERROR CODE IN T1)
; NORMAL RETURN (FUNCTION CODE IN T3)
;
;P4 IS RETURNED CLEAR
; AND THE FUNCTION CODE IS STORED IN THE RIGHT HALF OF "FCODE"
;
SETUP: SETZB P4,NQERRF ;INITIALIZE FLAGS
HRR M,T1 ;GET PARAMETER BLOCK ADDR
HRRM M,RBLOCK ;SAVE THIS ADDRESS FOR LATER
HLRZ T3,T1 ;GET FUNCTION FROM CALL
MOVEM T3,FCODE ;SAVE IT FOR USE LATER
CAILE T3,(T2) ;IS IT WITHIN RANGE?
JRST NDUERR ;NO, ERROR RETURN
TLO M,400000 ;SO ERRORS RETURN RATHER THAN GOING TO STOTAC
JRST CPOPJ1## ;GIVE GOOD RETURN
IFN FTKA10,<
;ROUTINE TO SET UP U FOR RELOCATION OF A USER BYTE-POINTER
;ENTER WITH POINTER ON STACK
RELPTR: PUSHJ P,SAVT## ;SAVE ACS
PUSH P,J
MOVE J,.C0JOB##
HRRZ U,R ;ASSUME ADDR IS IN LOW SEG
PUSHJ P,HSVAD##
HRRZ T4,-7(P)
CAMGE T4,T2 ;IS IT?
JRST JPOPJ## ;YES, RETURN
MOVE T1,JBTSGN##(J) ;NO, GET HI-SEG RELOCATION
HRRZ U,JBTADR##(T1) ;SET U SUCH THAT UVA+C(U)
SUBI U,(T2) ; POINTS TO RIGHT PHYSICAL ADR
JRST JPOPJ## ; AND RETURN
>
;SUBROUTINE TO PERFORM CLEAN-UP ON A RESET
;
;CALL:
; PUSHJ P,ENQRST
; RETURN HERE ALWAYS
;
ENQRST::PUSHJ P,FNDPDS## ;FIND HIS PDB
SKIPA T1,.PDEQJ(W) ;GET START OF JOB Q
RESET2: MOVE T1,T2 ;FETCH ADDRESS OF CURRENT BLOCK
JUMPE T1,CPOPJ ;EXIT IF NO JOB QUEUE
LOAD T2,.QBNJQ,(T1) ;GET NEXT ENTRY IN JOB Q
PUSHJ P,DEQIT ;YES, DEQ THIS Q-BLOCK
JRST RESET2 ;GO BACK TO START OF LOOP
;SUBROUTINE TO PERFORM "CLOSE" ON FILE-LOCKS
; THIS ROUTINE IS CALLED ON EVERY CLOSE, OPEN, INIT,
; LOOKUP, AND ENTER WHICH OCCURS.
;IT CHECKS TO SEE IF THERE ARE
; ANY OUTSTANDING LOCKS FOR A GIVEN CHANNEL.
; HOWEVER, IT PERFORMS NO ACTION IF IT FINDS ANY.
;
;CALL:
; MOVEI P1,CHANNEL #
; PUSHJ P,ENQCLS##
; HERE IF THERE WERE LOCKS STILL OUT
; HERE IF USER HAD NO LOCKS OUTSTANDING
;
ENQCLS::PUSHJ P,SAVT## ;SAVE SOME AC'S
MOVE J,.C0JOB## ;GET USER'S JOB #
PUSHJ P,FNDPDS## ;GET HIS PDB
HRRZ T2,.PDEQJ(W) ;GET START OF JOB Q
CLOSE2: JUMPE T2,CPOPJ1## ;LEAVE NOW IF HE HAS NO LOCKS
MOVE T1,T2 ;UPDATE CURRENT BLOCK POINTER
LOAD T3,.QBCHN,(T1) ;GET CHANNEL # FOR THIS LOCK
LOAD T2,.QBNJQ,(T1) ;GET NEXT BLOCK IN JOB Q
CAIN T3,(P1) ;MATCHES THE CLOSED CHANNEL?
POPJ P, ;YES, GIVE ERROR RETURN
JRST CLOSE2 ;NO, GET NEXT Q-BLOCK IN JOB QUEUE
SUBTTL ERROR MESSAGES AND RETURNS
;ERROR RETURNS
; SOME OF THESE RETURN TO THE USER (JRST STOTAC), AND SOME
; OF THEM MERELY RETURN FROM THE CURRENTLY ACTIVE SUBROUTINE
; ERCODE ERRTAB,ENQRU% ;(1) SOME RESOURCES UNAVAILABLE
ERCODE HDRER8,ENQBP% ;(2) ILLEGAL # OF RESOURCES REQUESTED.
ERCODE QCERR1,ENQBJ% ;(3) BAD JOB NUMBER
ERCODE HDRER1,ENQBB% ;(4) BAD BYTE SIZE
ERCODE HDRER2,ENQST% ;(5) STRING TOO LONG
ERCODE NDUERR,ENQBF% ;(6) BAD FUNCTION CODE
ERCODE BFERR,ENQBL% ;(7) ILLEGAL ARGUMENT BLOCK LENGTH
ERCODE HDRERB,ENQIC% ;(10) ILLEGAL # OF LOCKS SPECIFIED
ERCODE HDRER6,ENQBC% ;(11) BAD CHANNEL NUMBER
ERCODE HDRER7,ENQPI% ;(12) OPERATOR/JACCT PRIVELEGE REQUIRED
ERCODE DOERR6,ENQNC% ;(13) NO CORE AVAILABLE
ERCODE HDRER9,ENQFN% ;(14) FILE NOT OPEN, OR DEVICE NOT A DISK
ERCODE HDRERA,ENQIN% ;(15) INDIRECT BYTE POINTER
; ERCODE DERNJQ,ENQNO% ;(16) NO RESOURCES WERE OWNED
ERCODE ENQER1,ENQLS% ;(17) LEVEL # TOO LOW
; ERCODE DOERR5,ENQCC% ;(20) CAN'T CHANGE ACCESS
; ERCODE ENQER3,ENQQE% ;(21) QUOTA EXCEEDED
ERCODE DOERR2,ENQPD% ;(22) POOL COUNT DESCREPANCY
ERCODE DOERR3,ENQDR% ;(23) LOCK ALREADY REQUESTED
; ERCODE DOERR4,ENQNE% ;(24) NOT ENQ'D ON THIS LOCK
ERCODE DOERR0,ENQLD% ;(25) LEVEL # DESCREPANCY
ERCODE PRVERR,ENQED% ;(26) ENQ/DEQ PRIVILEGES REQUIRED
;PRIVILEGES INSUFFICIENT (AND EXIT TO USER)
HDRERC: MOVEI T1,ENQPI%
JRST STOTAC##
;QUOTA EXCEEDED
ENQER3: MOVEI T1,ENQQE% ;QUOTA EXCEEDED
JRST STOTAC##
;BAD LENGTH GIVEN IN ARGUMENT BLOCK (FOR DUMP)
QCERR2: MOVEI T1,ENQBL% ;BAD DUMP BLOCK LENGTH
JRST STOTAC##
;NO REQUEST FOUND FOR LOCK
DOERR4: MOVEI T1,ENQNE% ;NO PENDING REQUEST FOUND
JRST MARETN ;GO STORE CODE
;CAN'T CHANGE ACCESS
DOERR5: MOVEI T1,ENQCC% ;CAN'T CHANGE ACCESS
MARETN: HRRM T1,NQERRF ;SAVE CODE
JRST CPOPJ1## ;RETURN FROM "DOIT"
;RESOURCE NOT FOUND (DEQ ALL OR DEQ REQ:ID)
DERNJQ: MOVEI T1,ENQNO% ;NO RESOURCES FOUND
JRST STOTAC## ;GIVE USER THE ERROR CODE
;COME HERE TO MAKE A GOOD EXIT BACK TO THE USER
;THE CONTENTS OF T1 ARE RETURNED IN THE UUO AC.
GUDXIT: HRRZ T1,NQERRF ;RETRIEVE ERROR CODE(FROM ENQ)
GUDXT2: AOS (P) ;BUMP RETURN ADDRESS
JRST STOTAC## ;AND GIVE IT BACK TO HIM
SUBTTL TEMPORARY STORAGE LOCATIONS FOR ENQ/DEQ
$LOW
;
;NOTE THAT THESE LOCATIONS ARE NOT SAVED IF A JOB BECOMES
; BLOCKED. THEREFORE, THEY SHOULD BE USED ONLY FOR
; TEMPORARY STORAGE FOR THE DURATION OF THE PROCESSING OF
; THE UUO, EXCLUDING ANY SCHEDULING WHICH MAY OCCUR.
FCODE: Z ;KEEP THE USER'S FUNCTION CODE HERE
HILEVL: Z ;HIGHEST LEVEL # ISSUED BY USER
DQFLAG: Z ;NON:ZERO IF A LOCK WAS DEQ'D
EQTMP1: Z ;RANDOM TEMPORARIES
EQTMP2: Z ;..SAME
EQTMP3: Z ;..SAME
EQTMP4: Z ;..SAME
EQTMP5: Z
LKTMP1: Z ;STORAGE FOR LOCK-SCHEDULER
LKTMP2: Z ;..SAME
LKTMP3: Z ;..SAME
QSKDF: Z ;STORAGE FOR Q-SCHEDULER
QSKDG: Z ;..SAME
QSKDT: Z ;..SAME
QSKDQ: Z ;..SAME
RBLOCK: Z ;ADDRESS OF USER'S PARAMETER BLOCK
LOCKCT: Z ;# OF LOCKS IN REQUEST,,# OF CURRENT LOCK
REQID: Z ;STORAGE FOR REQUEST ID
NQERRF: Z ;NON-ZERO IF ERROR OCCURED
REQCNT: Z ;COUNT OF OUTSTANDING RESOURCE REQUESTS FOR THIS USER
IFN FTTRACKS,<
LSTLOK::Z ;LAST LOCK-BLOCK CREATED
LASTQ:: Z ;LAST Q-BLOCK CREATED
>;END IFN FTTRACKS
$LIT
END
############################################################