;++ .title blocking_lock .ident "Blocking_Lock V2.0" ;++ ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ; Program: ; Blocking_Lock.MAR ; ; Author: ; Bruce Ellis April-1990 V1.0 - Original VAX demo program created. ; ; Modification History: ; Jim McKinney March-2003 V2.0 - Extensive rewrite and port to ; AXP - ok for Alpha V7.2+ or VAX V5.4+ ; ; Function: ; Identify blocked lock requests ; ; Abstract: ; Accept a PID or lock id (the lock id is only accepted if the PID ; the user skips entry of the PID) and ; ; PID case: if the user enters a PID, use it to locate the list of ; owned locks and determine the first blocked lock. Then determines ; the process(es) holding the locks which are blocking the process ; from accessing the given resource and displays an assortment of ; interesting information that identifies the lock and blockers. ; ; LKID case: same as PID case except wse go directly to the lock ; block by lock id. Typically this would be used in the case where ; you've executed this program once and discovered that a resource ; is mastered on a remote node. Note the remote LKID, log in to ; the remote node, and execute this program again - specifying ; the noted LKID. ; ; Note: the status SS$_NOMORELOCK will be returned if no blocking ; locks are found. ; ; World and CMKRNL privileges required. ; ; NOTE: this program executes in kernel mode at elevated IPL - ; primitive exception handling is provided - however, should ; a kernel mode fault occur that the exception handler is ; unable to handle your system WILL crash - there are no known ; bugs - but, you've been warned - use at your own risk ; ;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ;-- ; define ALPHA if R22 is a register and not a symbol ; .NTYPE ...IS_IT_ALPHA,R22 ;Get the type of R22 ...IS_IT_ALPHA = <...IS_IT_ALPHA@-4&^XF>-5 .IIF EQ,...IS_IT_ALPHA, ALPHA=1 ; Macro to check status .macro check ?l blbs r0,l $exit_s r0 l: .endm check ; Macro to build item_list_3 .macro item type=,item=,length=4,retlen=,retadr= .word length,type'$_'item ; length,,what .address retadr ; put it here .if nb,retlen ; if we have an explicit return length .address retlen ; then use it .iff ; else .long 0 ; we don't care .endc .endm item ; Include files .library "sys$library:lib.mlb" .link "sys$system:sys.stb"/selective_search .psect _data quad,wrt,noshr ; Data structure and status definitions $ipldef ; interrupt priority level $jpidef ; $getjpi definitions $lckdef ; lock modes $lkbdef ; lock block $pcbdef ; process control block $rsbdef ; resource block $ssdef ; system status definitions $syidef ; $getsyi definitions $sysversiondef ; system base image version numbers $uafdef ; uaf symbols ;****************** ; output buffer ;****************** tttext_size=512 tttext_buffer: ; buffer for $fao conversion .long tttext_size .address 10$ 10$: .blkb tttext_size ;****************** ; $fao format statements ;****************** fmt0: .ascid "!/"- " PID !8XL belongs to process !AS owned by user !AS!/"- " which has requested a !2AC mode lock with LKID !8XL." fmt1: .ascid "!/"- " LKID: !8XL!/"- " Resource name (ascii) !AF!/"- " Resource name (hex) !8XL !8XL !8XL !8XL!/"- " !8XL !8XL !8XL !8XL" fmt2: .ascid " Parent Resource name (ascii) !AF!/"- " Parent Resource name (hex) !8XL !8XL !8XL !8XL!/"- " !8XL !8XL !8XL !8XL" fmt3: .ascid "!/"- " This lock request is currently blocked by a !2AC mode lock"- " held by!/ process !AS with PID !8XL and owned by user !AS.!/" fmt4: .ascid "!/"- " This lock is converting from !2AC to !2AC!/" fmt5: .ascid "!/"- " This lock request is currently blocked by a lock with LKID"- " !XL!/ held on node !AS. The owner process for this blocking"- " lock may be!/ determine by using this utility on node !AS"- " and specifying this!/ LKID as input.!/" ;****************** ; $getjpi data structures ;****************** jpi_items: item type=jpi,- item=getjpi_control_flags,- ; must be 1st item in list retadr=jpi_flags ; (see $getjpi doc) item type=jpi,- item=username,- length=uaf$s_username,- retlen=username_len,- retadr=username item type=jpi,- item=prcnam,- length=15,- retlen=prcnam_len,- retadr=prcnam .long 0 jpi_flags: .long 0 ; control flags for $getjpi username: .blkb uaf$s_username username_desc: username_len: .word .-username .byte dsc$k_dtype_t .byte dsc$k_class_s .address username prcnam: .blkb 15 prcnam_desc: prcnam_len: .word .-prcnam .byte dsc$k_dtype_t .byte dsc$k_class_s .address prcnam ;****************** ; $getsyi data structures ;****************** syi_items: item type=syi,- item=nodename,- length=6,- retlen=nodename_len,- retadr=nodename .long 0 nodename: .blkb 12 nodename_desc: nodename_len: .word .-nodename .byte dsc$k_dtype_t .byte dsc$k_class_s .address nodename iosb: .quad 0 ; IOSB for $getjpi and $getsyi ;****************** ; lookup table for lock modes ; leave the blank space in each of the ASCIC entries below - three bytes ; of text and a count byte allows us to increment by longword to walk ; the mode table ;****************** ASSUME LCK$K_NLMODE EQ 0 ASSUME LCK$K_CRMODE EQ 1 ASSUME LCK$K_CWMODE EQ 2 ASSUME LCK$K_PRMODE EQ 3 ASSUME LCK$K_PWMODE EQ 4 ASSUME LCK$K_EXMODE EQ 5 mode_tbl: .ascic "NL " .ascic "CR " .ascic "CW " .ascic "PR " .ascic "PW " .ascic "EX " ;****************** ; input data and prompt strings ;****************** pid_a: .long 8 .address 10$ 10$: .blkb 8 pmt: .ascid "pid> " pmtl: .ascid "lkid> " lkid_a: .long 8 .address 10$ 10$: .blkb 8 ;****************** ; address of code/data to lock down while at elevated IPL ;****************** lock_adr: .address lock_start .address lock_end .psect _nonpagableddata quad lock_start: ; start location for $lkwset pid_b: .blkl 1 ; process id lkid_b: .blkl 1 ; lock id kargs: .long 4 ; arguments to $cmkrnl k_pid: .address pid_b ; process id address kbuff: .address lock_info_buffer ; buffer returned from kernel mode kflag: .blkl 1 ; 0=> pid, 1=> lkid passed klkid: .address lkid_b ; lock id address k_pid_offset=k_pid-kargs kbuff_offset=kbuff-kargs kflag_offset=kflag-kargs klkid_offset=klkid-kargs ;****************** ; buffer of data about locks ; NOTE: position is assumed; any changes will require that code area ; be researched and altered as needed ;****************** .align long lock_info_buffer: 10$: .blkl 1 ; remlkid 20$: .blkl 1 ; lkid 30$: .blkl 1 ; csid 40$: .blkb 1 ; rqmode 50$: .blkb 1 ; resnam_cnt .blkb 2 ; 2 bytes to provide longword alignment 60$: .blkb 32 ; presnam 70$: .blkb 1 ; presnam_cnt .blkb 3 ; 3 bytes to provide longword alignment 80$: .blkb 32 ; presnam_loc 90$: .blkb 1 ; process_cnt .blkb 3 ; 3 bytes to provide longword alignment 100$: .rept 10 ; info on up to 10 blocking processes .blkl 1 ; per_process_epid .blkl 1 ; per_process_mode .blkl 1 ; per_process_csid .blkl 1 ; per_process_flags .endr per_process_data_size=16 per_process_epid=0 per_process_mode=4 per_process_csid=8 per_process_flags=12 remlkid=10$-lock_info_buffer ; 0 lkid=20$-lock_info_buffer ; 4 csid=30$-lock_info_buffer ; 8 rqmode=40$-lock_info_buffer ; 12 resnam_cnt=50$-lock_info_buffer ; 13 resnam=60$-lock_info_buffer ; 16 presnam_cnt=70$-lock_info_buffer ; 48 presnam=80$-lock_info_buffer ; 52 process_cnt=90$-lock_info_buffer ; 84 epid_and_grmode=100$-lock_info_buffer ; resnam_loc=60$ presnam_loc=80$ .if df,ALPHA lock_end: .endc ;****************** ; Main Program ; Prompt for pid/lkid ; hop into kernel mode and get lock/resource info ; display the info ;****************** .psect _code page,nowrt,shr .entry blocking_lock,^m<> ;****************** ; for Alpha: ; insure that we're running on VMS V7.2 or later - this is whence the lock ; manager was moved up into S2 space and the addressing needs changed from ; 32bit to 64bit - if the version is mismatched then the value of ; lckmgr_version must be edited and the code examined for any required ; changes ;****************** .if df,ALPHA lckmgr_version_min = ^x00010100 ;V7.2 ; lckmgr_version = ^x00010110 ;V7.3 lckmgr_version_max = ^x00010120 ;V7.3-1 moval g^sys$version_begin,r2 movzbl #sys$k_clusters_lockmgr,r1 cmpl #lckmgr_version_min,4(r2)[r1] bgtr 1$ cmpl #lckmgr_version_max,4(r2)[r1] bgeq 2$ 1$: movl #ss$_sysverdif,r0 ; must recompile/relink $exit_s r0 2$: .endc pushal pid_a ; read with prompt for process id pushal pmt pushal pid_a calls #3,g^lib$get_input check tstw pid_a ; if no PID entered get lkid beql get_lkid pushl #1 ; else, convert PID to binary pushl #4 pushal pid_b pushal pid_a calls #4,g^ots$cvt_tz_l check brb got_pid get_lkid: incl kflag ; set flag for kernel mode code pushal lkid_a ; to process a lkid pushal pmtl ; read with prompt for lock id pushal lkid_a calls #3,g^lib$get_input check pushl #1 ; convert lock id to binary pushl #4 pushal lkid_b pushal lkid_a calls #4,g^ots$cvt_tz_l check got_pid: $lkwset_s inadr=lock_adr ; the inadr values vary with VAX/AXP check ; code and data on VAX / data on AXP .if df,ALPHA ; lock down kernel mode code to $lock_page_init done ; insure no pagefaults at high IPL .endc ;****************** ; Get into kernel mode and grab the resource/lock info ;****************** $cmkrnl_s routin=find_out_who,- arglst=kargs check ;****************** ; save the address of the lock data - we'll need it regardless of the code path ;****************** moval lock_info_buffer,r6 ; point to data buffer cmpl kflag,#0 ; 0=>pid, 1=>lkid beql 10$ ; pid, get the job info brw 20$ ; lkid, skip to resource info ;****************** ; get the associated process info for the process whose lock request is ; blocked - if the process is swapped, suspended, or otherwise unavailable, ; we won't attempt to deliver an AST to get it's attention ;****************** 10$: bisl3 #jpi$m_no_target_inswap,#jpi$m_ignore_target_status,jpi_flags $getjpiw_s - pidadr=pid_b, - itmlst=jpi_items, - iosb=iosb check movzwl iosb,r0 check locc #^A/ /,#uaf$s_username,username ; check for first ' ' subl3 r0,#uaf$s_username,r1 ; and set length in descriptor movzbl rqmode(r6),r8 ; use request mode as index moval mode_tbl[r8],r8 ; into display table ;****************** ; Format and display user info, lkid, and mode ;****************** movl #tttext_size,tttext_buffer ; reset buffer size $fao_s ctrstr=fmt0,- outbuf=tttext_buffer,- outlen=tttext_buffer,- p1=pid_b,- p2=#prcnam_desc,- p3=#username_desc,- p4=r8,- p5=lkid(r6) check pushal tttext_buffer calls #1,g^lib$put_output check ;****************** ; Format and display resource name ;****************** 20$: movl #tttext_size,tttext_buffer ; reset buffer size movzbl resnam_cnt(r6),r2 ; size of resource name $fao_s ctrstr=fmt1,- outbuf=tttext_buffer,- outlen=tttext_buffer,- p1=lkid(r6),- p2=r2,- p3=#resnam_loc,- p4=resnam+12(r6),- p5=resnam+8(r6),- p6=resnam+4(r6),- p7=resnam(r6),- p8=resnam+28(r6),- p9=resnam+24(r6),- p10=resnam+20(r6),- p11=resnam+16(r6) check pushal tttext_buffer calls #1,g^lib$put_output check ;****************** ; Format and display the parent resource name ;****************** movl #tttext_size,tttext_buffer ; reset buffer size movzbl presnam_cnt(r6),r2 ; size of resource name beql 40$ $fao_s ctrstr=fmt2,- outbuf=tttext_buffer,- outlen=tttext_buffer,- p1=r2,- p2=#presnam_loc,- p3=presnam+12(r6),- p4=presnam+8(r6),- p5=presnam+4(r6),- p6=presnam(r6),- p7=presnam+28(r6),- p8=presnam+24(r6),- p9=presnam+20(r6),- p10=presnam+16(r6) check pushal tttext_buffer calls #1,g^lib$put_output check ;****************** ; Format and display the epid and mode of (up to 10) blocking processes ; If master copy then display CSID ;****************** 30$: cmpl csid(r6),#0 beql 40$ brw 90$ 40$: movzbl process_cnt(r6),r11 ; set per process count moval epid_and_grmode(r6),r7 ; get address of per process buffer 50$: movl per_process_mode(r7),r8 ; get mode owned moval mode_tbl[r8],r8 ; get mode string address cmpl r11,#0 ; process_cnt=0 and a lock is blocked bneq 60$ ; brw 70$ ; indicates a conversion in progress 60$: movl #tttext_size,tttext_buffer ; reset buffer size ;****************** ; get the process info for the job that is blocking the lock request ;****************** bisl3 #jpi$m_no_target_inswap,#jpi$m_ignore_target_status,jpi_flags $getjpiw_s - ; let's get the lowdown on the process pidadr=(r7), - itmlst=jpi_items, - iosb=iosb check movzwl iosb,r0 check locc #^A/ /,#uaf$s_username,username ; check for first ' ' subl3 r0,#uaf$s_username,r1 ; and set length in descriptor movw r1,username_len $fao_s ctrstr=fmt3,- outbuf=tttext_buffer,- outlen=tttext_buffer,- p1=r8,- p2=#prcnam_desc,- p3=(r7),- p4=#username_desc check brb 80$ ;****************** ; Lock is in process of converting ; Format and display the current and requested lock mode ;****************** 70$: movl #1,r11 ; was 0, set =1 to indicate done movzbl rqmode(r6),r9 ; use request mode as index moval mode_tbl[r9],r9 ; into display table movl #tttext_size,tttext_buffer ; reset buffer size $fao_s ctrstr=fmt4,- outbuf=tttext_buffer,- outlen=tttext_buffer,- p1=r8,- p2=r9 check 80$: pushal tttext_buffer calls #1,g^lib$put_output check ; gotta rethink this next line; it creates an infinite loop when $60 ; block jumps to $80 and the mstcpy bit is set - we go back to $70 ; and then loop forever ; bbs #lkb$v_mstcpy,per_process_flags(r7),70$ brw 100$ ; lock blocked locally, skip... 90$: movl #1,r11 ; was 0, set =1 to indicate done $getsyiw_s - csidadr=csid(r6), - itmlst=syi_items, - iosb=iosb check movzwl iosb,r0 check movl #tttext_size,tttext_buffer ; reset buffer size $fao_s ctrstr=fmt5,- outbuf=tttext_buffer,- outlen=tttext_buffer,- p1=remlkid(r6),- p2=#nodename_desc,- p3=#nodename_desc check pushal tttext_buffer calls #1,g^lib$put_output check 100$: addl #per_process_data_size,r7 ; point to next data segment decl r11 ; decrement process count beql done ; if out, scram brw 50$ ; else, get next process done: ret ;****************** ; Kernel mode code to return lock/resource data ; Inputs: 4(ap) pid ; 8(ap) user buffer ; 12(ap) flag (0=pid passed, 1=lkid passed) ; 16(ap) lkid ; Outputs: user buffer filled ; r0= ss$_normal/ss$_ivlockid/ss$_nomorelock/ss$_nonexpr ; ; Note: much of the kernel mode code executes at elevated IPL ; and so must be locked down to guarantee no pagefaults ; occur. The $LKWSET system service is adequate on VAX ; but the $LOCK_PAGE macro must be used on Alpha to ; force the linkage section to be locked as well as the ; code. We'll just lock the whole routine in... ;****************** .if df,ALPHA ; lock down this code to avoid $locked_page_start ; pagefaults at elevated IPL .if_false .psect _nonpageablecode page,nowrt,shr .endc .entry find_out_who,^m<> movab g^exe$sigtoret,(fp) ; establish exception handler ; to prevent an ACCVIO from ; causing a SSRVEXCEPT bugcheck movl kbuff_offset(ap),r11 ; set return buffer address tstl kflag_offset(ap) ; if pid passed then process .iif df, ALPHA, .branch_likely beql use_pid ; else .iif df, ALPHA, .branch_unlikely brw use_lkid ; process lock id use_pid: movl k_pid_offset(ap),r6 ; move address of pid to r6 movl (r6),r6 ; move pid into register ; to avoid memory reference ; at elevated IPL lock lockname=SCHED,- ; grab SCHED lock at IPL$_SCHED preserve=NO movl r6,r0 ; need PID in R0 .if df,ALPHA jsb g^exe$cvt_epid_to_pcb ; get PCB associated with EPID .if_false jsb g^exe$epid_to_pcb ; get PCB associated with EPID .endc tstl r0 ; valid PCB? .iif df, ALPHA, .branch_likely bneq ok_proc ; 0=>error movl #ss$_nonexpr,r0 .iif df, ALPHA, .branch_unlikely brw err_out ; else scram ok_proc: movl r0,r4 ; move PCB address to R4 movl pcb$l_epid(r4),r6 ; move EPID to R6 unlock lockname=SCHED,- ; give up the SCHED spinlock newipl=#IPL$_SCS,- ; so we can grab SCS preserve=NO ; spinlock at correct rank ; leave ipl at 8 ASSUME IPL$_SCS EQ IPL$_SCHED lock lockname=SCS ; get lock spinlock lock lockname=SCHED ; reacquire scheduler spinlock cmpl pcb$l_epid(r4),r6 ; is he still there? .iif df, ALPHA, .branch_likely beql still_there ; if so, continue unlock lockname=SCHED,- ; release owned locks newipl=#0,- preserve=NO brw err_out_release_locks ; and scram still_there: unlock lockname=SCHED,- ; release owned locks newipl=#0,- preserve=NO .if df,ALPHA .enable quadword ; use 64bit addresses since ; LKBs are in P2 space EVAX_LDAQ r6,pcb$q_lockqfl(r4) EVAX_LDQ r0,(r6) EVAX_SUBQ r0,r6,r0 ; if back at listhead EVAX_BEQ r0,no_locks ; scram 10$: $PUSH64 r6 ; save listhead address $POP64 r7 ; from r6 into r7 next_lock: EVAX_LDQ r7,(r7) ; get next lock EVAX_SUBQ r6,r7,r0 ; if back at listhead, EVAX_BEQ r0,no_locks ; scram 20$: EVAX_LDAQ r8,<-lkb$q_ownqfl>(r7) ; find beginning of lock block .if_false moval pcb$l_lockqfl(r4),r6 ; get owner queue address cmpl (r6),r6 ; if no locks, scram bneq 10$ brw no_locks 10$: movl r6,r7 ; save listhead address next_lock: movl (r7),r7 ; get next lock cmpl r6,r7 ; if back at listhead, scram bneq 20$ brw no_locks 20$: moval <-lkb$l_ownqfl>(r7),r8 ; find beginning of lock block .endc process_lock: cmpb #lkb$k_granted,lkb$b_state(r8) ; if granted, skip bneq process_wait_on_lock brb next_lock process_wait_on_lock: movzbl lkb$b_rqmode(r8),rqmode(r11) ; save request mode movl lkb$l_lkid(r8),lkid(r11) ; save lock id movl lkb$l_remlkid(r8),remlkid(r11) ; get remote lock id .if df,ALPHA EVAX_LDQ r8,lkb$q_rsb(r8) ; get resource block address tstl rsb$l_csid(r8) ; if csid=0, beql 30$ ; then remlkid=0 movl rsb$l_csid(r8),csid(r11) ; get csid of master (if any) brb 40$ 30$: clrl csid(r11) clrl remlkid(r11) 40$: EVAX_LDQ r10,rsb$q_parent(r8) ; get parent resource block EVAX_BEQ r10,skip_parent ; if none skip copying name .if_false movl lkb$l_rsb(r8),r8 ; get resource block address tstl rsb$l_csid(r8) ; if csid=0, beql 30$ ; then remlkid=0 movl rsb$l_csid(r8),csid(r11) ; get csid of master (if any) brb 40$ 30$: clrl csid(r11) clrl remlkid(r11) 40$: movl rsb$l_parent(r8),r10 ; get parent resource block beql skip_parent ; if none skip copying name .endc movzbl rsb$b_rsnlen(r10),r0 ; copy parent resource name movb r0,presnam_cnt(r11) ; to user buffer movc3 r0,rsb$t_resnam(r10),presnam(r11) skip_parent: movzbl rsb$b_rsnlen(r8),r0 ; copy resource name to movb r0,resnam_cnt(r11) ; user buffer movc3 r0,rsb$t_resnam(r8),resnam(r11) .if df,ALPHA clrq r5 ; clear process counter EVAX_LDQ r1,#10 ; handle up to 10 processes EVAX_LDAQ r9,rsb$q_grqfl(r8) ; get granted queue $PUSH64 r9 ; save listhead address $POP64 r10 ; from r9 to r10 .if_false clrl r5 ; clear process counter movl #10,r1 ; handle up to 10 processes moval rsb$l_grqfl(r8),r9 ; get granted queue movl r9,r10 ; save listhead address .endc moval epid_and_grmode(r11),r2 ; get per process buffer next_process: .if df,ALPHA EVAX_LDQ r10,(r10) ; get next granted lock EVAX_SUBQ r10,r9,r0 ; circular queue, if done EVAX_BEQ r0,done_with_procs ; scram EVAX_LDAQ r3,<-lkb$q_sqfl>(r10) ; locate start of lock block bbs #lkb$v_mstcpy,lkb$l_status(r3),use_epid .disable quadword .if_false movl (r10),r10 ; get next granted lock cmpl r10,r9 ; circular queue, if done, scram beql done_with_procs moval <-lkb$l_sqfl>(r10),r3 ; locate start of lock block movl lkb$l_pid(r3),r0 ; get pid to determine epid bbs #lkb$v_mstcpy,lkb$w_status(r3),use_epid .endc movl lkb$l_pid(r3),r0 ; get pid to determine epid movzwl r0,r0 ; get index into pcb vector tbl movl @sch$gl_pcbvec[r0],r0 ; get his pcb address movl pcb$l_epid(r0),(r2)+ ; get his epid brb got_epid use_epid: movl lkb$l_epid(r3),(r2)+ ; if remote, copy epid field got_epid: movzbl lkb$b_grmode(r3),(r2)+ ; copy mode granted ; if not master, skip csid/flag .if df,ALPHA bbc #lkb$v_mstcpy,lkb$l_status(r3),skip_master movl lkb$l_csid(r3),(r2)+ ; copy csid of master movl lkb$l_flags(r3),(r2)+ ; copy flags .if_false bbc #lkb$v_mstcpy,lkb$w_status(r3),skip_master movl lkb$l_csid(r3),(r2)+ ; copy csid of master movzwl lkb$w_flags(r3),(r2)+ ; copy flags .endc brb skip_add skip_master: clrl (r2)+ ; clear csid, incr pointer clrl (r2)+ ; clear flags, incr pointer ; addl #8,r2 ; point to next buffer skip_add: incl r5 ; increment count of processes sobgtr r1,next_process ; get next process done_with_procs: movb r5,process_cnt(r11) ; return process count movl #ss$_normal,r0 ; beat it err_out_release_locks: unlock lockname=SCS,preserve=YES,newipl=#0 err_out: ret no_locks: unlock lockname=SCS,preserve=NO,newipl=#0 movl #ss$_nomorelock,r0 ; no locks ret ;****************** ; Process using lock id ;****************** use_lkid: movl @klkid_offset(ap),r7 ; get the lock id lock lockname=SCS extzv #0,#lkb$s_index,r7,r8 ; extract the index cmpl r8,lck$gl_maxid ; if bogus index, scram bgtru 60$ .if df,ALPHA .enable quadword ; EVAX_LDAQ r8,@lck$gq_idtbl[r8] ; doesn't work - replace w/1-5 movaq g^lck$gq_idtbl,r10 ;1 start at lck$gq_idtbl EVAX_LDQ r10,(r10) ;2 get the address there mull3 r8,#8,r9 ;3 and we'll find the address EVAX_ADDQ r10,r9,r8 ;4 of our lock block at EVAX_LDQ r8,(r8) ;5 8bytes*index EVAX_BLT r8,50$ ; a negative number indicates ; an address in P2 space brw 60$ ; system virtual address is ; not pointing to an LKB .if_false movl @lck$gl_idtbl[r8],r8 ; get the lock block bgeq 60$ ; if not, system virtual ; address is not pointing ; to an LKB .endc 50$: cmpl r7,lkb$l_lkid(r8) ; correct lkid? bneq 60$ ; if not, scram cmpb #lkb$k_granted,lkb$b_state(r8) ; if granted, scram beql 60$ brw process_wait_on_lock 60$: movl #ss$_ivlockid,r0 ; invalid lock id unlock lockname=SCS,preserve=NO,newipl=#0 ret .if df,ALPHA .disable quadword $locked_page_end ; locked using $lock_page macro .if_false ; else, if it's a VAX lock_end: ; we'll be using $lkwset .endc ; to lock this code .end blocking_lock