/* ** BLOCKING.C, Hein van den Heuvel, Digital, July 1995 ** ** List all locks not granted (converting, waiting) for a specified PID. ** For each, print blocking lock information, resource name and parent. ** Have fun, ** Hein van den Heuvel, July 1995. */ #include #include #include #include #include #include #include #define terminator 0,0,0,0 #define EFN 1 typedef struct { short len, cod; void *address; short *retlen; } item; int sys$getlkiw(), sys$getjpi(), sys$setprv(), sys$cmexec(); char *mode[]={"NL", "CR", "CW", "PR", "PW", "EX", "??"}; void print_resource_name(void *p, short len, char *t) { int i, (*x)[8]; char out[32], *in, c; x = in = p; if (len >= sizeof out) len = sizeof out - 1; for (i=0; i\n", t, len, &out[0]); printf (" %08X %08X %08X %08X\n", (*x)[0],(*x)[1],(*x)[2],(*x)[3]); if (len > 16) printf (" %08X %08X %08X %08X\n", (*x)[4],(*x)[5],(*x)[6],(*x)[7]); } main(argc, argv) int argc; char *argv[]; { int stat, s, i, l, parent, grand_parent, lock_id, lock_pid; int wildcard=0, retlen=0, pid=0, locks=0; char *x; struct lkidef lkibuf[50], *lki; struct { unsigned all : 16, one : 15, too_small : 1 ;} lkilen; int privs[] = { PRV$M_WORLD | PRV$M_CMEXEC , 0}, context[] = {0,0}; #pragma nostandard /* Using address of variable where constant is standard */ struct { char rqmode, grmode, queue, fill;} lki_state; struct { int rms; unsigned short fid_num, fid_seq, fid_rvn; char devlocknam[22] ;} parent_resnam; struct { int id, vbn, fill[6];} resnam; item getlki_items[] = { 4, LKI$_LOCKID, &lock_id, 0, 4, LKI$_PID, &lock_pid, 0, 3, LKI$_STATE, &lki_state, 0, terminator}; item block_items[] = { 31, LKI$_RESNAM, &resnam, &retlen, 4, LKI$_PARENT, &parent, 0, sizeof lkibuf, LKI$_BLOCKING, &lkibuf, &lkilen, terminator}; item parent_items[] = { 31, LKI$_RESNAM, &parent_resnam, &retlen, 4, LKI$_PARENT, &grand_parent, 0, terminator}; int getlki_args[] = {7, EFN, (int) &wildcard, (int) &getlki_items,0,0,0,0}, parent_args[] = {7, EFN, (int) &parent, (int) &parent_items,0,0,0,0}, block_args[] = {7, EFN, (int) &lock_id, (int) &block_items,0,0,0,0}; #pragma standard /* ** First get some temporary privs for the GETLKI in EXEC mode later on. */ stat = sys$setprv ( 1, privs, 0, 0); if (stat != SS$_NORMAL) return (stat & -2); if (argc > 1) { sscanf (argv[1], "%x", &pid); printf (" Looking for non-granted locks for PID %8X\n\n", pid); } else { printf (" Looking for non-granted locks for all PIDs\n\n"); }; /* ** Main loop. Get a lock, any lock. ** Find out wether it is held by specified process, and waiting. */ stat = sys$cmexec (&sys$getlkiw, &getlki_args); while (stat & 1) { locks++; if ( (lki_state.queue != LKI$C_GRANTED) && ((pid == 0) || (lock_pid == pid)) ) { parent = 0; /* ** Have blocked lock for specified PID, request details. */ stat = sys$cmexec (&sys$getlkiw, &block_args); if (!(stat & 1)) break; l = lkilen.all / lkilen.one; printf ("Pid %08X Lock %08X, Rq=%s, Parent %08X, blocked by %d.\n", lock_pid, lock_id, mode[lki_state.rqmode], parent, l); print_resource_name(&resnam, retlen, ""); lki = &lkibuf; for ( i = 0; i < l; i++) { printf (" PID=%8X, Gr=%s, Rq=%s, LockId=%08X, System=%08\n", lki->lki$l_pid, mode[lki->lki$b_grmode], mode[lki->lki$b_rqmode], lki->lki$l_lkid, lki->lki$l_csid); lki++; } if (parent!=0) { s = sys$cmexec (&sys$getlkiw, &parent_args); print_resource_name(&parent_resnam, retlen, "Parent "); if ((s & 1) && (grand_parent==0) && (parent_resnam.rms == 'RMS$')) { /* ** Stumbled accross an rms lock. ** Let's printf out formatted resourse names. */ printf (" RMS lock! VBN/ID %X/%X, File (%d,%d,%d) on %s\n", resnam.vbn, resnam.id, parent_resnam.fid_num, parent_resnam.fid_seq, parent_resnam.fid_rvn, &parent_resnam.devlocknam[1]); } /* RMS$ ? */ } /* Parent? */ printf ("\n"); } /* PID ? */ if (stat &1) stat = sys$cmexec (&sys$getlkiw, &getlki_args); } /* stat ? */ if (stat == SS$_NOMORELOCK) stat = SS$_NORMAL; printf (" Done. Scanned %d locks.\n", locks); return stat; }