15e96a66cSDavid du Colombier// pick up the common data structures 25e96a66cSDavid du Colombier 35e96a66cSDavid du Colombierrc("cd /sys/src/cmd/fossil; mk 9fsys.acid"); 45e96a66cSDavid du Colombierinclude("/sys/src/cmd/fossil/9fsys.acid"); 55e96a66cSDavid du Colombierrc("cd /sys/src/cmd/fossil; mk cache.acid"); 65e96a66cSDavid du Colombierinclude("/sys/src/cmd/fossil/cache.acid"); 75e96a66cSDavid du Colombierrc("cd /sys/src/cmd/fossil; mk disk.acid"); 85e96a66cSDavid du Colombierinclude("/sys/src/cmd/fossil/disk.acid"); 95e96a66cSDavid du Colombierrc("cd /sys/src/cmd/fossil; mk fs.acid"); 105e96a66cSDavid du Colombierinclude("/sys/src/cmd/fossil/fs.acid"); 11*588b1baaSDavid du Colombierrc("cd /sys/src/liboventi; mk plan9-thread.acid"); 12*588b1baaSDavid du Colombierinclude("/sys/src/liboventi/plan9-thread.acid"); 135e96a66cSDavid du Colombier 145e96a66cSDavid du Colombier// make a list of pids from a list of Thread structures 155e96a66cSDavid du Colombierdefn _threadlist(t) 165e96a66cSDavid du Colombier{ 175e96a66cSDavid du Colombier local l; 185e96a66cSDavid du Colombier 195e96a66cSDavid du Colombier l = {}; 205e96a66cSDavid du Colombier while t do { 215e96a66cSDavid du Colombier t = (Thread)t; 225e96a66cSDavid du Colombier l = append l, t.pid; 235e96a66cSDavid du Colombier t = t.next; 245e96a66cSDavid du Colombier } 255e96a66cSDavid du Colombier return l; 265e96a66cSDavid du Colombier} 275e96a66cSDavid du Colombier 285e96a66cSDavid du Colombier// print info about a VtRendez 295e96a66cSDavid du Colombierdefn vtrendez(r) 305e96a66cSDavid du Colombier{ 315e96a66cSDavid du Colombier local l, t, w, q; 325e96a66cSDavid du Colombier 335e96a66cSDavid du Colombier r = (VtRendez)r; 345e96a66cSDavid du Colombier w = _threadlist(r.wfirst); 355e96a66cSDavid du Colombier if match(pid, w) >= 0 then 365e96a66cSDavid du Colombier print("\twaiting for wakeup\n"); 375e96a66cSDavid du Colombier 385e96a66cSDavid du Colombier l = (VtLock)r.lk; 395e96a66cSDavid du Colombier q = _threadlist(l.qfirst); 405e96a66cSDavid du Colombier if match(pid, q) >= 0 then 415e96a66cSDavid du Colombier print("\tawakened; waiting for lock\n"); 425e96a66cSDavid du Colombier 435e96a66cSDavid du Colombier print("\tr=(VtRendez)", r\X, "\n"); 445e96a66cSDavid du Colombier print("\tl=(VtLock)", l\X, "\n"); 455e96a66cSDavid du Colombier if l.writer != 0 then { 465e96a66cSDavid du Colombier t = (Thread)l.writer; 475e96a66cSDavid du Colombier print("\tvtLock is held by ", t.pid\D, "\n"); 485e96a66cSDavid du Colombier } 495e96a66cSDavid du Colombier} 505e96a66cSDavid du Colombier 515e96a66cSDavid du Colombier// print info about a VtLock 525e96a66cSDavid du Colombierdefn vtlock(l) 535e96a66cSDavid du Colombier{ 545e96a66cSDavid du Colombier local t; 555e96a66cSDavid du Colombier 565e96a66cSDavid du Colombier l = (VtLock)l; 575e96a66cSDavid du Colombier print("\tl=(VtLock)", l\X, "\n"); 585e96a66cSDavid du Colombier if l.writer then { 595e96a66cSDavid du Colombier t = (Thread)l.writer; 605e96a66cSDavid du Colombier print("\tvtLock is held by ", t.pid\D, "\n"); 615e96a66cSDavid du Colombier } else if l.readers then 625e96a66cSDavid du Colombier print("\tvtLock is held by ", l.readers\D, " readers\n"); 635e96a66cSDavid du Colombier else 645e96a66cSDavid du Colombier print("\tvtLock is not held!\n"); 655e96a66cSDavid du Colombier} 665e96a66cSDavid du Colombier 675e96a66cSDavid du Colombier// try to say something intelligent about why a process is stuck. 685e96a66cSDavid du Colombier_pauses = { 690b9a5132SDavid du Colombier open, 700b9a5132SDavid du Colombier pread, 710b9a5132SDavid du Colombier pwrite, 720b9a5132SDavid du Colombier sleep, 730b9a5132SDavid du Colombier vtSleep, 740b9a5132SDavid du Colombier vtLock, 750b9a5132SDavid du Colombier vtRLock, 765e96a66cSDavid du Colombier}; 775e96a66cSDavid du Colombier 785e96a66cSDavid du Colombierdefn deadlocklist(l) 795e96a66cSDavid du Colombier{ 805e96a66cSDavid du Colombier while l do { 815e96a66cSDavid du Colombier setproc(head l); 825e96a66cSDavid du Colombier deadlock(); 835e96a66cSDavid du Colombier l = tail l; 845e96a66cSDavid du Colombier } 855e96a66cSDavid du Colombier} 865e96a66cSDavid du Colombier 875e96a66cSDavid du Colombierdefn deadlock() 885e96a66cSDavid du Colombier{ 895e96a66cSDavid du Colombier local stk, frame, name, stallframe, fossilframe, stallname; 905e96a66cSDavid du Colombier 915e96a66cSDavid du Colombier stk = strace(*PC, *SP, linkreg(0)); 925e96a66cSDavid du Colombier 935e96a66cSDavid du Colombier print("setproc(", pid, ") // ", readfile("/proc/"+itoa(pid)+"/args"), "\n"); 945e96a66cSDavid du Colombier stallframe = 0; 955e96a66cSDavid du Colombier stallname = ""; 965e96a66cSDavid du Colombier fossilframe = 0; 970b9a5132SDavid du Colombier frame = {0}; 985e96a66cSDavid du Colombier while stk do { 990b9a5132SDavid du Colombier lastframe = frame; 1005e96a66cSDavid du Colombier frame = head stk; 1015e96a66cSDavid du Colombier name = fmt(frame[0], 'a'); 1025e96a66cSDavid du Colombier if !stallframe && match(name, _pauses) >= 0 then { 1035e96a66cSDavid du Colombier stallframe = frame; 1045e96a66cSDavid du Colombier stallname = name; 1055e96a66cSDavid du Colombier print("\t", fmt(frame[0], 'a'), "("); 1065e96a66cSDavid du Colombier params(frame[2]); 1075e96a66cSDavid du Colombier print(") ", pcfile(frame[0]), ":", pcline(frame[0])); 1085e96a66cSDavid du Colombier print("\n\t\tcalled from ", fmt(frame[1], 'a'), " "); 1095e96a66cSDavid du Colombier pfl(frame[1]); 1105e96a66cSDavid du Colombier } 1115e96a66cSDavid du Colombier if !fossilframe && regexp("^/sys/src/cmd/fossil/.*", pcfile(frame[0])) then { 1120b9a5132SDavid du Colombier if !stallframe then { 1130b9a5132SDavid du Colombier stallframe = lastframe; 1140b9a5132SDavid du Colombier stallname = fmt(lastframe[0], 'a'); 1150b9a5132SDavid du Colombier print("\tunexpected stall: ", stallname, "\n"); 1160b9a5132SDavid du Colombier if match(stallname, _pauses) >= 0 then 1170b9a5132SDavid du Colombier print("\t\t but it matches!\n"); 1180b9a5132SDavid du Colombier } 1195e96a66cSDavid du Colombier fossilframe = frame; 1205e96a66cSDavid du Colombier print("\t", fmt(frame[0], 'a'), "("); 1215e96a66cSDavid du Colombier params(frame[2]); 1225e96a66cSDavid du Colombier print(") ", pcfile(frame[0]), ":", pcline(frame[0])); 1235e96a66cSDavid du Colombier print("\n\t\tcalled from ", fmt(frame[1], 'a'), " "); 1245e96a66cSDavid du Colombier pfl(frame[1]); 1255e96a66cSDavid du Colombier 1265e96a66cSDavid du Colombier if name == cacheLocalLookup && stallname == vtLock then 1275e96a66cSDavid du Colombier print("\twaiting to lock block b=(Block)", *cacheLocalLookup:b\X, "\n"); 1285e96a66cSDavid du Colombier if name == cacheLocal && stallname == vtSleep then 1295e96a66cSDavid du Colombier print("\tsleeping on block b=(Block)", *cacheLocal:b\X, "\n"); 1300b9a5132SDavid du Colombier if name == blockWrite && stallname == vtSleep then 1315e96a66cSDavid du Colombier print("\tsleeping on block b=(Block)", *blockFlush:b\X, "\n"); 1325e96a66cSDavid du Colombier } 1335e96a66cSDavid du Colombier stk = tail stk; 1345e96a66cSDavid du Colombier } 1355e96a66cSDavid du Colombier 1365e96a66cSDavid du Colombier if stallname == vtSleep then 1375e96a66cSDavid du Colombier vtrendez(*vtSleep:q); 1385e96a66cSDavid du Colombier if stallname == vtLock then 1395e96a66cSDavid du Colombier vtlock(*vtLock:p); 1400b9a5132SDavid du Colombier if !stallframe || !fossilframe then { 1410b9a5132SDavid du Colombier print("\tconfused:"); 1420b9a5132SDavid du Colombier if !stallframe then print(" stallframe?"); 1430b9a5132SDavid du Colombier if !fossilframe then print(" fossilframe?"); 1440b9a5132SDavid du Colombier print("\n"); 1450b9a5132SDavid du Colombier } 1465e96a66cSDavid du Colombier print("\n"); 1475e96a66cSDavid du Colombier} 1485e96a66cSDavid du Colombier 1495e96a66cSDavid du Colombier// fetch fsys 1505e96a66cSDavid du Colombierdefn 1515e96a66cSDavid du ColombierfsysGet(name) 1525e96a66cSDavid du Colombier{ 1535e96a66cSDavid du Colombier return fsysmain; 1545e96a66cSDavid du Colombier} 1555e96a66cSDavid du Colombier 1565e96a66cSDavid du Colombier// dump information about the cache 1575e96a66cSDavid du Colombierdefn 1585e96a66cSDavid du ColombiercacheDump(c) 1595e96a66cSDavid du Colombier{ 1605e96a66cSDavid du Colombier local i, b, x; 1615e96a66cSDavid du Colombier 1625e96a66cSDavid du Colombier c = (Cache)c; 1635e96a66cSDavid du Colombier x = c.blocks; 1645e96a66cSDavid du Colombier i=0; 1655e96a66cSDavid du Colombier loop 1,c.nblocks do { 1665e96a66cSDavid du Colombier b = (Block)(x+i); 1675e96a66cSDavid du Colombier print(b\X, " ", b.pc\X, " ", b.ref\D, "\n"); 1685e96a66cSDavid du Colombier i = i+sizeofBlock; 1695e96a66cSDavid du Colombier } 1705e96a66cSDavid du Colombier} 1715e96a66cSDavid du Colombier 1725e96a66cSDavid du Colombier// print block info 1735e96a66cSDavid du Colombierdefn 1745e96a66cSDavid du Colombierprintblist(bl) 1755e96a66cSDavid du Colombier{ 1765e96a66cSDavid du Colombier bl = (BList)bl; 1775e96a66cSDavid du Colombier while bl != 0 do { 1785e96a66cSDavid du Colombier print("[", bl.part\D, " ", bl.addr\X, " ", bl.vers\D, "]"); 1795e96a66cSDavid du Colombier bl = bl.next; 1805e96a66cSDavid du Colombier if bl != 0 then 1815e96a66cSDavid du Colombier print(", "); 1825e96a66cSDavid du Colombier } 1835e96a66cSDavid du Colombier} 1845e96a66cSDavid du Colombier 1855e96a66cSDavid du Colombierdefn 1865e96a66cSDavid du Colombierblock(b) 1875e96a66cSDavid du Colombier{ 1885e96a66cSDavid du Colombier local i; 1895e96a66cSDavid du Colombier 1905e96a66cSDavid du Colombier b = (Block)b; 1915e96a66cSDavid du Colombier print("b=(Block)", b\X, "\n"); 1925e96a66cSDavid du Colombier print("\tref ", b.ref\D, " nlock ", b.nlock\D, "\n"); 1935e96a66cSDavid du Colombier print("\tpav=[", b.part\D, " ", b.addr\X, " ", b.vers\D, "]\n"); 1945e96a66cSDavid du Colombier print("\tprior="); 1955e96a66cSDavid du Colombier printblist(b.prior); 1965e96a66cSDavid du Colombier print("\n"); 1975e96a66cSDavid du Colombier print("\tunlink="); 1985e96a66cSDavid du Colombier printblist(b.uhead); 1995e96a66cSDavid du Colombier print("\n"); 2005e96a66cSDavid du Colombier} 201