mirror of
https://github.com/PDP-10/stacken.git
synced 2026-02-16 12:42:51 +00:00
2823 lines
92 KiB
Plaintext
2823 lines
92 KiB
Plaintext
TITLE QUESER -- ENQUEUE/DEQUEUE SERVICE FACILITY - V145
|
||
SUBTTL S. BLOUNT /WRS/PMV 22-DEC-87
|
||
SEARCH F,S
|
||
$RELOC
|
||
$HIGH
|
||
|
||
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
|
||
; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
|
||
;
|
||
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION
|
||
; 1974,1975,1976,1977,1978,1979,1980,1982,1984,1986,1988.
|
||
;ALL RIGHTS RESERVED.
|
||
|
||
.CPYRT<1974,1988>
|
||
|
||
|
||
XP VQUESR,145
|
||
|
||
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 !
|
||
+-------------------------+----------+--------------+
|
||
!.QBJCH: !.QBCHN: !.QBFLG: !
|
||
! ! CHANNEL ! !
|
||
! JOB CONTEXT HANDLE ! NUMBER ! FLAGS !
|
||
+-------------------------+----------+--------------+
|
||
!.QBLQ: !.QBNQ: !
|
||
! POINTER TO LAST QUEUE ! POINTER TO NEXT QUEUE !
|
||
! BLOCK FOR THIS LOCK ! BLOCK FOR THIS LOCK !
|
||
+-------------------------+-------------------------+
|
||
!.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 !
|
||
+-------------------------+-------------------------+
|
||
! .QBCHK: ! .QBMSK: !
|
||
! POINTER TO NEXT Q-BLOCK ! MASK BLOCK !
|
||
! TO BE DEADLOCK CHECKED ! !
|
||
+-------------------------+-------------------------+
|
||
;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 TABLE !
|
||
! ! -2, -3, OR 400000+JOB # !
|
||
+-------------------------+-------------------------+
|
||
!.LBPUL: !.LBAVL: !
|
||
! ! !
|
||
! # IN POOL ! # AVAILABLE !
|
||
+-------------------------+-------------------------+
|
||
!.LBTIM: !
|
||
! TIME-STAMP !
|
||
! !
|
||
+---------------------------------------------------+
|
||
!.LBTLN: !.LBTBL: !
|
||
! LENGTH OF TABLE BLOCK ! LOCK ASSOCIATED TABLE !
|
||
! ! !
|
||
+-------------------------+-------------------------+
|
||
!.LBNMS !.LBPLT! !
|
||
! NUMBER OF WORDS IN THE !TIMER ! !
|
||
! MASK BLOCK ! !
|
||
+-------------------------+-------------------------+
|
||
!.LBTXT: ASCIZ STRING !
|
||
! OR 500000,,0 + USER CODE !
|
||
! OR 36-BIT 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(.QBJCH,1,17,18) ;JOB/CONTEXT HANDLE 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
|
||
DEFSTR(.QBCHK,6,17,18) ;NEXT BLOCK TO BE DEADLOCK CHECKED
|
||
DEFSTR(.QBMSK,6,35,18) ;POINTER TO MASK BLOCK
|
||
QBSIZE==7 ;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 TABLE ADDRESS/-2/-3/400000+JOB #
|
||
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(.LBTLN,6,17,18) ;LENGTH OF LOCK-ASSOCIATED TABLE
|
||
DEFSTR(.LBTBL,6,35,18) ;ADDRESS OF LOCK-ASSOCIATED TABLE
|
||
DEFSTR(.LBNMS,7,17,18) ;LENGTH OF MASK BLOCK FOR THIS LOCK
|
||
DEFSTR(.LBPLT,7,22,5) ;PERMANENT LOCK TIMER
|
||
DEFSTR(.LBTXT,10,35,36) ;USER CODE/TEXT STRING
|
||
LBSIZE==10 ;SIZE OF LOCK-BLOCK (MINUS TEXT)
|
||
;IDLE
|
||
O.TEXT==10 ;OFFSET OF START OF TEXT (SEE LB.TXT)
|
||
|
||
|
||
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
|
||
EN%LTL==(1B2) ;LONG TERM LOCK
|
||
EN%NDR==(1B3) ;NOT DEQUEUED ON RESET
|
||
EN%ABT==(1B4) ;PROGRAM SAID THIS LOCK HAS BEEN ABORTED
|
||
EN%DED==(1B5) ;DEADLOCK DETECTION
|
||
EN%UCW==(1B6) ;USER CODE WORD INSTEAD OF STRING POINTER
|
||
|
||
;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
|
||
EN%QCN==(1B5) ;THIS LOCK IS NOT DEQUEUED ON RESET
|
||
EN%QCA==(1B6) ;THIS LOCK IS ABORTED (NO FURTHER REQUESTS GRANTED)
|
||
EN%QCI==(1B7) ;THIS QUEUE BLOCK IS INVISIBLE
|
||
EN%QCD==(1B8) ;THIS QUEUE BLOCK WILL BE CHECKED FOR DEADLOCK
|
||
|
||
|
||
;SOME VARIOUS DEFINITIONS
|
||
HDRMAX==3 ;MAXIMUM SIZE OF HEADER
|
||
LKMIN==2 ;MINIMUM SIZE OF LOCK
|
||
LKMAX==5 ;MAXIMUM SIZE OF LOCK
|
||
EQMXCH==:^D30 ;MAXIMUM STRING SIZE IN WORDS
|
||
EQDFEQ==:^D100 ;DEFAULT ENQ QUOTA
|
||
EQMXMW==:17 ;MAXIMUM PIE SLICE MASK WORD BLOCK LENGTH
|
||
EQMXTB==:^D512 ;MAXIMUM LOCK-ASSOCIATED TABLE LENGTH
|
||
EQMLTL==:^D5 ;MINUTES LONG TERM LOCKS STAY AROUND
|
||
EQMXAQ==:^D500 ;MAXIMUM NUMBER OF ACTIVE QUEUES
|
||
|
||
CODMIN==400000 ;MINIMUM VALUE OF A SPECIAL CODE
|
||
|
||
;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)
|
||
QBINVS==1B31 ;THIS ENTRY IS "INVISIBLE"
|
||
QBLKBK==1B30 ;THIS IS A LOCK-BLOCK (ALWAYS ZERO)
|
||
QBDEAD==1B29 ;CHECK FOR DEADLOCK
|
||
QBLNDR==1B28 ;NOT DEQ'D ON RESET
|
||
QBLABT==1B27 ;ABORTED RESOURCE
|
||
|
||
|
||
;FLAGS IN LOCK-BLOCK
|
||
LBLKBK==1B30 ;THIS IS A LOCK-BLOCK (Q-BLOCKS MUST HAVE THIS BIT ZERO)
|
||
LBLAUC==1B26 ;READ COUNT INCREMENTED IN THE ACCESS TABLE
|
||
LBLLTL==1B25 ;LONG TERM LOCK
|
||
LBTEXT==1B24 ;THIS BLOCK HAS TEXT INSTEAD OF USER CODE
|
||
|
||
SUBTTL ERROR CODES RETURNED TO USER
|
||
|
||
ENQRU%==1 ;SOME RESOURCE(S) REQUESTED 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
|
||
ENQME%==27 ;MASK IS TOO LONG, OR LENGTHS DO NOT MATCH.
|
||
ENQTE%==30 ;ENQ. TABLE IS TOO LONG
|
||
ENQAB%==31 ;ATTEMPT TO ENQ. AN ABORTED LOCK
|
||
ENQGF%==32 ;ATTEMPT TO LOCK WITH NDR ON A 'GHOST FILE'
|
||
ENQDD%==33 ;DEADLOCK DETECTED
|
||
ENQTL%==34 ;TIME LIMIT EXCEEDED
|
||
SUBTTL ENQ--ENQ A RESOURCE REQUEST
|
||
;
|
||
;
|
||
;
|
||
|
||
|
||
UENQ:: PUSHJ P,SAVE4## ;SAVE P1-P4
|
||
SETZ P4, ;CLEAR LIST OF REQUESTS
|
||
AOS %ENQTE ;BUMP TOTAL NUMBER OF ENQ'S
|
||
SETOM ENQFLG ;FLAG THAT THIS IS AN ENQ
|
||
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
|
||
IFN FTMP,<
|
||
PUSHJ P,EQLOCK ;GET THE EQ RESOURCE
|
||
>
|
||
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,ENQIT ;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
|
||
JRST ENQFAI ;NOT ALL WERE FREE
|
||
ENQ3: HLLZS LOCKCT ;RESET LOCK ARGUMENT COUNTER
|
||
FILTBL: PUSHJ P,GETLOK ;GET A LOCK ARGUMENT
|
||
SKIPE EQLTBL ;IS THERE A TABLE TO FILL?
|
||
PUSHJ P,REDTBL ;YES, GO FILL IT FOR HIM
|
||
PUSHJ P,CHKCNT ;ANY OTHER LOCKS TO CHECK?
|
||
JRST FILTBL ;YES, GET NEXT
|
||
JRST GUDXIT ;EVERYTHING WAS OK
|
||
|
||
;COME HERE IF ONE OR MORE OF THE RESOURCES WERE BUSY
|
||
|
||
ENQFAI: HLRZ T1,P4 ;GET ADDRESS OF LAST ENQ'ED BLOCK
|
||
LOAD. T2,.QBFLG,(T1) ; AND IT'S FLAGS
|
||
TRNN T2,QBPSI ;IF USING PSI, IGNORE TIME LIMIT (TEMP)
|
||
SKIPN TIMLIM ;IF TIME LIMIT, POSTPONE DEADLOCK CHECK
|
||
TRNN T2,QBDEAD ;SHOULD DEADLOCKS BE DETECTED?
|
||
JRST ENQFA2 ;NO, USER DOESN'T CARE
|
||
PUSHJ P,DEADLK ;CHECK TO SEE IF DEADLOCK
|
||
JRST ENQDED ;YES, GO CLEAN UP
|
||
HLRZ T1,P4 ;GET ADDRESS OF LAST ENQ'ED BLOCK
|
||
LOAD. T2,.QBFLG,(T1) ; AND IT'S FLAGS
|
||
ENQFA2: 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## ;NO, 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
|
||
PUSH P,REQCNT
|
||
PUSH P,LOKSIZ
|
||
PUSH P,HDRSIZ
|
||
PUSH P,RBLOCK
|
||
PUSH P,FCODE
|
||
PUSH P,LOCKCT
|
||
PUSH P,REQID
|
||
PUSH P,TIMLIM
|
||
PUSH P,HILEVL
|
||
IFN FTMP,<
|
||
PUSHJ P,DWNEQ ;FREE EQ RESOURCE OVER HIBER CALL
|
||
>
|
||
MOVSI T1,HBRSEC## ;TIME LIMIT IS IN SECONDS
|
||
HRR T1,TIMLIM ;TELL HIBER HOW LONG TO WAIT
|
||
PUSHJ P,HIBER## ;HIBERNATE HIM
|
||
JFCL
|
||
IFN FTMP,<
|
||
PUSHJ P,UPEQ ;GET THE EQ RESOURCE BACK
|
||
>
|
||
POP P,HILEVL
|
||
POP P,TIMLIM
|
||
POP P,REQID
|
||
POP P,LOCKCT
|
||
POP P,FCODE
|
||
POP P,RBLOCK
|
||
POP P,HDRSIZ
|
||
POP P,LOKSIZ
|
||
POP P,REQCNT
|
||
POP P,NQERRF ;GET ERROR FLAG BACK
|
||
POP P,P4 ;GET BACK P4
|
||
HLRZ T1,P4 ;GET SAVED ADDRESS OF LAST Q
|
||
LOAD. T1,.QBLB,(T1) ;GET ADDRESS OF LOCK BLOCK
|
||
PUSHJ P,CHKABT ;WAS THIS LOCK ABORTED?
|
||
JRST [MOVEI T1,ENQAB% ;YES, SET UP ERROR CODE
|
||
JRST BACKUP] ;AND RELEASE THE REQUEST
|
||
HLRZ T1,P4 ;GET SAVED ADDRESS OF LAST Q
|
||
PUSHJ P,QSKD ;SCHEDULE IT
|
||
CAIA ;NOT ALL REQUESTS WERE GRANTED
|
||
JRST ENQ3 ;ALL LOCKED
|
||
JUMPN T1,ENQFAI ;WAIT SOME MORE IF ANYTHING GRANTED
|
||
SKIPN TIMLIM ;WAS A TIME LIMIT SPECIFIED?
|
||
JRST ENQFAI ;NO, SO WE CAN'T TIMEOUT
|
||
PUSHJ P,DEADLK ;SEE IF TIMEOUT DUE TO DEADLOCK
|
||
JRST ENQDED ;YES, COUNT AND RELEASE REQUEST
|
||
AOS %ENQTO ;COUNT TIMEOUTS
|
||
MOVEI T1,ENQTL% ;SET UP ERROR CODE
|
||
JRST BACKUP ;AND RELEASE THE REQUEST
|
||
|
||
ENQDED: AOS %ENQDD ;COUNT DEADLOCKS DETECTED
|
||
MOVEI T1,ENQDD% ;SET UP ERROR CODE
|
||
JRST BACKUP ;AND RELEASE THE REQUEST
|
||
;ROUTINE TO FILL A USER TABLE WITH DATA FROM THE LOCK-ASSOCIATED TABLE
|
||
|
||
REDTBL: PUSHJ P,FNDLOK ;FIND THE LOCK BLOCK
|
||
STOPCD CPOPJ##,DEBUG,ENQLNF ;++LOCK NOT FOUND
|
||
HLRZ T2,EQLTBL ;LENGTH OF USER'S DATA BLOCK
|
||
LOAD. T3,.LBTLN,(T1) ;LENGTH OF STORED DATA
|
||
CAMG T2,T3 ;IS THE USERS TABLE LONGER?
|
||
JRST REDTB1 ;NO, JUST COPY THE DATA
|
||
HRRZ T4,EQLTBL ;POINTER TO USER'S ARGUMENT BLOCK
|
||
EXCTXU <SETZM (T4)> ;CLEAR FIRST WORD FOR HIM
|
||
ADDI T2,-1(T4) ;LAST WORD OF BLOCK
|
||
HRL T4,T4 ;SETUP SOURCE AT START OF BLOCK
|
||
ADDI T4,1 ;MAKE PROPAGATING POINTER
|
||
CAIL T2,(T4) ;ONE WORD BLOCK?
|
||
EXCTUU <BLT T4,(T2)> ;ZERO BLOCK TO ENSURE ZERO FILL
|
||
MOVEI T2,(T3) ;COPY ONLY REAL DATA
|
||
REDTB1: JUMPE T2,CPOPJ## ;IF ZERO LENGTH, JUST RETURN
|
||
LOAD. T3,.LBTBL,(T1) ;GET ADDRESS OF LOCK-ASSOCIATED TABLE
|
||
HRLZ T3,T3 ;MAKE THIS THE SOURCE ADDRESS FOR BLT
|
||
HRR T3,EQLTBL ;AND USERS TABLE IS THE DESTINATION
|
||
ADDI T2,-1(T3) ;LAST WORD TO TRANSFER
|
||
EXCTXU <BLT T3,(T2)> ;COPY THE DATA FOR HIM
|
||
POPJ P, ;AND RETURN
|
||
;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,ENQIT
|
||
;RETURNS:
|
||
; +1 ERROR RETURN
|
||
; +2 NORMAL RETURN
|
||
;USES T1-T4
|
||
|
||
ENQIT: 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 ENQIT1 ;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
|
||
ENQIT1: PUSHJ P,LOCKOK ;CHECK OTHER THINGS ABOUT THE LOCK
|
||
POPJ P, ; ERROR FOUND
|
||
HRRE T2,P1 ;GET CHANNEL #
|
||
JUMPL T2,ENQIT2 ;NOT A CHANNEL NUMBER
|
||
MOVE T3,DEVMOD(F) ;AND DEVICE BITS
|
||
TLNE T3,DVDSK ;IS THIS A DISK?
|
||
TLNN F,LOOKB+ENTRB ; AND HAS THE FILE BEEN 'LOOKED-UP'...
|
||
JRST HDRER9 ;NO, ERROR
|
||
ENQIT2: PUSHJ P,CHPRIV ;DOES THIS GUY HAVE THE PRIVILEGES?
|
||
POPJ P, ;NO, ERROR
|
||
PUSHJ P,FNDLOK ;DOES LOCK EXIST?
|
||
JRST ENQIT4 ;NO, WE MUST CREATE IT
|
||
|
||
;CONTINUED ON THE NEXT PAGE
|
||
;CONTINUED FROM THE PREVIOUS PAGE
|
||
|
||
PUSHJ P,CHKABT ;HAS THIS LOCK BEEN ABORTED
|
||
JRST ABTERR ;YES, INFORM THE NEW REQUESTER
|
||
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 ENQIT3 ;SKIP OVER CHECK
|
||
CAIE T2,(T3) ; SAME?
|
||
JRST DOERR0 ;NO, ERROR RETURN
|
||
ENQIT3: 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
|
||
PUSH P,T1
|
||
MOVE T2,.CPJCH##
|
||
PUSHJ P,CHECKQ ;IS THIS GUY IN THE Q?
|
||
JRST [POP P,T1
|
||
JRST DOERR3]
|
||
POP P,T1
|
||
JRST ENQIT5 ;NO, GO PUT HIM IN IT
|
||
|
||
; HERE IF NEW LOCK
|
||
|
||
ENQIT4: MOVE T1,EQTMP4 ;GET HASH BACK AGAIN
|
||
MOVEI T2,LBLKBK ;FLAGS="LOCK-BLOCK"
|
||
TLNE P1,EN%UCW ;CODE WORD?
|
||
JRST ENQIT7 ;YES, DON'T SET TEXT FLAG
|
||
LDB T3,[POINT 3,P2,2]
|
||
CAIE T3,5 ;IS THIS A USER CODE?
|
||
TRO T2,LBTEXT ;NO, SET "TEXT" FLAG IN LOCK BLOCK
|
||
ENQIT7: TLNE P1,EN%LTL ;USER WANTS THIS ONE TO STAY AROUND?
|
||
TRO T2,LBLLTL ;YES, SET 'LONG TERM LOCK' BIT
|
||
PUSHJ P,BLDLOK ;BUILD A LOCK BLOCK
|
||
POPJ P, ;ERROR (NO CORE,BAD STRING,ETC.)
|
||
MOVEM T1,LSTLOK ;REMEMBER LAST LOCK ADDRESS
|
||
AOS %ENQNQ ;BUMP THE NUMBER OF QUEUES
|
||
TLNE P3,-1 ;IF THIS IS A POOLED RESOURCE..
|
||
AOS %ENQNP ; BUMP THE TOTAL OF THEM TOO
|
||
ENQIT5: SETZ T3,
|
||
SKIPL P1 ;IS THE "SHARED" BIT ON?
|
||
MOVEI T3,QBEXCL ;NO, SET EXCLUSIVE BIT IN BLOCK
|
||
TLNN P1,EN%NDR
|
||
JRST ENQIT6
|
||
TRO T3,QBLNDR
|
||
PUSHJ P,OKNDR ;OK TO NDR LOCK?
|
||
JRST STOTAC ;GIVE ERROR RETURN
|
||
PUSH P,T1 ;SAVE LOCK BLOCK ADDRESS
|
||
LOAD. T1,.LBACC,(T1) ;GET THE ACCESS-TABLE ADDRESS
|
||
CAIGE T1,CODMIN ;IS IT REALLY A SPECIAL CODE?
|
||
PUSHJ P,FILNDR## ;NO, MARK FILE AS NDR
|
||
POP P,T1 ;GET BACK LOCK BLOCK ADDRESS
|
||
ENQIT6: MOVE T4,FCODE ;GET STORED FUNCTION CODE
|
||
TDO T3,[EXP QBWAIT,0,QBPSI](T4) ;SET BIT IN FLAG WORD
|
||
TLNE P1,EN%ABT ;ABORT REQUESTED?
|
||
TRO T3,QBLABT ;YES, REMEMBER IT
|
||
TLNE P1,EN%DED ;DEADLOCK DETECTION REQUESTED?
|
||
TRO T3,QBDEAD ;YES, REMEMBER IN QUEUE BLOCK
|
||
HLRZ T2,P4 ;GET MULTIPLE REQUEST ADDRESS
|
||
PUSHJ P,QHIM ;PUT HIM ON Q
|
||
JRST DOERR6 ;NO MORE CORE LEFT
|
||
MOVEM T1,LASTQ ;REMEMBER LAST Q-BLOCK ADDRESS
|
||
PUSHJ P,BLDMSK ;BUILD THE MASK BLOCK FOR HIM
|
||
POPJ P, ;NO CORE OR MISMATCHED LENGTHS
|
||
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,FNDLOK ;DOES THE LOCK EXIST?
|
||
JRST DOERR4 ;NO, GIVE USER ERROR
|
||
MOVE T2,.CPJCH##
|
||
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,QBOWNR ;IS HE THE OWNER
|
||
JRST DOFC3B ;NO
|
||
TRNN T2,QBEXCL ;EXCLUSIVE?
|
||
JRST DOFC3A ;NO
|
||
;OWNER/EXCLUSIVE
|
||
TLNN P1,EN%SHR ;HE WANTS IT SHARABLE NOW?
|
||
JRST DOFC3E ;NO, NO CHANGE
|
||
TRZ T2,QBEXCL ;CLEAR EXCLUSIVE
|
||
JRST DOFC3D ;AND STORE FLAGS
|
||
|
||
;OWNER/SHARED
|
||
DOFC3A: TLNE P1,EN%SHR ;HE WANTS IT EXCLUSIVE NOW?
|
||
JRST DOFC3E ;NO, NO CHANGE
|
||
PUSHJ P,CKONLY ;ONLY IF HE'S THE ONLY ONE
|
||
JRST DOERR5 ;SOMEONE ELSE IS SHARING ALSO
|
||
TRO T2,QBEXCL ;OKAY, SET EXCLUSIVE
|
||
JRST DOFC3D ;AND STORE UPDATED FLAGS
|
||
|
||
;HERE IF A NON-OWNER
|
||
DOFC3B: TRNN T2,QBEXCL ;EXCLUSIVE
|
||
JRST DOFC3C ;NO
|
||
;NON-OWNER/EXCLUSIVE
|
||
TLNN P1,EN%SHR ;WANTS IT SHARABLE NOW?
|
||
JRST DOFC3E ;NO, NO CHANGE
|
||
TRZ T2,QBEXCL ;CLEAR EXCLUSIVE
|
||
JRST DOFC3D ;AND STORE FLAGS
|
||
|
||
;NON-OWNER/SHARED
|
||
DOFC3C: TLNE P1,EN%SHR ;WANTS IT EXCLUSIVE NOW?
|
||
JRST DOFC3E ;NO, NO CHANGE
|
||
TRO T2,QBEXCL ;SET EXCLUSIVE
|
||
DOFC3D: STOR. T2,.QBFLG,(T1) ;STORE UPDATED FLAGS
|
||
DOFC3E:
|
||
|
||
;CONTINUED ON THE NEXT PAGE
|
||
;CONTINUED FROM THE PREVIOUS PAGE
|
||
|
||
;CHECK HERE FOR SETTING/CLEARING THE ABORT STATUS IN THE QUEUE
|
||
; BLOCK
|
||
|
||
TLNN P1,EN%ABT ;CHANGE TO ABORT STATUS?
|
||
JRST [TRNE T2,QBOWNR ;NO, OWNING QUEUE BLOCK?
|
||
TRZ T2,QBLABT ;YES, CLEAR ABORT STATUS
|
||
JRST DOFC3F]
|
||
TRNN T2,QBOWNR ;OWNING QUEUE BLOCK?
|
||
JRST DERNJQ ;NO, ERROR
|
||
TRO T2,QBLABT ;SET ABORT FLAG
|
||
DOFC3F: STOR. T2,.QBFLG,(T1) ;RESTORE FLAGS IN Q-BLOCK
|
||
|
||
;CHECK HERE FOR SETTING/CLEARING THE NO DEQUEUE ON RESET BIT
|
||
|
||
;T1-T4 ALREADY SET UP ABOVE
|
||
TLNN P1,EN%NDR ;CLEAR NO DEQUEUE ON RESET?
|
||
JRST [TRNE T2,QBOWNR ;OWNING QUEUE BLOCK?
|
||
TRZ T2,QBLNDR ;YES, CLEAR NO DEQUEUE ON RESET
|
||
JRST DOFC3G]
|
||
TRNN T2,QBOWNR ;OWNING QUEUE BLOCK?
|
||
JRST DERNJQ ;NO, ERROR
|
||
MOVE T3,T1 ;SAVE Q-BLOCK ADDRESS
|
||
LOAD. T1,.QBLB,(T1) ;LOCK BLOCK ADDRESS
|
||
PUSHJ P,OKNDR
|
||
JRST STOTAC ;GIVE ERROR RETURN
|
||
LOAD. T1,.LBACC,(T1) ;GET ACCESS TABLE ADDRESS
|
||
CAIGE T1,CODMIN ;IS IT REALLY A SPECIAL CODE?
|
||
PUSHJ P,FILNDR## ;NO, MARK THE FILE AS NDR
|
||
MOVE T1,T3 ;GET BACK Q-BLOCK ADDRESS
|
||
TRO T2,QBLNDR ;SET NO DEQUEUE ON RESET
|
||
DOFC3G: STOR. T2,.QBFLG,(T1) ;RESETORE FLAGS IN Q-BLOCK
|
||
LOAD. T1,.QBLB,(T1) ;GET LOCK BLOCK ADDRESS
|
||
PUSHJ P,LOKSKD ;SCHEDULE THIS LOCK
|
||
PJRST CPOPJ1## ;RETURN FROM "ENQIT"
|
||
;ROUTINE TO CHECK FOR SOLE OWNERSHIP OF A SHARABLE LOCK
|
||
|
||
;CALL WITH T1 CONTAINING THE ADDRESS OF A QUEUE-BLOCK
|
||
; PUSHJ P,CKONLY
|
||
; <IF OTHER OWNERS ALSO>
|
||
; <IF SOLE OWNER>
|
||
|
||
|
||
CKONLY: PUSHJ P,SAVT## ;PRESERVES ALL AC'S
|
||
MOVEI T3,(T1) ;INITIALIZE CURRENT BLOCK POINTER
|
||
CKONL1: LOAD. T3,.QBNQ,(T3) ;NEXT REQUEST
|
||
CAIN T3,(T1) ;BACK TO SELF?
|
||
JRST CPOPJ1## ;YES, GOOD RETURN
|
||
LOAD. T2,.QBFLG,(T3) ;FLAG BITS
|
||
TRNN T2,QBLKBK ;IF THIS IS THE LOCK BLOCK, IGNORE IT
|
||
TRNN T2,QBOWNR ;IS THIS ONE AN OWNER?
|
||
JRST CKONL1 ;NO, LOOP OVER WHOLE LIST
|
||
PUSHJ P,CKOMSK ;CHECK FOR NON-CONFLICTING MASKS
|
||
POPJ P, ;MATCH ON MASKS
|
||
JRST CKONL1 ;NO MATCH
|
||
|
||
|
||
;CKOMSK -- ROUTINE FOR CKONLY TO CHECK FOR MULTI-RESOURCE
|
||
; MASKS.
|
||
|
||
CKOMSK: PUSHJ P,SAVE3## ;SAVE P1-P3
|
||
LOAD. P1,.QBMSK,(T1) ;MASK ADDRESS
|
||
JUMPE P1,CPOPJ ;NO MASK IMPLIES ALL. MUST CONFLICT
|
||
LOAD. P2,.QBMSK,(T3) ;MASK ADDRESS
|
||
JUMPE P2,CPOPJ ;NO MASK IMPLIES ALL. MUST CONFLICT
|
||
TLO P1,(<POINT 36,>) ;MAKE A BYTE POINTER TO THE MASK
|
||
CKOMS1: LDB T2,P1 ;WORD FROM MASK 1
|
||
AND T2,(P2) ;AND WITH WORD OF MASK 2
|
||
JUMPN T2,CPOPJ ;FAIL IF ANY MATCHES
|
||
SOJLE P3,CPOPJ1 ;IF END OF BLOCK. NO CONFLICT
|
||
AOJA P2,CKOMS1 ;NOT END. LOOP OVER WHOLE MASK STRING
|
||
SUBTTL DEQ--DEQ A RESOURCE REQUEST
|
||
|
||
UDEQ:: PUSHJ P,SAVE4## ;SAVE P1-P4
|
||
AOS %ENQTD ;BUMP TOTAL OF DEQ'S SINCE RELOAD
|
||
SETZM ENQFLG ;THIS IS NOT AN ENQ.
|
||
MOVEI T2,DQMXFC ;SET MAX FUNCTION CODE
|
||
PUSHJ P,SETUP ;DO PRELIMINARY THINGS
|
||
POPJ P, ;ERROR RETURN
|
||
JRST @[EXP DEQFC0,DEQFC1,DEQFC1](T3)
|
||
|
||
DEQFC1: PUSHJ P,FNDPDS## ;GET THIS GUY'S PDB
|
||
IFN FTMP,<
|
||
PUSHJ P,EQLOCK ;KEEPS OTHERS OUT OF THE DATABASE
|
||
>
|
||
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
|
||
|
||
IFN FTMP,<
|
||
PUSHJ P,EQLOCK ;INTERLOCK ON EQ
|
||
>
|
||
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,FNDLOK ;FIND THIS LOCK IN DATA BASE
|
||
JRST FCERR1 ;DOESN'T EXIST
|
||
MOVE T2,.CPJCH##
|
||
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,STOTBL ;STORE USER SUPPLIED TABLE INFORMATION
|
||
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 ;FLAG DOING A DEQ. FUNCTION
|
||
PUSHJ P,SAVT## ;SAVE T-REGISTERS (RESET NEEDS THEM)
|
||
IFN FTMP,<
|
||
PUSHJ P,HAVEQ
|
||
STOPCD .+1,DEBUG,ENQDNL ;++DEQ NOT INTERLOCKED
|
||
>
|
||
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,.LBPUL,(T1) ;GET NUMBER IN RESOURCE POOL
|
||
SKIPE T3 ;IS IT POOLED?
|
||
SOS %ENQNP ;YES, DECREMENT THAT TOTAL
|
||
LOAD. T3,.LBFLG,(T1) ;GET FLAGS
|
||
TRNE T3,LBLLTL ;IS THIS A PERMANENT LOCK?
|
||
PJRST FLUSH1 ;YES DON'T DELETE NOW. GO START TIMER
|
||
PUSH P,T1 ;SAVE LOCK BLOCK ADDRESS
|
||
PUSHJ P,FLSHQ1 ;DELETE Q-BLOCK WITHOUT RESCHEDULING
|
||
POP P,T1 ;RESTORE LOCK BLOCK ADDRESS
|
||
PJRST DLTLOK ;DELETE THE LOCK BLOCK
|
||
|
||
|
||
;HERE IF THE LOCK BLOCK HAS THE LONG-TERM-LOCK BIT SET. START
|
||
;THE TIMER, THEN GO DELETE THE QUEUE BLOCK.
|
||
|
||
FLUSH1: MOVE T3,%ENQLT ;GET NUMBER OF MINUTES TO WAIT
|
||
STOR. T3,.LBPLT,(T1) ;PERMANENT LOCK TIMER VALUE
|
||
PJRST FLSHQ1 ;DELETE Q-BLOCK WITHOUT RESCHEDULING
|
||
|
||
|
||
;HERE TO DELETE THE QUEUE BLOCK. ENTER AT FLSHQ1 TO SKIP RESCHEDULING
|
||
;IF THE ASSOCIATED LOCK BLOCK HAS EITHER BEEN DELETED OR NOW HAS
|
||
;A NULL QUEUE.
|
||
|
||
FLSHQ: PUSHJ P,RSKED ;DO RE-SCHEDULING FOR THIS Q-BLOCK
|
||
FLSHQ1: PUSHJ P,DLTMSK ;DELETE MASK BLOCK, IF ANY
|
||
MOVEI T1,QBSIZE ;SET UP SIZE
|
||
PJRST GIVWDS## ;FREE UP THIS SPACE NO RETURN
|
||
|
||
|
||
;SUBROUTINE TO DELETE A LOCK BLOCK.
|
||
;CALL:
|
||
; MOVE T1, LOCK-BLOCK ADDRESS
|
||
; PUSHJ P,DLTLOK
|
||
; ALWAYS RETURNS HERE
|
||
;PRESERVES ALL AC'S
|
||
|
||
DLTLOK: PUSHJ P,SAVT## ;SAVE T1-T4
|
||
PUSHJ P,DLTTBL ;DELETE LOCK ASSOCIATED TABLE, IF ANY
|
||
MOVE T2,T1 ;COPY LOCK BLOCK ADDRESS
|
||
LOAD. T3,.LBFLG,(T2) ;GET FLAGS
|
||
TRNN T3,LBLAUC ;INCREMENTED A.T. READ COUNT?
|
||
JRST DLTLK1 ;NO, DON'T NEED TO DECREMENT
|
||
LOAD. T1,.LBACC,(T2) ;GET ACCESS TABLE ADDRESS
|
||
CAIGE T1,CODMIN ;IS IT REALLY A SPECIAL CODE?
|
||
PUSHJ P,FILDRC## ;NO, DECREMENT READER COUNT
|
||
DLTLK1: LOAD. T3,.LBNHS,(T2) ;GET NEXT HASH PTR
|
||
LOAD. T4,.LBLHS,(T2) ; AND LAST HASH PTR
|
||
STOR. T3,.LBNHS,(T4) ;RELINK THEM
|
||
STOR. T4,.LBLHS,(T3) ; SO THIS BLOCK DISAPPEARS
|
||
LOAD. T1,.LBLEN,(T2) ;GET LENGTH
|
||
SOS %ENQNQ ;REDUCE NUMBER OF QUEUES
|
||
PJRST GIVWDS## ;GIVE BACK THE SPACE TO MONITOR
|
||
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-26 CONTEXT NUMBER OF OWNER
|
||
; B27-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
|
||
|
||
UENQC:: PUSHJ P,SAVE4## ;PRESERVE P1-P4
|
||
SETZM ENQFLG ;THIS IS NOT AN ENQ.
|
||
MOVEM M,SBLOCK ;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
|
||
JRST @[EXP QC0,QC1,QC2,QC3](T3)
|
||
;ENQC. FUNCTION 0 (.ENQCS), RETURN STATUS
|
||
|
||
QC0: PUSHJ P,CHKBLK ;CHECK LEGALITY OF RESOURCE BLOCK
|
||
JRST STOTAC## ; ERROR FOUND--ABORT
|
||
IFN FTMP,<
|
||
PUSHJ P,EQLOCK ;
|
||
>
|
||
AOS SBLOCK ;GET ADDRESS OF AC BACK
|
||
HRR M,SBLOCK ;GET AC+1
|
||
PUSHJ P,GETWDU## ;GET CONTENTS OF AC+1
|
||
SOS T1 ;PUTWD1 BUMPS IT
|
||
HRRZM T1,SBLOCK ;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,FNDLOK ;DOES THIS QUEUE EXIST?
|
||
JRST [MOVEI P3,-1 ;SET STATUS=-1
|
||
SETZB P4,P2 ;CLEAR TIME-STAMP
|
||
JRST TELHIM]
|
||
PUSHJ P,COUNTQ ;COUNT THE QUEUE LENGTH
|
||
JUMPE T2,[MOVEI P3,-1 ;NO ONE IN QUEUE, SET STATUS=-1
|
||
SETZB P4,P2 ;CLEAR TIME-STAMP
|
||
JRST TELHIM]
|
||
HRLZ P2,T2 ;PUT IT IN LEFT HALF
|
||
MOVE T2,.CPJCH##
|
||
PUSHJ P,CHECKQ ;YES, BUT AM I IN IT?
|
||
JRST GOTHIM ; YES
|
||
SETZB P3,P4 ;CLEAR AC
|
||
LOAD. T1,.LBNQ,(T1) ;GET FIRST Q-BLOCK IN QUEUE (T1=LOCK)
|
||
LOAD. T2,.QBRID,(T1) ;REQUEST ID
|
||
HRR P2,T2 ;PUT IT IN RIGHT HALF
|
||
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,.QBRID,(T1) ;GET REQUEST ID.
|
||
HRR P2,T2 ;PUT IT IN RIGHT HALF
|
||
LOAD. T2,.QBFLG,(T1) ;GET HIS FLAG'S
|
||
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,.QBJCH,(T1) ;GET JOB/CONTEXT HANDLE
|
||
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,SBLOCK ;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,SBLOCK ;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
|
||
;ENQC. FUNCTION 1 (.ENQCG), 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
|
||
|
||
|
||
;ENQC. FUNCTION 2 (.ENQCC), SET USER'S QUOTA
|
||
;
|
||
QC2: TLZ M,FLMCOM ;FOR PRVBIT
|
||
MOVSI T1,JP.POK
|
||
PUSHJ P,PRVBIT## ;AM I [1,2] OR JACCT?
|
||
TLOA M,FLMCOM ;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
|
||
HRRE J,P1 ;JOB NUMBER
|
||
CAMN J,[-1] ;IF -1
|
||
MOVE J,.CPJOB## ;USE CURRENT
|
||
PUSHJ P,FNDPDB## ;FIND USER'S PDB
|
||
JRST QCERR1 ;BAD JOB NUMBER
|
||
MOVE T1,.PDEQQ##(W) ;FETCH USER'S QUOTA
|
||
TLZN T1,EQ.HBS##
|
||
HRRZ T1,%ENQDF
|
||
MOVE J,P2 ;RESTORE CURRENT JOB NUMBER
|
||
JRST CPOPJ1## ;SKIP RETURN
|
||
SUBTTL DATA-STRUCTURE DUMP UTILITY
|
||
|
||
;ENQC. FUNCTION 3 (.ENQCD), DUMP ENQ/DEQ DATABASE.
|
||
|
||
;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!PVSPYA ;GET SPY BITS
|
||
PUSHJ P,PRVBIT## ;CAN HE SPY?
|
||
SKIPA ;YES, LET HIM THRU
|
||
JRST HDRERC ;NO, FLUSH THIS REQUEST
|
||
IFN FTMP,<
|
||
PUSHJ P,EQLOCK ;INTERLOCK ON EQ RESOURCE
|
||
>
|
||
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 TABLE 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,.QBJCH,(P3) ;GET JOB/CONTEXT HANDLE
|
||
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
|
||
TRNE T2,QBLNDR ;NOT DEQ'ED ON RESET?
|
||
TLO T1,EN%QCN ;YES, SET IT
|
||
TRNE T2,QBLABT ;ABORT?
|
||
TLO T1,EN%QCA ;YES, SET IT
|
||
TRNE T2,QBINVS ;INVISIBLE?
|
||
TLO T1,EN%QCI ;YES, SET IT
|
||
TRNE T2,QBDEAD ;CHECK FOR DEADLOCK?
|
||
TLO T1,EN%QCD ;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 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,M
|
||
;
|
||
|
||
CHKBLK:
|
||
IFN FTMP,<
|
||
PUSHJ P,HAVEQ ;DOES HE HAVE EQ RESOURCE
|
||
CAIA ;NO, OKAY
|
||
STOPCD .+1,DEBUG,ENQAVE ;++ALREADY HAVE EQ
|
||
>
|
||
HRR M,RBLOCK ;GET PARAMETER BLOCK ADDRESS
|
||
PUSHJ P,GETWDU## ;GET THE HEADER WORD
|
||
LDB T2,[POINT 6,T1,5] ;LENGTH OF BLOCK HEADER
|
||
CAIN T2,0 ;ANY HEADER SIZE SPECIFIED?
|
||
MOVEI T2,2 ;NO, MAKE IT 2 (HISTORICAL)
|
||
CAILE T2,HDRMAX ;WITHIN DEFINED RANGE?
|
||
JRST BFERR ;NO, TOO MANY ARGUMENTS
|
||
MOVEM T2,HDRSIZ ;NOTE HEADER LENGTH
|
||
HRRZ T2,T1 ;TOTAL LENGTH OF THE BLOCK
|
||
SUB T2,HDRSIZ ;NUMBER OF WORDS FOR LOCK BLOCKS
|
||
LDB T4,[POINT 12,T1,17] ;NUMBER OF LOCKS
|
||
IDIVI T2,(T4) ;COMPUTE OF WORDS PER LOCK
|
||
JUMPN T3,BFERR ;IF NON-ZERO REMAINDER
|
||
CAIL T2,LKMIN ;IF LOCK TOO SMALL
|
||
CAILE T2,LKMAX ;OR TOO LARGE
|
||
JRST BFERR
|
||
MOVEM T2,LOKSIZ ;REMEMBER PER-LOCK BLOCK LENGTH
|
||
HRLZM T4,LOCKCT ;SAVE LOCK-COUNT,,0
|
||
HRRE T4,T4 ;GET # OF LOCKS
|
||
JUMPLE T4,HDRERB ;BAD LOCK COUNT
|
||
IMUL T4,LOKSIZ ;COMPUTE WHAT LENGTH SHOULD
|
||
PUSHJ P,FNDPDS## ;FIND PDB OR DIE
|
||
PUSHJ P,GETLVL ;GET LEVEL # OF HIGHEST LOCK
|
||
MOVEM T1,HILEVL ;SAVE IT FOR USE LATER
|
||
SETZ T1, ;DEFAULT REQUEST ID IS 0
|
||
MOVE T2,HDRSIZ ;GET THE SIZE OF THE HEADER
|
||
CAIL T2,2 ;DID HEADER INCLUDE REQUEST ID?
|
||
PUSHJ P,GETWD1## ;GET THE REQUEST ID
|
||
MOVEM T1,REQID ;SAVE IT FOR LATER
|
||
SETZ T1, ;DEFAULT TIME LIMIT IS FOREVER
|
||
MOVE T2,HDRSIZ ;GET THE SIZE OF THE HEADER
|
||
CAIL T2,3 ;DID HEADER INCLUDE TIME LIMIT?
|
||
PUSHJ P,GETWD1## ;YES, GET IT
|
||
MOVEM T1,TIMLIM ;SAVE IN CASE WE BLOCK
|
||
CHKBK2: PUSHJ P,GETLOK ;GET A LOCK SPEC
|
||
TLNE P1,EN%UCW ;CODE WORD?
|
||
JRST CHKBK3 ;YES, DON'T ADDRESS CHECK
|
||
MOVE T1,P2 ;ARGUMENT TO CHKSTR
|
||
PUSHJ P,CHKSTR ;MAKE SURE STRING IS IN CORE AND LEGAL
|
||
POPJ P, ;PROPAGATE ERROR
|
||
CHKBK3: SKIPN EQLMSK ;CHECK FOR MASK ARGUMENT
|
||
JRST CHKBK4 ;IF NONE
|
||
HRRZ T1,EQLMSK ;MASK WORD ADDRESS
|
||
HLRZ T2,EQLMSK ;AND LENGTH
|
||
CAMLE T2,%ENQMM ;IS IT OF LEGAL LENGTH?
|
||
JRST MWLERR ;IF NO
|
||
PUSHJ P,ARNGE## ;RANGE CHECK
|
||
JRST UADERR## ;ADDRESS IS ILLEGAL
|
||
JRST UADERR## ;ADDRESS IS ILLEGAL FOR I/O
|
||
CHKBK4: SKIPN EQLTBL ;DID USER SPECIFY A LOCK TABLE?
|
||
JRST CHKBK5 ;NO, SKIP ADDRESS CHECKS
|
||
HRRZ T1,EQLTBL ;GET START ADDRESS
|
||
HLRZ T2,EQLTBL ;AND LENGTH
|
||
CAMLE T2,%ENQMT ;MAXIMUM TABLE LENGTH
|
||
JRST TBLERR ;TABLE SIZE TOO LARGE
|
||
PUSHJ P,ARNGE## ;RANGE CHECK
|
||
JRST UADERR## ;ADDRESS IS ILLEGAL
|
||
JRST UADERR## ;ADDRESS IS ILLEGAL FOR I/O
|
||
|
||
CHKBK5: PUSHJ P,CHKCNT ;UPDATE LOCK COUNT AND CHECK IT
|
||
JRST CHKBK2 ;THERE'S MORE LOCKS TO GO
|
||
HLLZS LOCKCT ;RESET 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:
|
||
TRNN T4,QBPSI ;DOES THIS USER EXPECT AN INTERRUPT?
|
||
JRST RSKED2 ;NO, HE IS BLOCKED
|
||
PUSH P,J ;SAVE J
|
||
LOAD. J,.QBJCH,(T2) ;GET JOB/CONTEXT HANDLE OF USER
|
||
MOVE T1,T2 ;COPY LOCK BLOCK ADDRESS
|
||
SETZ T2, ;INDICATE NORMAL REQUEST
|
||
PUSHJ P,GENPSI ;YES, GIVE HIM ONE
|
||
POP P,J ;RESTORE J
|
||
JRST RSKED3 ; AND GO ON TO SCHEDULE LOCK
|
||
RSKED2: LOAD. T1,.QBJCH,(T2) ;GET HIS JOB NUMBER
|
||
PUSHJ P,CTXWAK## ;GO AND WAKE HIM UP
|
||
STOPCD .+1,JOB,ENQCWD ;++CAN'T WAKE JOB/CONTEXT AFTER DEQ.
|
||
RSKED3: POP P,T1 ;GET LOCK-BLOCK BACK AGAIN
|
||
PUSHJ P,LOKSKD ;SCHEDULE LOCK BLOCK
|
||
JRST T2POPJ## ;GET Q-BLOCK ADDRESS BACK AND RETURN
|
||
|
||
|
||
|
||
;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
|
||
; T1 = 0 IF ALREADY LOCKED BEFORE THIS CALL
|
||
; T1 =-1 IF THIS CALL DID ANY LOCKING
|
||
;
|
||
;
|
||
|
||
QSKD: PUSHJ P,SAVE2## ;SAVE P1-P2
|
||
SETZM QSKDF ;ASSUME LOCK ALREADY LOCKED
|
||
MOVEM T1,QSKDQ ;SAVE THE ADDRESS OF THIS Q-BLOCK
|
||
QSKD0: PUSHJ P,SETINV ;SET INVISIBLE BITS
|
||
JRST QSKD1 ;GO MAKE SCHEDULING PASS
|
||
JRST QSKD6 ;LOCK IS ALREADY LOCKED
|
||
|
||
QSKD1: MOVE T1,QSKDQ ;GET ADDR OF THIS BLOCK AGAIN
|
||
QSKD2: MOVEM T1,QSKDT ;SAVE IT TEMPORARILY
|
||
LOAD. T2,.QBMSK,(T1) ;GET THE MASK WORD
|
||
MOVEM T2,QSKDM ;SAVE FOR FUTURE REFERENCE
|
||
LOAD. T2,.QBLB,(T1) ;GET POINTER TO LOCK BLOCK
|
||
LOAD. T2,.LBNMS,(T2) ;GET LENGTH OF MASK BLOCK
|
||
MOVEM T2,QSKDN ;SAVE
|
||
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 QSKD5 ;YES, CONTINUE SCANNING SIDEWAYS
|
||
QSKD3: LOAD. T1,.QBLQ,(T1) ;GET PREVIOUS BLOCK IN QUEUE
|
||
MOVE T2,QSKDT ;GET THIS QUEUE BLOCK ADDRESS AGAIN
|
||
LOAD. T3,.QBFLG,(T2) ;AND FLAGS FROM SAME
|
||
LOAD. T4,.QBFLG,(T1) ;AND FLAGS FROM PREVIOUS
|
||
TRNE T4,LBLKBK ;IS THIS A LOCK BLOCK?
|
||
JRST QSKD4 ;YES, WE ARE AT TOP OF QUEUE
|
||
TRNE T4,QBINVS ;IS IT INVISIBLE?
|
||
JRST QSKD3 ;YES, IGNORE IT ENTIRELY
|
||
TRNN T4,QBEXCL ;IS THIS AN EXCLUSIVE REQUEST?
|
||
TRNE T3,QBEXCL ;OR IS ORIGINAL REQUEST EXCLUSIVE?
|
||
JRST QSKD7 ;YES TO EITHER. MUST LOOK AT MASKS
|
||
LOAD. T2,.QBGRP,(T1) ;GET GROUP NUMBER
|
||
CAME T2,QSKDG ;SAME GROUP AS OWNER?
|
||
JRST QSKD13 ;NO, STOP HERE
|
||
JRST QSKD3 ;LOOP BACK UNTIL AT LOCK BLOCK
|
||
|
||
;QSKD CONTINUES ON NEXT PAGE...
|
||
QSKD4: MOVE T3,QSKDT
|
||
LOAD. T3,.QBNRP,(T3) ;GET # OF RESOURCES WANTED
|
||
LOAD. T4,.LBAVL,(T1) ;GET # OF RESOURCES AVAILABLE
|
||
SUB T4,T3 ;SUBTRACT REQUEST
|
||
JUMPL T4,QSKD13 ;NOT ENOUGH AVAILABLE
|
||
STOR. T4,.LBAVL,(T1) ;STORE BACK UPDATED TOTAL
|
||
MOVE T3,QSKDT ;GET BACK ADDR OF Q-BLOCK
|
||
LOAD. T2,.QBFLG,(T3) ;GET FLAGS FROM SAME
|
||
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
|
||
JRST QSKD0 ;AND SCAN AGAIN
|
||
|
||
QSKD5: 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 QSKD2 ;NO, GO CHECK IF THIS Q LOCKED
|
||
QSKD6: MOVE T1,QSKDF ;GET FLAG
|
||
PJRST CPOPJ1## ;SKIP RETURN
|
||
|
||
QSKD7: LOAD. T3,.QBMSK,(T1) ;CHECK FOR MASKS
|
||
SKIPE T4,QSKDM ;IS THERE A MASK FOR THE QUEUE BLOCK
|
||
JUMPN T3,QSKD10 ;YES, DO BOTH HAVE A MASK
|
||
JUMPN T4,QSKD8 ;NO, ONLY ONE?
|
||
JUMPE T3,QSKD13 ;YES, CAN'T GET THE LOCK NOW
|
||
MOVE T4,T3 ;GET ADDRESS OF BLOCK TO USE
|
||
QSKD8: MOVE T3,QSKDN ;GET LENGTH OF MASK BLOCK
|
||
QSKD9: SKIPE (T4) ;ANY BIT ON IN MASK
|
||
JRST QSKD13 ;YES, QUIT
|
||
ADDI T4,1 ;ADVANCE TO NEXT WORD IN MASK
|
||
SOJG T3,QSKD9 ;LOOP OVER WHOLE MASK BLOCK
|
||
JRST QSKD3 ;ENTIRE MASK BLOCK IS ZERO
|
||
|
||
QSKD10: MOVE P1,QSKDN ;LENGTH OF MASK BLOCK
|
||
QSKD11: MOVE P2,0(T3) ;NEXT WORD IN MASK BLOCK
|
||
AND P2,0(T4) ;CLEAR NON-CONFLICTING BITS
|
||
JUMPN P2,QSKD13 ;RETURN IF ANY CONFLICTS
|
||
ADDI T3,1 ;STEP
|
||
ADDI T4,1 ; TO NEXT MASK WORD
|
||
SOJG P1,QSKD11 ;LOOP OVER WHOLE BLOCK
|
||
JRST QSKD3 ;THESE BLOCKS CAN CO-EXIST
|
||
|
||
QSKD13: MOVE T1,QSKDF ;GET FLAG
|
||
POPJ P, ;GIVE ERROR 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 OR ABORTED
|
||
;
|
||
|
||
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
|
||
SETZM LKTMP4 ;FLAG THAT LOCK IS NOT ABORTED
|
||
PUSHJ P,CHKABT ;CHECK TO SEE IF LOCK IS ABORTED
|
||
SETOM LKTMP4 ;YES IT IS ABORTED
|
||
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
|
||
SKIPE LKTMP4 ;WAS LOCK JUST ABORTED?
|
||
JRST LOKSK4 ;YES, GO WAKEUP OR SIGNAL
|
||
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 EXHAUSTED
|
||
LOKSK0: PUSHJ P,QSKD ;SCHEDULE THIS Q-BLOCK
|
||
JRST LOKSK2 ;IT WASN'T LOCKED
|
||
JUMPE T1,LOKSK2 ;IF NOT JUST LOCKED, DON'T INTERRUPT
|
||
LOKSK4: MOVE T1,LKTMP2 ;GET ADDR OF THIS Q-BLOCK
|
||
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,.QBJCH,(T1) ;GET JOB/CONTEXT HANDLE OF USER
|
||
MOVE T2,LKTMP4 ;INDICATE NORMAL OR ABORTED REQUEST
|
||
PUSHJ P,GENPSI ;GENERATE AN INTERRUPT FOR HIM
|
||
POP P,J ;RESTORE J
|
||
JRST LOKSK2 ;AND CONTINUE
|
||
LOKSK3: LOAD. T1,.QBJCH,(T1) ;GET THIS GUY'S JOB NUMBER
|
||
PUSH P,W ;JUST IN CASE W GETS LOST
|
||
PUSHJ P,CTXWAK## ;WAKE HIM UP
|
||
STOPCD .+1,JOB,ENQCWJ ;++CAN'T WAKE JOB/CONTEXT
|
||
POP P,W ;GET IT BACK
|
||
|
||
LOKSK2: MOVE T1,LKTMP2 ;GET Q-BLOCK ADDR AGAIN
|
||
JRST LOKSK1 ;LOOP BACK FOR REST OF Q
|
||
SUBTTL DEADLK -- CHECK QUEUE STRUCTURE FOR DEADLOCK
|
||
|
||
;CALL:
|
||
; PUSHJ P,DEADLK
|
||
; <IF DEADLOCK>
|
||
; <IF NO DEADLOCK>
|
||
|
||
DEADLK: PUSHJ P,SAVE4## ;PRESERVE P1-P4
|
||
PUSHJ P,SAVJW## ;PRESERVE J AND W TOO
|
||
SETZM ENQTBC ;NULL LIST OF REQUESTS TO BE CHECKED
|
||
SETZM ENQHBC ;NULL LIST OF ALREADY CHECKED REQUESTS
|
||
MOVE P3,.CPJCH## ;GET REQUESTER'S JOB/CONTEXT HANDLE
|
||
|
||
DEADJQ: MOVE T1,P3 ;GET THE NEXT JOB/CONTEXT HANDLE
|
||
PUSHJ P,CTXENQ## ;GET START OF JOB/CONTEXT'S QUEUE CHAIN
|
||
STOPCD .+1,JOB,ENQIJC ;++ILLEGAL JOB/CONTEXT HANDLE
|
||
SKIPA P1,T2 ;SAVE IN P1
|
||
|
||
DEADR: LOAD. P1,.QBNJQ,(P1) ;GET THE NEXT QUEUE ENTRY
|
||
JUMPE P1,DEADJ ;NO QUEUE CHAIN, CHECK NEXT JOB
|
||
LOAD. T1,.QBFLG,(P1) ;GET QUEUE BLOCK FLAGS
|
||
TRNE T1,QBOWNR ;IS THIS A REQUEST?
|
||
JRST DEADR ;NO, TRY NEXT QUEUE ENTRY
|
||
LOAD. P2,.QBLB,(P1) ;GET THE LOCK-BLOCK FOR THIS QUEUE ENTRY
|
||
|
||
DEADQ: LOAD. P2,.QBNQ,(P2) ;GET THE NEXT QUEUE ENTRY
|
||
CAMN P1,P2 ;HAVE WE LOOPED BACK TO THE REQUEST?
|
||
JRST DEADR ;YES, CHECK JOB'S NEXT REQUEST
|
||
LOAD. T1,.QBJCH,(P2) ;GET OWNER OF THIS QUEUE ENTRY
|
||
CAMN T1,.CPJCH## ;ARE WE THE OWNER?
|
||
POPJ P, ;YES, DEADLOCK
|
||
SKIPN T2,ENQHBC ;HAS THIS JOB ALREADY BEEN CHECKED?
|
||
MOVEM P2,ENQHBC ;NULL LIST, MAKE NON-EMPTY
|
||
JUMPE T2,DEADQ2 ;AND GO STORE ON CHECK LIST
|
||
DEADQ1: MOVE T4,T2 ;SAVE ORIGINAL POINTER
|
||
LOAD. T3,.QBJCH,(T2) ;GET OWNER OF THIS QUEUE ENTRY
|
||
CAMN T3,T1 ;ALREADY ON CHECK LIST?
|
||
JRST DEADQ ;YES, GET ANOTHER QUEUE ENTRY
|
||
LOAD. T2,.QBCHK,(T2) ;GET NEXT ENTRY IN CHECK LIST
|
||
JUMPN T2,DEADQ1 ;ANY MORE ENTRIES IN CHECK LIST?
|
||
STOR. P2,.QBCHK,(T4) ;NO, PUT REQUEST ON TAIL OF CHECK LIST
|
||
DEADQ2: STOR. T2,.QBCHK,(P2) ;PUT NULL AT END OF CHECK LIST
|
||
SKIPN ENQTBC ;LIST EMPTY?
|
||
MOVEM P2,ENQTBC ;YES, MAKE NOT EMPTY
|
||
JRST DEADQ ;GET ANOTHER QUEUE ENTRY
|
||
|
||
DEADJ: SKIPN P4,ENQTBC ;GET NEXT REQUEST TO BE CHECKED
|
||
JRST CPOPJ1## ;NO JOBS FOUND, NO DEADLOCK!
|
||
LOAD. P3,.QBJCH,(P4) ;GET JOB/CONTEXT HANDLE OF REQUEST
|
||
LOAD. T1,.QBCHK,(P4) ;GET NEXT REQUEST TO BE CHECKED
|
||
MOVEM T1,ENQTBC ;SAVE FOR LATER
|
||
JRST DEADJQ ;GO CHECK OUT THIS JOB
|
||
SUBTTL SUBROUTINE TO GET A LOCK SPECIFICATION FROM USER SPACE
|
||
|
||
;SUBROUTINE TO GET ONE LOCK SPEC (2 TO 5 WORDS) 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 CONTAIN THE FIRST 3 WORDS 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 TABLE ADDRESS IN IT
|
||
; (OR -2/-3/400000+JOB #)
|
||
; IN ADDITION, THE WORD EQLTBL WILL CONTAIN A WORD OF THE
|
||
; FORM XWD LENGTH,ADDRESS FOR THE USERS LOCK-ASSOCIATED TABLE,
|
||
; AND THE WORD EQLMSK WILL CONTAIN A WORD OF THE FORM
|
||
; XWD LENGTH,ADDRESS FOR THE USERS PIE-SLICE LOCK MASK WORD.
|
||
|
||
GETLOK: HRR M,RBLOCK ;GET ADDRESS OF PARAMETERS
|
||
HRRZ T1,LOCKCT ;GET THE NUMBER OF THIS LOCK
|
||
IMUL T1,LOKSIZ ;MULTIPLY BY SIZE
|
||
ADD T1,HDRSIZ ;ADD IN HEADER SIZE
|
||
ADDI M,-1(T1) ;BUMP POINTER, ALLOW FOR PREINCREMENT
|
||
SETZM USRLOK ;CLEAR MONITOR COPY TO ZERO
|
||
MOVE T1,[USRLOK,,USRLOK+1]
|
||
BLT T1,USRLOK+LKMAX-1
|
||
MOVN P1,LOKSIZ ;LENGTH OF PER-LOCK BLOCK
|
||
MOVSI P1,(P1) ;MAKE INTO AN AOBJN POINTER
|
||
GETLK1: PUSHJ P,GETWD1## ;FETCH A WORD
|
||
MOVEM T1,USRLOK(P1) ;SAVE IT
|
||
AOBJN P1,GETLK1 ;LOOP OVER WHOLE BLOCK
|
||
MOVE P3,[USRLOK,,P1] ;SET TO COPY TO AC'S
|
||
BLT P3,P3 ;ZAP!
|
||
TLNE P1,EN%UCW ;CODE WORD?
|
||
JRST GETLK2 ;YES, CAN'T BE BYTE POINTER
|
||
HLRZ T1,P2 ;GET LEFT HALF OF PTR
|
||
CAIN T1,-1 ;IS IT -1?
|
||
HRLI P2,(POINT 7,0) ;YES, MAKE IT INTO A BYTE PTR
|
||
GETLK2: HRRE T1,P1 ;GET CHANNEL #/-1/-2/-3
|
||
CAMN T1,[-1] ;IS THIS A JOB WIDE LOCK?
|
||
HRRI T1,CODMIN(J) ;YES, MAKE 400000+JOB NUMBER
|
||
JUMPL T1,GETLK3 ;LEAVE NOW IF NOT A FILE LOCK
|
||
HRRZS P1 ;ISOLATE CHANNEL NUMBER
|
||
PUSHJ P,SETUF## ;POINT F AT THE DDB
|
||
TDZA T1,T1 ;CHANNEL ILLEGAL OR NOT YET OPEN
|
||
HRRZ T1,DEVACC##(F) ;GET ACCESS TABLE ADDRESS
|
||
CAIL T1,CODMIN ;DOES IT LOOK LIKE A SPECIAL CODE?
|
||
STOPCD .+1,DEBUG,ENQATA ;++BAD ACCESS TABLE ADDRESS
|
||
MOVE P1,USRLOK ;RESTORE P1
|
||
GETLK3: HRRM T1,P4 ;SAVE THIS IN RH OF P4 FOR USE LATER
|
||
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 ASCII STRING
|
||
;CALL:
|
||
; MOVE T1,USERS BYTE STRING
|
||
; PUSHJ P,CHKSTR
|
||
; BAD POINTER RETURN
|
||
; STRING OKAY RETURN
|
||
;USES T1-T2. NEVER RETURNS IF BAD ADDRESS IN THE STRING.
|
||
|
||
CHKSTR: LDB T2,[POINT 3,T1,2] ;FIRST 3 BITS
|
||
CAIN T2,5 ;IS IT A 5 (SPECIAL CODE FOR NUMBER)
|
||
JRST CPOPJ1## ;YES, GIVE GOOD RETURN NOW
|
||
TLNE T1,37 ;ANY INDEX OR INDIRECT BITS
|
||
JRST HDRERA ;YES, THE POINTER IS BAD
|
||
PUSHJ P,SAVE4## ;PRESERVE P1-P4
|
||
MOVEI P1,^D36 ;BITS PER WORD
|
||
LDB P2,[POINT 6,T1,11] ;BITS PER USER BYTE
|
||
JUMPE P2,HDRER1 ;IF ZERO
|
||
CAILE P2,^D36 ;OR MORE THAN A WORD
|
||
JRST HDRER1 ;BAD BYTE SIZE ERROR
|
||
IDIVI P1,(P2) ;COMPUTE BYTES PER WORD
|
||
IMUL P1,%ENQML ;COMPUTE MAXIMUM ALLOWABLE NR. OF BYTES
|
||
MOVE P2,T1 ;SAVE BYTE POINTER
|
||
SETO P3, ;LAST PAGE CHECKED
|
||
CHKST1: IBP P2 ;POINT TO ADDRESS ACTUALLY REFERENCED
|
||
LDB P4,[POINT 9,P2,26] ;PAGE ADDRESS OF THE POINTER
|
||
CAME P4,P3 ;CHECKED LAST TIME?
|
||
PUSHJ P,ADRCHK ;CHECK ADDRESS
|
||
EXCTUX <LDB T2,P2> ;GET A BYTE
|
||
JUMPE T2,CPOPJ1## ;IF END OF STRING
|
||
SOJG P1,CHKST1 ;LOOP OVER MAXIMUM LENGTH
|
||
JRST HDRER2 ;ELSE RETURN ERROR
|
||
|
||
|
||
;ROUTINE TO CHECK AN ADDRESS, CALLED ONLY BY CKST1.
|
||
;CALL WITH BYTE POINTER IN P2, PAGE ADDRESS IN P4.
|
||
;RETURNS WITH LAST PAGE CHECKED IN P3. CLOBBERS T1.
|
||
|
||
ADRCHK: PUSH P,M ;SAVE M
|
||
HRRZ M,P2 ;ADDRESS TO BE CHECKED
|
||
PUSHJ P,GETWDU## ;LOOK AT THE WORD
|
||
MOVE P3,P4 ;UPDATE PAGE LAST CHECKED
|
||
PJRST MPOPJ## ;RESTORE M AND 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: TLNE P1,EN%UCW ;CODE WORD?
|
||
JRST LKOK2 ;YES, CODE IS OK
|
||
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
|
||
JUMPE T2,HDRER1 ;ZERO BYTE SIZE?
|
||
CAILE T2,^D36 ;TOO LARGE?
|
||
JRST HDRER1 ;YES, BAD BYTE SIZE ERROR
|
||
TLNE P2,37 ;INDEXED OR INDIRECT POINTER?
|
||
JRST HDRERA ;YES, ERROR
|
||
LKOK2: HRRE T1,P1 ;GET CHANNEL #
|
||
CAMGE T1,[-3] ;OR LESS THAN -3?
|
||
JRST HDRER6
|
||
JUMPL T1,LKOK3 ;NO DDB IF NEGATIVE
|
||
CAIGE T1,775 ;CAN'T USE CHANNELS 775,776,777
|
||
PUSHJ P,QSTUF ;LEGAL CHANNEL?
|
||
JRST HDRER6 ;YES TO EITHER IS AN ERROR
|
||
LKOK3: 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
|
||
|
||
;
|
||
QSTUF: PUSHJ P,SAVE1## ;SAVE P1
|
||
HRRZ P1,P1 ;CLEAR LEFT HALF
|
||
PJRST SETUF## ;CHECK FOR LEGAL CHANNEL
|
||
;SUBROUTINE TO CHECK IF A USER HAS BEEN QUEUE'D FOR A LOCK
|
||
;
|
||
;CALL:
|
||
; MOVE T1,LOCK-BLOCK-ADDR
|
||
; MOVE T2,JOB-CONTEXT-HANDLE
|
||
; PUSHJ P,CHECKQ
|
||
; HERE IF HE IS Q'ED
|
||
; HERE IF USER NOT Q'D
|
||
;
|
||
;ON NON-SKIP RETURN, T1 WILL HAVE THE Q-BLOCK ADDRESS IN IT
|
||
;ON SKIP RETURN, T1 WILL STILL HAVE THE LOCK-BLOCK ADDRESS IN IT
|
||
;
|
||
;
|
||
CHECKQ: PUSHJ P,SAVE3## ;SAVE P1-P3
|
||
MOVE P1,T1 ;SAVE LOCK BLOCK ADDR
|
||
LOAD. P2,.LBNMS,(T1) ;LENGTH OF RESOURCE MASK
|
||
MOVE P3,T2 ;SAVE JOB/CONTEXT HANDLE
|
||
LOAD. T1,.LBNQ,(T1) ;GET ADDRESS OF NEXT Q-BLOCK
|
||
CHECK2: CAIN T1,(P1) ;ARE WE BACK AT START?
|
||
JRST CPOPJ1## ;YES, SKIP RETURN
|
||
LOAD. T2,.QBJCH,(T1) ;GET THIS Q-BLOCK'S JOB/CONTEXT HANDLE
|
||
CAME T2,P3 ;FOR THIS JOB/CONTEXT?
|
||
JRST CHECK3 ;NO, KEEP LOOKING
|
||
JUMPE P2,CPOPJ ;IF NO MASKS SPECIFIED
|
||
PUSH P,T1 ;SAVE ADDRESS OF THIS QUEUE ENTRY
|
||
LOAD. T1,.QBMSK,(T1) ;ADDRESS OF MASK
|
||
HRRZ T2,EQLMSK ;ADDRESS OF TARGET MASK
|
||
MOVEI T3,(P2) ;LENGTH OF MASK BLOCK
|
||
PUSHJ P,TSTMSK ;SEE IF IDENTICAL
|
||
CAIA ;NO
|
||
JRST TPOPJ## ;RETURN SKIP. HE'S QUEUED
|
||
POP P,T1 ;RESTORE Q-BLOCK ADDRESS
|
||
CHECK3: LOAD. T1,.QBNQ,(T1) ;TO NEXT Q-BLOCK
|
||
JRST CHECK2 ;KEEP GOING
|
||
|
||
;SUBROUTINE TO CHECK IF A LOCK HAS BEEN ABORTED
|
||
;
|
||
;CALL:
|
||
; MOVE T1,LOCK-BLOCK-ADDR
|
||
; PUSHJ P,CHKABT
|
||
; HERE IF LOCK IS ABORTED
|
||
; HERE IF LOCK IS NOT ABORTED
|
||
;
|
||
;ON RETURN, T1 WILL STILL HAVE THE LOCK-BLOCK ADDRESS IN IT
|
||
;
|
||
CHKABT: MOVE T3,T1 ;SAVE LOCK BLOCK ADDR
|
||
CHKAB2: LOAD. T3,.LBNQ,(T3) ;GET ADDRESS OF NEXT Q-BLOCK
|
||
CAIN T3,(T1) ;ARE WE BACK AT START?
|
||
JRST CPOPJ1## ;YES, SKIP RETURN
|
||
LOAD. T4,.QBFLG,(T3) ;GET THIS Q-BLOCK'S FLAGS
|
||
TRNE T4,QBOWNR ;IS THIS THE OWNER OF THE LOCK?
|
||
TRNN T4,QBLABT ;AND IS IT AN ABORTED LOCK?
|
||
JRST CHKAB2 ;NO, SO KEEP GOING
|
||
POPJ P, ;YES, RETURN
|
||
;TSTMSK -- ROUTINE TO COMPARE TWO MASK BLOCKS FOR EQUALITY
|
||
;CALL:
|
||
; MOVEI T1,ADDR-OF-MASK BLOCK
|
||
; MOVEI T2,ADDR-OF MASK BLOCK
|
||
; MOVEI T3,LENGTH
|
||
; PUSHJ P,TSTMSK
|
||
; <IF DIFFERENT>
|
||
; <IF EQUAL>
|
||
|
||
TSTMSK: JUMPE T1,TSTMS1 ;IF ZERO ADDRESS (ASSUMES -1,...,-1)
|
||
MOVE T4,(T1) ;FIRST WORD OF MASK 1
|
||
AOJA T1,TSTMS2 ;INCREMENT POINTER, JOIN PROCESSING
|
||
|
||
TSTMS1: SETO T4, ;ASSUME -1 FOR MISSING BLOCK
|
||
TSTMS2: JUMPN T2,TSTMS3 ;IF NON-ZERO ADDRESS FOR MASK 2
|
||
SETCA T4, ;MASK-2 = -1,...,-1. SEE IF MASK 1 = -1
|
||
JUMPN T4,CPOPJ ;NO, NOT SAME
|
||
SOJG T3,TSTMSK ;THIS WORD MATCHES, CHECK NEXT
|
||
JRST CPOPJ1 ;NO MORE. WHOLE MATCH
|
||
|
||
TSTMS3: EXCTUX <CAME T4,(T2)> ;CHECK THIS WORD
|
||
POPJ P, ;NO MATCH. RETURN FAILURE
|
||
AOS T2 ;MATCH. INCREMENT POINTER FOR BLOCK 2
|
||
SOJG T3,TSTMSK ;CHECK NEXT WORD
|
||
JRST CPOPJ1
|
||
|
||
;SUBROUTINE TO COUNT USERS SHARING A LOCK
|
||
;
|
||
;CALL:
|
||
; MOVE T1,LOCK-BLOCK-ADDR
|
||
; PUSHJ P,COUNTQ
|
||
; HERE WITH COUNT IN T2, LOCK-BLOCK-ADDR STILL IN T1
|
||
;
|
||
|
||
COUNTQ: MOVE T3,T1 ;SAVE LOCK BLOCK ADDR
|
||
SETZ T2, ;INITIALIZE COUNTER
|
||
COUNT2: LOAD. T3,.LBNQ,(T3) ;GET ADDR OF NEXT Q-BLOCK
|
||
CAIN T3,(T1) ;BACK AT START?
|
||
POPJ P, ;YES, RETURN
|
||
LOAD. T4,.QBFLG,(T3) ;GET Q-BLOCK FLAGS
|
||
TRNN T4,QBOWNR ;IS HE THE OWNER?
|
||
JRST COUNT2 ;NO, DON'T COUNT THIS ENTRY
|
||
AOJA T2,COUNT2 ;TRY NEXT BLOCK
|
||
SUBTTL BLDLOK -- SUBROUTINE TO BUILD A LOCK BLOCK
|
||
|
||
|
||
|
||
;SUBROUTINE TO CREATE A LOCK-BLOCK
|
||
;
|
||
;CALL:
|
||
; MOVE T1,HASH-INDEX
|
||
; MOVE T2,FLAGS
|
||
; P1-P4 SETUP BY GETLOK
|
||
; 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
|
||
MOVE T1,%ENQNQ ;GET THE NUMBER OF LOCK BLOCKS
|
||
CAML T1,%ENQMQ ;ARE WE ALREADY AT MAXIMUM?
|
||
JRST DOERR6 ;YES, DON'T EAT UP ALL OF FREE CORE
|
||
MOVEI T2,1 ;ASSUME LENGTH OF CODE/TEXT IS ONE
|
||
TLNE P1,EN%UCW ;CODE WORD?
|
||
JRST GOTLNG ;YES, LENGTH IS 1
|
||
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
|
||
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
|
||
LDB T4,[POINT 6,P2,11] ;GET BYTE SIZE TO
|
||
MOVEI T3,^D36 ;BITS PER WORD
|
||
IDIV T3,T4 ;BYTES PER WORD
|
||
IDIV T2,T3 ;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,GETZWD ;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
|
||
|
||
;CONTINUED ON THE NEXT PAGE...
|
||
;CONTINUED FROM THE PREVIOUS PAGE
|
||
|
||
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 TABLE 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
|
||
PUSHJ P,BLDTBL ;BUILD LOCK-ASSOCIATED TABLE, IF NEEDED
|
||
JRST DOERR6 ;INSUFFICIENT FREE CORE
|
||
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)]
|
||
LDB T3,[POINT 6,P2,11]
|
||
DPB T3,[POINT 6,T2,11]
|
||
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
|
||
SUBTTL ROUTINES TO BUILD AND DELETE A LOCK-ASSOCIATED TABLE.
|
||
|
||
;BLDTBL -- ROUTINE TO BUILD A LOCK-ASSOCIATED TABLE
|
||
;CALL:
|
||
; MOVE T1,LOCK BLOCK ADDRESS
|
||
; PUSHJ P,BLDTBL
|
||
; NO CORE RETURN
|
||
; TABLE POINTER SETUP IN THE LOCK BLOCK
|
||
|
||
BLDTBL: HLRZ T2,EQLTBL ;LENGTH OF TABLE TO GET SPACE FOR
|
||
JUMPE T2,CPOPJ1## ;IF ZERO LENGTH, JUST RETURN
|
||
PUSHJ P,SAVE1## ;SAVE A REGISTER
|
||
MOVE P1,T1 ;COPY POINTER TO LOCK BLOCK
|
||
STOR. T2,.LBTLN,(P1) ;SAVE LENGTH OF THE TABLE TOO
|
||
PUSHJ P,GETZWD ;GET THE SPACE
|
||
POPJ P, ;NO SPACE
|
||
STOR. T1,.LBTBL,(P1) ;SAVE ADDRESS OF THE TABLE
|
||
MOVE T1,P1 ;RESTORE T1
|
||
JRST CPOPJ1## ;AND GIVE GOOD RETURN
|
||
|
||
|
||
;ROUTINE TO DELETE A TABLE (IF ANY) ASSOCIATED WITH A LOCK BLOCK.
|
||
;CALL WITH
|
||
; MOVE T1,LOCK BLOCK ADDRESS
|
||
; PUSHJ P,DLTTBL
|
||
; ALWAYS RETURNS HERE WITH TABLE DELETED
|
||
;USES T2-T4
|
||
|
||
DLTTBL: LOAD. T2,.LBTBL,(T1) ;ADDRESS OF THE TABLE
|
||
JUMPE T2,CPOPJ## ;DONE IF NONE
|
||
PUSH P,T1 ;SAVE ADDRESS OF LOCK BLOCK
|
||
LOAD. T1,.LBTLN,(T1) ;LENGTH OF LOCK-ASSOCIATED TABLE
|
||
PUSHJ P,GIVWDS## ;RETURN THE SPACE TO THE MONITOR
|
||
POP P,T1 ;RESTORE LOCK BLOCK ADDRESS
|
||
SETZ T2, ;ZERO
|
||
STOR. T2,.LBTBL,(T1) ;CLEAR TABLE ADDRESS
|
||
STOR. T2,.LBTLN,(T1) ;AND THE LENGTH
|
||
POPJ P, ;RETURN
|
||
SUBTTL ROUTINES TO MANAGE THE USER TABLE
|
||
|
||
;ROUTINE TO COPY INFORMATION FROM THE USER TO THE LOCK-TABLE
|
||
|
||
STOTBL: SKIPN EQLTBL ;ANY DATA GIVEN
|
||
POPJ P, ;NO, JUST RETURN
|
||
LOAD. T2,.QBFLG,(T1) ;GET FLAGS
|
||
TRNE T2,QBOWNR ;IS THE QUEUE ENTRY THE OWNER
|
||
TRNN T2,QBEXCL ;AND EXCLUSIVELY SO?
|
||
POPJ P, ;EITHER NOT OWNER OR NOT EXCLUSIVE
|
||
PUSH P,T1 ;SAVE ADDRESS OF Q-BLOCK
|
||
LOAD. T1,.QBLB,(T1) ;ADDRESS OF LOCK BLOCK
|
||
LOAD. T2,.LBTBL,(T1) ;ADDRESS OF LOCK-ASSOCIATED TABLE
|
||
JUMPE T2,TPOPJ##
|
||
HRL T2,EQLTBL ;ADDRESS OF USERS DATA
|
||
LOAD. T3,.LBTLN,(T1) ;LENGTH OF MONITORS TABLE
|
||
HLRZ T4,EQLTBL ;LENGTH OF USERS DATA
|
||
CAML T4,T3 ;USERS SHORTER?
|
||
JRST STOTB1 ;NO, COPY AS MUCH AS MONITOR CAN HOLD
|
||
PUSHJ P,CLRTBL ;CLEAR MONITORS TABLE (SO ZERO FILL)
|
||
HLRZ T3,EQLTBL ;AND USE USERS LENGTH (WHICH IS SHORTER)
|
||
STOTB1: ADDI T3,-1(T2) ;LAST WORD ADDRESS
|
||
EXCTUX <BLT T2,(T3)> ;COPY USERS DATA
|
||
JRST TPOPJ## ;RESTORE T1 AND RETURN
|
||
|
||
|
||
;ROUTINE TO CLEAR THE CONTENTS OF THE TABLE IN MONITOR FREE SPACE
|
||
;TO ZEROS
|
||
;CALL WITH T1 POINTING TO LOCK BLOCK.
|
||
|
||
CLRTBL: PUSHJ P,SAVE2## ;PRESERVE P1-P2
|
||
LOAD. P1,.LBTBL,(T1) ;LOAD ADDRESS OF TABLE
|
||
JUMPE P1,CPOPJ## ;IF ZERO, TABLE IS ALREADY ZEROS
|
||
HRL P1,P1 ;COPY ADDRESS TO LEFT HALF
|
||
SETZM (P1) ;CLEAR FIRST WORD
|
||
LOAD. P2,.LBTLN,(T1) ;LENGTH OF THE TABLE
|
||
ADDI P2,-1(P1) ;COMPUTE LAST WORD OF TABLE
|
||
ADDI P1,1 ;MAKE PROPAGATING BLT POINTER
|
||
CAIL P2,(P1) ;LENGTH GREATER THAN ONE?
|
||
BLT P1,(P2) ;YES, CLEAR REST OF TABLE
|
||
POPJ P, ;AND RETURN
|
||
SUBTTL ROUTINES TO BUILD AND DELETE THE MASK BLOCK
|
||
|
||
BLDMSK: SKIPN EQLMSK ;DOES HE NEED THIS?
|
||
JRST CPOPJ1## ;NO, GIVE GOOD RETURN
|
||
PUSHJ P,SAVE1## ;SAVE P1
|
||
MOVE P1,T1 ;ADDRESS OF QUEUE BLOCK
|
||
HLRZ T2,EQLMSK ;LENGTH OF USERS MASK
|
||
LOAD. T3,.QBLB,(P1) ;ADDRESS OF LOCK BLOCK
|
||
LOAD. T4,.LBNMS,(T3) ;LENGTH OF EXISTING MASKS
|
||
JUMPN T4,BLDMS1 ;ALREADY HAVE SOME, CHECK FOR MATCH
|
||
STOR. T2,.LBNMS,(T3) ;STORE LENGTH IN LOCK BLOCK
|
||
JRST BLDMS2 ;JOIN PROCESSING
|
||
|
||
BLDMS1: CAME T4,T2 ;ARE THEY BOTH THE SAME?
|
||
JRST MWLERR ;NO, THIS IS AN ERROR
|
||
BLDMS2: PUSHJ P,GETZWD ;GET THE SPACE
|
||
JRST DOERR6 ;NO MORE FREE CORE
|
||
STOR. T1,.QBMSK,(P1) ;IN THE QUEUE BLOCK
|
||
ADDI T2,-1(T1) ;COMPUTE LAST WORD TO BE COPIED
|
||
HRL T1,EQLMSK ;SOURCE ADDRESS FOR COPY
|
||
EXCTUX <BLT T1,(T2)> ;COPY THE MASK
|
||
MOVE T1,P1 ;RESTORE T1
|
||
JRST CPOPJ1## ;AND RETURN
|
||
|
||
|
||
;DLTMSK -- ROUTINE TO RETURN A MULTI-RESOURCE LOCK MASK BLOCK
|
||
;CALL:
|
||
; MOVEI T2,Q-BLOCK ADDRESS
|
||
; PUSHJ P,DLTMSK
|
||
; <ALWAYS RETURNS HERE WITH MASK BLOCK DELETED>
|
||
;PRESERVES ALL AC'S
|
||
|
||
DLTMSK: PUSHJ P,SAVT## ;PRESERVE T1-T4
|
||
LOAD. T3,.QBLB,(T2) ;LOCATION OF THE LOCK BLOCK
|
||
LOAD. T2,.QBMSK,(T2) ;GET ADDRESS
|
||
JUMPE T2,CPOPJ## ;IF NONE
|
||
LOAD. T1,.LBNMS,(T3) ;THEN LENGTH OF MASK BLOCK
|
||
PJRST GIVWDS## ;RETURN SPACE TO MONITOR
|
||
SUBTTL QHIM -- SUBROUTINE TO BUILD A Q-BLOCK
|
||
|
||
;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,GETZWD ;GET SOME FREE SPACE FOR IT
|
||
POPJ P, ; NO MORE LEFT!
|
||
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 POOLED 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: MOVE T2,.CPJCH## ;GET OUR JOB/CONTEXT HANDLE
|
||
STOR. T2,.QBJCH,(T1) ;STORE JOB/CONTEXT HANDLE
|
||
|
||
;CONTINUED ON THE NEXT PAGE
|
||
;CONTINUED FROM THE PREVIOUS PAGE
|
||
|
||
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) ;SET GROUP NUMBER
|
||
JRST CPOPJ1## ; AND EXIT
|
||
SUBTTL GENPSI AND CHKCNT
|
||
|
||
;SUBROUTINE TO GENERATE AN INTERRUPT FOR A USER
|
||
;
|
||
;CALL:
|
||
; MOVE T1,Q-BLOCK ADDRESS
|
||
; MOVE T2,FLAG ;0 FOR NORMAL, -1 FOR ABORTED REQUEST
|
||
; PUSHJ P,GENPSI
|
||
; RETURN HERE ALWAYS
|
||
;
|
||
;
|
||
GENPSI:
|
||
MOVE T3,T2 ;SAVE THE FLAG
|
||
LOAD. T2,.QBRID,(T1) ;GET REQUEST ID FROM Q-BLOCK
|
||
SKIPE T3 ;WAS THIS AN ABORTED REQUEST?
|
||
TLO T2,(1B0) ;YES, LIGHT BIT IN STATUS WORD
|
||
SIGNAL C$QUE ;SIGNAL INTERRUPT
|
||
JFCL
|
||
POPJ P, ;RETURN
|
||
|
||
|
||
|
||
|
||
|
||
;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
|
||
CAILE T2,(T3) ;MORE TO GO?
|
||
POPJ P, ;YES
|
||
JRST CPOPJ1## ;NO, GIVE SKIP RETURN
|
||
SUBTTL ENQMIN -- ONCE A MINUTE CODE FOR QUESER
|
||
|
||
ENQMIN::PUSHJ P,SAVE4## ;PRESERVE P1-P4
|
||
MOVEI P1,HSHLEN##-1 ;START AT TOP OF HASH HEADER TABLE
|
||
ENQMN1: MOVEI P2,HSHTAB##(P1) ;START POINTER
|
||
ENQMN2: LOAD. P2,.LBNHS,(P2) ;POINT TO NEXT LOCK BLOCK ON CHAIN
|
||
CAIN P2,HSHTAB##(P1) ;REACHED END?
|
||
JRST ENQMN4 ;YES, CHECK NEXT CHAIN
|
||
LOAD. T2,.LBFLG,(P2) ;GET FLAGS
|
||
TRNN T2,LBLLTL ;IS THIS A LONG-TERM-LOCK?
|
||
JRST ENQMN2 ;NO, GET NEXT LOCK BLOCK
|
||
LOAD. T3,.LBNQ,(P2) ;YES, LOAD THE Q-BLOCK CHAIN POINTER
|
||
CAIE T3,(P2) ;IS THIS CHAIN EMPTY?
|
||
JRST ENQMN2 ;NO, CHECK NEXT BLOCK
|
||
LOAD. T3,.LBPLT,(P2) ;FETCH TIMER VALUE
|
||
SOJL T3,ENQMN3 ;COUNT DOWN, JUMP IF EXPIRED
|
||
STOR. T3,.LBPLT,(P2) ;RESTORE COUNT
|
||
JRST ENQMN2 ;CHECK NEXT BLOCK
|
||
|
||
ENQMN3: MOVEI T1,(P2) ;ADDRESS OF THIS LOCK BLOCK
|
||
LOAD. P2,.LBLHS,(P2) ;BACKUP POINTER NOW, SINCE DELETING
|
||
PUSHJ P,DLTLOK ;DELETE THE LOCK BLOCK
|
||
JRST ENQMN2 ;SEARCH REST OF CHAIN
|
||
|
||
;HERE TO ADVANCE TO THE NEXT HASH CHAIN
|
||
|
||
ENQMN4: SOJGE P1,ENQMN1 ;DECREMENT POINTER, LOOP OVER ALL
|
||
POPJ P, ;RETURN AFTER CHECKING ALL LOCK BLOCKS
|
||
SUBTTL ENQSDT -- SET DAYTIME CODE FOR QUESER
|
||
|
||
;SUBROUTINE TO FIX UP DATE-TIME STAMPS IN ALL LOCK BLOCKS
|
||
;
|
||
;CALL:
|
||
; MOVE T1,DATE-TIME-OFFSET
|
||
; PUSHJ P,ENQSDT
|
||
; RETURN HERE ALWAYS
|
||
;
|
||
;PRESERVES ALL
|
||
|
||
ENQSDT::PUSHJ P,SAVE4## ;PRESERVE P1-P4
|
||
MOVEI P1,HSHLEN##-1 ;START AT TOP OF HASH HEADER TABLE
|
||
|
||
ENQSD1: MOVEI P2,HSHTAB##(P1) ;START POINTER
|
||
|
||
ENQSD2: LOAD. P2,.LBNHS,(P2) ;POINT TO NEXT LOCK BLOCK ON CHAIN
|
||
CAIN P2,HSHTAB##(P1) ;REACHED END?
|
||
JRST ENQSD3 ;YES, CHECK NEXT CHAIN
|
||
LOAD. P3,.LBTIM,(P2) ;GET TIME-STAMP OF LOCK
|
||
JUMPE P3,ENQSD2 ;IF 0, NO TIME-STAMP WAS SET
|
||
ADD P3,T1 ;FUDGE UP TIME-STAMP
|
||
STOR. P3,.LBTIM,(P2) ;STORE CORRECTED VALUE
|
||
JRST ENQSD2 ;CHECK NEXT BLOCK
|
||
|
||
;HERE TO ADVANCE TO THE NEXT HASH CHAIN
|
||
|
||
ENQSD3: SOJGE P1,ENQSD1 ;DECREMENT POINTER, LOOP OVER ALL
|
||
POPJ P, ;RETURN AFTER CHECKING ALL LOCK BLOCKS
|
||
SUBTTL MHASH -- SUBROUTINE TO HASH TWO NUMBERS TOGETHER
|
||
|
||
;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
|
||
SUBTTL HASH -- SUBROUTINE TO HASH A STRING
|
||
|
||
;SUBROUTINE TO HASH A STRING
|
||
;
|
||
;CALL:
|
||
; MOVE T2,STRING-POINTER
|
||
; PUSHJ P,STHASH
|
||
; RETURN HERE WITH HASH IN T1
|
||
;
|
||
|
||
STHASH: PUSHJ P,SAVE1## ;PRESERVE P1
|
||
MOVEM T2,EQTMP1 ;SAVE POINTER
|
||
SETZM EQTMP2 ;CLEAR ANSWER REGISTER
|
||
LDB T4,[POINT 6,T2,11] ;GET BYTE SIZE
|
||
MOVEI T3,44 ;COMPUTE BYTES/WORD
|
||
IDIV T3,T4 ;BYTE/WORD IN T3
|
||
MOVE P1,T3 ; INTO P1
|
||
STHSH1: MOVE T4,P1 ;GET BYTES/WORD FOR COUNT
|
||
MOVE T3,[POINT 7,T2]
|
||
LDB T2,[POINT 6,EQTMP1,11]
|
||
DPB T2,[POINT 6,T3,11]
|
||
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 CHARACTERS
|
||
XOR T2,EQTMP2 ;XOR THIS INTO ANSWER WORD
|
||
ROT T2,1 ;ROTATE TO MUSH BITS A LITTLE MORE
|
||
MOVEM T2,EQTMP2 ;AND RE-STORE THE 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
|
||
SUBTTL HASH -- SUBROUTINE TO HASH A LOCK NAME
|
||
|
||
;SUBROUTINE TO CALCULATE AN INDEX INTO THE HASH TABLE
|
||
;
|
||
;CALL:
|
||
; MOVE P1,FLAGS,,ACCESS-TABLE-ADDR/-2/-3/400000+JOB #
|
||
; MOVE P2,USER CODE OR STRING POINTER
|
||
; PUSHJ P,HASH
|
||
; NORMAL RETURN
|
||
;
|
||
|
||
HASH: HRRE T1,P4 ;GET ACCESS-TABLE-ADDR/-2/-3/400000+JOB #
|
||
MOVE T2,P2 ; AND STRING POINTER
|
||
TLNE P1,EN%UCW ;CODE WORD?
|
||
JRST HASH2 ;YES, DON'T HASH IT
|
||
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 TABLE 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
|
||
SUBTTL FNDLOK -- SUBROUTINE TO FIND A LOCK BLOCK
|
||
|
||
;SUBROUTINE TO FIND A LOCK-BLOCK
|
||
;
|
||
;CALL:
|
||
; SET UP P1-P4 BY GETLOK
|
||
; PUSHJ P,FNDLOK
|
||
;
|
||
; RETURN HERE IF NOT FOUND
|
||
; HERE IF FOUND, ADDRESS OF LOCK-BLOCK IN T1
|
||
;
|
||
;
|
||
FNDLOK: 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 TABLE ADDRESS
|
||
CAIE T2,(P4) ;IS THIS A MATCH?
|
||
JRST FNDLK2 ;NO, TRY NEXT ENTRY
|
||
PUSHJ P,STRCMP ;COMPARE THE STRINGS
|
||
JRST FNDLK2 ;NO MATCH
|
||
MOVE T1,EQTMP1 ;GET BACK LOCK-BLOCK ADDRESS
|
||
PJRST CPOPJ1## ;SKIP RETURN
|
||
|
||
FNDLK2: MOVE T1,EQTMP1 ;GET LOCK-BLOCK ADDRESS
|
||
JRST FNDLK1 ;GO ON
|
||
SUBTTL STRCMP -- SUBROUTINE TO COMPARE TWO STRINGS
|
||
|
||
;SUBROUTINE TO COMPARE STRINGS OR USER CODES
|
||
;
|
||
;CALL:
|
||
; MOVE T1,LOCK-BLOCK-ADDRESS
|
||
; P1-P4 SET UP BY GETLOK
|
||
; PUSHJ P,STRCMP
|
||
; HERE IF NO MATCH
|
||
; RETURN HERE IF MATCH
|
||
;
|
||
;
|
||
|
||
STRCMP: TLNE P1,EN%UCW ;CODE WORD?
|
||
JRST STRCMC ;YES
|
||
LDB T3,[POINT 3,P2,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, ;NO
|
||
PUSHJ P,SAVE1## ;SAVE P1
|
||
MOVE P1,[POINT 7,O.TEXT(T1)] ;SET UP PTR TO TEXT
|
||
LDB T3,[POINT 6,P2,11] ;BYTE SIZE
|
||
DPB T3,[POINT 6,P1,11]
|
||
MOVE T2,P2 ;COPY STRING POINTER
|
||
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 T3,P2 ;MATCH?
|
||
POPJ P, ;NO
|
||
PJRST CPOPJ1## ;YES, SKIP RETURN
|
||
SUBTTL GETLVL -- SUBROUTINE TO FIND THE HIGHEST LEVEL # FOR A GIVEN USER
|
||
|
||
;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:
|
||
IFN FTMP,<
|
||
PUSHJ P,EQLOCK
|
||
>
|
||
SETO T1, ;ASSUME THE QUEUE IS EMPTY
|
||
SETZM REQCNT ;CLEAR REQUEST COUNT
|
||
HRRZ T2,.PDEQJ##(W) ;GET START OF JOB Q
|
||
GTLVL2: 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/-2/-3/400000+JOB #
|
||
CAIE P2,-3 ;IS THIS A PRIVILEGED LOCK?
|
||
JRST GTLVL3 ;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 GTLVL4 ; AND KEEP GOING
|
||
|
||
GTLVL3: HRRE T3,T1 ;GET HIGHEST USER'S LEVEL
|
||
CAMLE T4,T3 ;A NEW HIGH?
|
||
HRR T1,T4 ;YES
|
||
GTLVL4: LOAD. T2,.QBNJQ,(T2) ;RETURN ADDRESS OF Q-BLOCK
|
||
JRST GTLVL2 ;NO, MORE TO GO
|
||
SUBTTL -- MISCELLANEOUS SUBROUTINES
|
||
|
||
;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
|
||
HRRZM M,RBLOCK ;SAVE THIS ADDRESS FOR LATER
|
||
HLRZ T3,T1 ;GET FUNCTION FROM CALL
|
||
MOVEM T3,FCODE ; AND SAVE IT FOR USE LATER
|
||
CAILE T3,(T2) ;IS IT WITHIN RANGE?
|
||
JRST NDUERR ;NO, ERROR RETURN
|
||
TLO M,FLMCOM ;SO ERRORS RETURN INSTEAD OF EXIT
|
||
JRST CPOPJ1## ; TO STOTAC. THEN GIVE GOOD RETURN
|
||
|
||
|
||
;ROUTINE TO ALLOCATE FREE CORE
|
||
;
|
||
;CALL:
|
||
; MOVEI T2,NUMBER OF WORDS
|
||
; PUSHJ P,GETZWD
|
||
; ERROR RETURN
|
||
; NORMAL RETURN
|
||
;USES T1,T3,T4
|
||
|
||
GETZWD: PUSH P,T2 ;
|
||
PUSHJ P,GETWDS## ;GET BLOCK
|
||
PJRST T2POPJ##
|
||
MOVE T2,(P) ;LENGTH
|
||
ADDI T2,-1(T1) ;LAST WORD
|
||
SETZM (T1) ;CLEAR FIRST
|
||
MOVEI T3,1(T1) ;DESTINATION
|
||
HRL T3,T1 ;SOURCE
|
||
BLT T3,(T2) ;CLEAR BLOCK
|
||
JRST T2POJ1## ;
|
||
;SUBROUTINE TO GET THE EQ RESOURCE TO INTERLOCK SMP SYSTEMS
|
||
;
|
||
;CALL:
|
||
; PUSHJ P,EQLOCK
|
||
; <RETURN HERE WITH INTERLOCK>
|
||
;
|
||
;AUTOMATICALLY FREES LOCK WHEN CALLER OF EQLOCK RETURNS
|
||
|
||
IFN FTMP,<
|
||
EQLOCK: PUSH P,NQERRF
|
||
PUSH P,LOKSIZ
|
||
PUSH P,HDRSIZ
|
||
PUSH P,RBLOCK
|
||
PUSH P,FCODE
|
||
PUSH P,LOCKCT
|
||
PUSH P,REQID
|
||
PUSH P,TIMLIM
|
||
PUSH P,HILEVL
|
||
PUSH P,SBLOCK
|
||
PUSHJ P,UPEQ ;WAIT FOR RESOURCE
|
||
POP P,SBLOCK
|
||
POP P,HILEVL
|
||
POP P,TIMLIM
|
||
POP P,REQID
|
||
POP P,LOCKCT
|
||
POP P,FCODE
|
||
POP P,RBLOCK
|
||
POP P,HDRSIZ
|
||
POP P,LOKSIZ
|
||
POP P,NQERRF
|
||
PUSHJ P,@0(P) ;RETURN TO CALLER OF EQLOCK
|
||
CAIA ;IF NON-SKIP RETURN
|
||
AOS -1(P) ;ADVANCE RETURN
|
||
POP P,(P) ;CLEAR EQLOCK CALLER'S ADDRESS
|
||
PJRST DWNEQ ;FREE RESOURCE AND RETURN
|
||
|
||
;SUBROUTINE TO CHECK TO SEE IF THE CURRENT JOB OWNS THE EQ
|
||
;RESOURCE
|
||
;CALL:
|
||
; PUSHJ P,HAVEQ
|
||
; <NO>
|
||
; <YES>
|
||
;PRESERVES ALL
|
||
|
||
HAVEQ:: PUSH P,T1
|
||
HRRZ T1,EQUSER##
|
||
CAIE T1,(J)
|
||
JRST TPOPJ##
|
||
JRST TPOPJ1##
|
||
|
||
UPEQ: PUSH P,F ;SAVE F
|
||
SETZ F, ;DON'T TOUCH EVM
|
||
PUSHJ P,EQWAIT## ;GET THE EQ
|
||
JRST FPOPJ## ;AND RESTORE F
|
||
DWNEQ: PUSH P,F ;SAVE F
|
||
SETZ F, ;DON'T TOUCH EVM
|
||
PUSHJ P,EQFREE## ;GIVE UP THE EQ
|
||
JRST FPOPJ## ;AND RESTORE F
|
||
>
|
||
;SUBROUTINE TO PERFORM CLEAN-UP ON A RESET (OR LOGOUT, OR POP)
|
||
;
|
||
;CALL: HRRZ T1,NEWJCH
|
||
; XMOVEI T2,NEWJQ
|
||
; PUSHJ P,ENQRST -OR- PUSHJ P,ENQLGO -OR- PUSHJ P,ENQPOP
|
||
; RETURN HERE ALWAYS
|
||
;
|
||
ENQRST::TDZA T4,T4 ;INDICATE RESET (DEQ ALL BUT NDR)
|
||
ENQLGO::MOVEI T4,1 ;INDICATE LOGOUT (DEQ ALL)
|
||
CAIA
|
||
ENQPOP::MOVEI T4,2 ;INDICATE POP (RENAME TO NEW JCH)
|
||
PUSHJ P,FNDPDS## ;FIND HIS PDB
|
||
SKIPN .PDEQJ##(W) ;DOES HE HAVE A QUEUE
|
||
POPJ P, ;IF NULL QUEUE
|
||
PUSHJ P,SAVE3## ;SAVE SOME ACS
|
||
MOVE P1,T4 ;SAVE THE ENTRY CODE
|
||
MOVE P2,T1 ;SAVE NEW JCH (FOR POPIT)
|
||
MOVE P3,T2 ;SAVE NEW JOB QUEUE ADDRESS (FOR POPIT)
|
||
IFN FTMP,<
|
||
PUSHJ P,EQLOCK ;INTERLOCK THE ENQ/DEQ DATABASE
|
||
>
|
||
MOVE T2,.PDEQJ##(W) ;GET START OF JOB QUEUE
|
||
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,@[RSTIT ;RESET
|
||
DEQIT ;LOGOUT ALWAYS DEQUEUES
|
||
POPIT](P1) ;POP
|
||
JRST RESET2 ;GO BACK TO START OF LOOP
|
||
|
||
RSTIT: LOAD. T4,.QBFLG,(T1) ;GET FLAGS FOR THIS Q-BLOCK
|
||
TRNN T4,QBOWNR ;IS THIS THE OWNER OF THE LOCK?
|
||
PJRST DEQIT ;NO, DON'T CHECK ETERNAL FLAG
|
||
TRNN T4,QBLNDR ;NOT TO BE DELETED ON RESET?
|
||
PJRST DEQIT ;IF NDR OPTION NOT SELECTED.
|
||
SETO T4, ;CHANNEL OF 777
|
||
STOR. T4,.QBCHN,(T1) ;WON'T MATCH ON NEXT FILE OPERATION
|
||
PUSHJ P,TSTAAC ;DO WE NEED TO INCRMENT THE A.T. COUNT?
|
||
POPJ P, ;NO. GO LOOK AT NEXT REQUEST
|
||
LOAD. T3,.QBLB,(T1) ;LOCK BLOCK ADDRESS
|
||
LOAD. T4,.LBFLG,(T3) ;YES, GET FLAGS FOR THIS LOCK BLOCK
|
||
TRO T4,LBLAUC ;NOTE THAT USE COUNT IS INCREMENTED
|
||
STOR. T4,.LBFLG,(T3) ;RESET FLAGS IN LOCK BLOCK
|
||
LOAD. T1,.LBACC,(T3) ;GET ACCESS TABLE ADDRESS
|
||
CAIGE T1,CODMIN ;IS IT REALLY A SPECIAL CODE?
|
||
PUSHJ P,FILIRC## ;NO, INCREMENT READER COUNT
|
||
POPJ P, ;LOOK FOR NEXT Q-BLOCK
|
||
|
||
POPIT: PUSHJ P,[PUSHJ P,SAVT## ;SAVE ALL TEMP ACS
|
||
LOAD. T1,.QBLB,(T1) ;GET LOCK BLOCK ADDRESS
|
||
MOVE T2,P2
|
||
PJRST CHECKQ] ;SEE IF USER IS ALREADY QUEUED
|
||
PJRST DEQIT ;YES, DEQUEUE THIS LOCK
|
||
LOAD. T4,.QBLJQ,(T1) ;GET ADDRESS OF JOB QUEUE HEADER
|
||
STOR. T2,.QBNJQ,(T4) ;POINT JOB QUEUE TO NEXT Q-BLOCK
|
||
SKIPE T2 ;IS THERE REALLY A NEXT Q-BLOCK?
|
||
STOR. T4,.QBLJQ,(T2) ;YES, POINT IT BACK TO JOB QUEUE HEADER
|
||
STOR. P2,.QBJCH,(T1) ;STORE NEW JCH IN Q-BLOCK
|
||
SE1XCT< LOAD. T3,.QBNJQ,(P3) ;GET FIRST Q-BLOCK IN NEW JOB QUEUE
|
||
STOR. T1,.QBNJQ,(P3)> ;POINT NEW JOB QUEUE HEADER TO Q-BLOCK
|
||
STOR. T3,.QBNJQ,(T1) ;POINT NEW FIRST Q-BLOCK TO OLD Q-BLOCK
|
||
SKIPE T3 ;IS THERE REALLY AN OLD FIRST Q-BLOCK?
|
||
STOR. T1,.QBLJQ,(T3) ;YES, POINT IT BACK TO THE NEW Q-BLOCK
|
||
POPJ P, ;LOOK FOR NEXT Q-BLOCK
|
||
|
||
;TSTAAC -- ROUTINE TO DETERMINE IF WE NEED TO INCREMENT THE
|
||
; READ COUNT IN THE ACCESS TABLE TO MAKE IT STAY
|
||
; AROUND.
|
||
;CALL:
|
||
; MOVE T1,Q-BLOCK ADDRESS
|
||
; LOAD. T3,.QBLB,(T1) ;LOCK BLOCK ADDRESS
|
||
; PUSHJ P,TSTAAC
|
||
; <NO NEED TO INCREMENT>
|
||
; <MUST INCREMENT>
|
||
|
||
TSTAAC: PUSHJ P,SAVE4## ;SAVE P1-P4
|
||
HRRZ P1,.PDEQJ##(W) ;START OF JOBS QUEUE LIST
|
||
LOAD. P4,.LBACC,(T3) ;ACCESS TABLE TO BE CHECKED
|
||
TSTAA1: LOAD. P2,.QBLB,(P1) ;LOCK BLOCK ADDRESS OF THIS ENTRY
|
||
LOAD. P3,.LBACC,(P2) ;ACCESS TABLE FOR THIS LOCK
|
||
CAIE P3,(P4) ;SAME?
|
||
JRST TSTAA2 ;NO, LOOK AT NEXT
|
||
LOAD. P3,.LBFLG,(P2) ;YES, SEE IF INCREMENTED
|
||
TRNE P3,LBLAUC ; BY CHECKING FLAG
|
||
POPJ P, ;YES. NO NEED TO INCREMENT AGAIN
|
||
TSTAA2: CAIN P1,(T1) ;SEARCHED TO CURRENT Q-BLOCK
|
||
JRST CPOPJ1## ;YES. NOT YET INCREMENTED
|
||
LOAD. P1,.QBNJQ,(P1) ;ADVANCE TO NEXT Q-BLOCK
|
||
JUMPN P1,TSTAA1 ;AND CHECK IT TOO
|
||
STOPCD .+1,JOB,ENQQFU ;++Q-BLOCKS FOULED UP
|
||
JRST CPOPJ1## ;INCRMENT AND HOPE
|
||
|
||
;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:
|
||
; HRRI P1,CHANNEL #
|
||
; PUSHJ P,ENQCLS##
|
||
; HERE IF THERE WERE LOCKS STILL OUT
|
||
; HERE IF USER HAD NO LOCKS OUTSTANDING
|
||
;PRESERVES ALL
|
||
;
|
||
ENQCLS::PUSHJ P,SAVJW## ;SAVE JOB/CONTEXT HANDLE
|
||
MOVE J,.CPJOB## ;GET USER'S JOB #
|
||
PUSHJ P,FNDPDS## ;GET HIS PDB
|
||
SKIPN .PDEQJ##(W) ;ANY LOCKS FOR THIS JOB?
|
||
JRST CPOPJ1## ;NO, LEAVE QUICKLY
|
||
PUSHJ P,SAVT## ;PRESERVE SOME AC'S
|
||
HRRZ T2,.PDEQJ##(W) ;GET START OF JOB Q
|
||
ENQCL2: 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 ENQCL2 ;NO, GET NEXT Q-BLOCK IN JOB QUEUE
|
||
|
||
|
||
;ROUTINE TO VERIFY THAT AN NDR LOCK IS PERMISSIBLE ON A SPECIFIED FILE.
|
||
;CALL:
|
||
; MOVE T1,LOCK-BLOCK ADDRESS
|
||
; PUSHJ P,OKNDR
|
||
; ERROR
|
||
; OK
|
||
;PRESERVES ALL IF NO ERROR. ELSE ERROR CODE IN T1
|
||
|
||
OKNDR: PUSH P,T1 ;SAVE T1
|
||
LOAD. T1,.LBACC,(T1) ;GET ACCESS TABLE ADDRESS
|
||
CAIL T1,CODMIN ;IS IT REALLY A SPECIAL CODE?
|
||
JRST OKNDR1 ;YES, OK
|
||
PUSHJ P,FILGFC## ;GHOST FILE? (BEING CREATED OR SUPERSEDED)
|
||
JRST OKNDR2 ;YES, ERROR
|
||
OKNDR1: MOVSI T1,JP.ENQ ;ENQ PRIVILEGE BIT
|
||
PUSHJ P,[PUSHJ P,SAVT## ;PRESERVE THE TEMP ACS
|
||
PJRST PRVBIT##] ;CHECK PRIVILEGE
|
||
JRST TPOPJ1## ;OK, GIVE GOOD RETURN
|
||
POP P,T1 ;RESTORE T1
|
||
MOVEI T1,ENQED% ;GIVE INSUFFICIENT PRIVILEGES ERROR
|
||
POPJ P, ;GIVE ERROR RETURN
|
||
|
||
OKNDR2: POP P,T1 ;RESTORE T1
|
||
MOVEI T1,ENQGF% ;CANNOT USE EQ.FEL ON A GHOST FILE
|
||
POPJ P, ;ERROR RETURN
|
||
|
||
;ENQNDR -- CHECK FOR OUTSTANDING LOCKS WITH 'NO
|
||
; DELETE ON RESET' SET.
|
||
;
|
||
;CALL:
|
||
; MOVE T1,ACCESS TABLE ADDRESS
|
||
; PUSHJ P,ENQNDR
|
||
; <IF ANY SET>
|
||
; <IF NONE SET>
|
||
;PRESERVES ALL
|
||
|
||
ENQNDR::PUSHJ P,SAVE4## ;SAVE P1-P4
|
||
MOVEI P1,HSHLEN##-1 ;TABLE LENGTH
|
||
ENQND1: MOVEI P2,HSHTAB##(P1) ;
|
||
ENQND2: LOAD. P2,.LBNHS,(P2) ;GET NEXT
|
||
CAIN P2,HSHTAB##(P1) ;END OF CHAIN?
|
||
JRST ENQND4 ;YES, CHECK NEXT HEADER
|
||
LOAD. P3,.LBACC,(P2) ;GET A.T. ADDRESS
|
||
CAIE P3,(T1) ;TARGET?
|
||
JRST ENQND2 ;NO, LOOK AT NEXT LOCK BLOCK
|
||
LOAD. P3,.LBNQ,(P2) ;GET Q-BLOCK LIST
|
||
ENQND3: CAIN P3,(P2) ;END OF Q-BLOCK CHAIN?
|
||
JRST ENQND2 ;YES, CHECK NEXT LOCK BLOCK
|
||
LOAD. P4,.QBFLG,(P3) ;Q-BLOCK FLAGS
|
||
TRNE P4,QBLNDR ;NDR REQUEST
|
||
POPJ P, ;YES, FAIL NOW
|
||
LOAD. P3,.QBNQ,(P3) ;NO. GET NEXT Q-BLOCK
|
||
JRST ENQND3 ;LOOP OVER Q-BLOCK CHAIN
|
||
|
||
ENQND4: SOJGE P1,ENQND1 ;ADVANCE TO NEXT BIN HEADER
|
||
JRST CPOPJ1## ;IF DONE
|
||
|
||
|
||
$INIT
|
||
|
||
;ENQINI -- INITIALIZE THE QUEUEING SYSTEM (CALLED FROM SYSINI)
|
||
;
|
||
;CALL:
|
||
; PUSHJ P,ENQINI
|
||
; RETURN HERE ALWAYS
|
||
|
||
ENQINI::SKIPE [HSHTAB##] ;SKIP IF NO INITIALIZATION TO BE DONE
|
||
SKIPL T1,[-HSHLEN##,,HSHTAB##] ;AOBJN POINTER TO HASH TABLE
|
||
POPJ P, ;DONE IF NO ENQ/DEQ
|
||
ENQIN1: HRRM T1,(T1) ;MAKE RIGHT HALF POINT TO ITSELF
|
||
HRLM T1,(T1) ;AND LEFT HALF TOO
|
||
AOBJN T1,ENQIN1 ;BUMP POINTER AND COUNTER
|
||
POPJ P, ;TABLE ALL DONE
|
||
|
||
$HIGH
|
||
|
||
;ENQJBI -- INITIALIZE THE PROCESS DATA BLOCK (FOR LOGIN OR PUSH)
|
||
;
|
||
;CALL:
|
||
; PUSHJ P,ENQJBI
|
||
; RETURN HERE ALWAYS
|
||
|
||
ENQJBI::SETZM .PDEQJ##(W) ;ZERO THE JOB QUEUE
|
||
POPJ P, ;DONE
|
||
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 PRIVILEGE 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 DISCREPANCY
|
||
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
|
||
ERCODE MWLERR,ENQME% ;(27) MASK WORD LENGTH ERROR
|
||
ERCODE TBLERR,ENQTE% ;(30) TABLE ERROR
|
||
ERCODE ABTERR,ENQAB% ;(31) ATTEMPT TO ENQ. AN ABORTED LOCK
|
||
; ERCODE NDRERC,ENQGF% ;(32) ATTEMPT TO LOCK WITH NDR ON A 'GHOST FILE'
|
||
; ERCODE DEDERR,ENQDD% ;(33) DEADLOCK DETECTED
|
||
; ERCODE TLEERR,ENQTL% ;(34) TIME LIMIT EXCEEDED
|
||
|
||
|
||
;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 "ENQIT"
|
||
|
||
|
||
;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.
|
||
;
|
||
;WHEN ADDING OR DELETING VARIABLES
|
||
;FROM THIS AREA, BE SURE TO
|
||
;UPDATE THE VALUE OF QDBLEN IN
|
||
;COMMON SO IT IS THE SAME AS
|
||
;THE VALUE COMPUTED HERE
|
||
;
|
||
|
||
|
||
ENQ...==0 ;VARIABLE FOR WORD MACRO
|
||
|
||
DEFINE WORD(SYM),<
|
||
SYM==.CPQTS##+ENQ...
|
||
ENQ...==ENQ...+1
|
||
>
|
||
|
||
DEFINE BLOK(SYM,N),<
|
||
SYM==.CPQTS##+ENQ...
|
||
ENQ...==ENQ...+N
|
||
>
|
||
|
||
BLOK(ENQFLG,1) ;-1 IF ENQ., ELSE 0
|
||
;***DO NOT SEPARATE OR REORDER THE FOLLOWING WORDS***
|
||
BLOK(USRLOK,3) ;COPY OF USERS LOCK BLOCK ARGUMENT
|
||
BLOK(EQLMSK,1) ;COPY OF MASK WORD FROM USER
|
||
BLOK(EQLTBL,1) ;COPY OF TABLE POINTER FROM USER
|
||
;***THE PREVIOUS GROUP MUST BE LKMAX WORDS LONG***
|
||
WORD(LOKSIZ) ;SIZE OF LOCK ENTRY FOR THIS CALL
|
||
WORD(HDRSIZ) ;SIZE OF HEADER FOR THIS CALL
|
||
WORD(FCODE) ;KEEP THE USER'S FUNCTION CODE HERE
|
||
WORD(HILEVL) ;HIGHEST LEVEL # ISSUED BY USER
|
||
WORD(RBLOCK) ;ADDRESS OF USER'S PARAMETER BLOCK
|
||
WORD(SBLOCK) ;ADDRESS OF USER'S STATUS BLOCK
|
||
WORD(LOCKCT) ;# OF LOCKS IN REQUEST,,# OF CURRENT LOCK
|
||
WORD(REQID) ;STORAGE FOR REQUEST ID
|
||
WORD(TIMLIM) ;TIME LIMIT TO OBTAIN LOCKS
|
||
WORD(NQERRF) ;NON-ZERO IF ERROR OCCURED
|
||
WORD(REQCNT) ;COUNT OF OUTSTANDING RESOURCE REQUESTS FOR THIS USER
|
||
WORD(LSTLOK) ;LAST LOCK-BLOCK CREATED (FOR DEBUGGING)
|
||
WORD(LASTQ) ;LAST Q-BLOCK CREATED (FOR DEBUGGING)
|
||
QDBLEN==:ENQ... ;DEFINE LENGTH OF DATABASE
|
||
|
||
;
|
||
; THESE ARE ALL SUPER-TEMPORARY VARIABLES ONLY USED WITH EQ RESOURCE
|
||
;
|
||
|
||
DQFLAG: BLOCK 1 ;NON:ZERO IF A LOCK WAS DEQ'D
|
||
EQTMP1: BLOCK 1 ;RANDOM TEMPORARIES
|
||
EQTMP2: BLOCK 1 ;..SAME
|
||
EQTMP3: BLOCK 1 ;..SAME
|
||
EQTMP4: BLOCK 1 ;..SAME
|
||
EQTMP5: BLOCK 1
|
||
LKTMP1: BLOCK 1 ;STORAGE FOR LOCK-SCHEDULER
|
||
LKTMP2: BLOCK 1 ;..SAME
|
||
LKTMP3: BLOCK 1 ;..SAME
|
||
LKTMP4: BLOCK 1 ;..SAME
|
||
QSKDF: BLOCK 1 ;STORAGE FOR Q-SCHEDULER
|
||
QSKDG: BLOCK 1 ;..SAME
|
||
QSKDT: BLOCK 1 ;..SAME
|
||
QSKDQ: BLOCK 1 ;..SAME
|
||
QSKDM: BLOCK 1 ;..SAME
|
||
QSKDN: BLOCK 1 ;..SAME
|
||
ENQTBC: BLOCK 1 ;POINTER TO NEXT Q-BLOCK TO BE DEADLOCK CHECKED
|
||
ENQHBC: BLOCK 1 ;POINTER TO NEXT Q-BLOCK ALREADY CHECKED
|
||
SUBTTL GETTAB TABLE
|
||
|
||
.EQTAB::
|
||
%ENQML: EXP EQMXCH ;MAXIMUM WORD SIZE OF STRING
|
||
%ENQNQ: Z ;NUMBER OF ACTIVE QUEUES
|
||
%ENQTE: Z ;TOTAL NUMBER OF ENQ'S SINCE RELOAD
|
||
%ENQTD: Z ;TOTAL NUMBER OF DEQ'S SINCE RELOAD
|
||
%ENQNP: Z ;NUMBER OF ACTIVE POOLED RESOURCES
|
||
%ENQDF: EXP M.ENQD## ;DEFAULT ENQ QUOTA
|
||
%ENQMM: EXP EQMXMW ;PIE-SLICE-LOCK MAX BLOCK SIZE
|
||
%ENQMT: EXP EQMXTB ;LOCK-ASSOCIATED TABLE MAX SIZE
|
||
%ENQLT: EXP EQMLTL ;MINUTES LONG TERM LOCKS STAY AROUND
|
||
%ENQDD: Z ;NUMBER OF DEADLOCKS DETECTED
|
||
%ENQTO: Z ;NUMBER OF TIMEOUTS
|
||
%ENQMQ: EXP M.ENQM## ;MAXIMUM NUMBER OF ACTIVE QUEUES
|
||
|
||
ENQMXL==:<.-.EQTAB-1>B26 ;FOR GETTAB
|
||
|
||
|
||
$LIT
|
||
|
||
QUEEND::END
|
||
|