123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- // pick up the common data structures
- rc("cd /sys/src/cmd/fossil; mk 9fsys.acid");
- include("/sys/src/cmd/fossil/9fsys.acid");
- rc("cd /sys/src/cmd/fossil; mk cache.acid");
- include("/sys/src/cmd/fossil/cache.acid");
- rc("cd /sys/src/cmd/fossil; mk disk.acid");
- include("/sys/src/cmd/fossil/disk.acid");
- rc("cd /sys/src/cmd/fossil; mk fs.acid");
- include("/sys/src/cmd/fossil/fs.acid");
- rc("cd /sys/src/libventi; mk plan9-thread.acid");
- include("/sys/src/libventi/plan9-thread.acid");
- // make a list of pids from a list of Thread structures
- defn _threadlist(t)
- {
- local l;
- l = {};
- while t do {
- t = (Thread)t;
- l = append l, t.pid;
- t = t.next;
- }
- return l;
- }
- // print info about a VtRendez
- defn vtrendez(r)
- {
- local l, t, w, q;
- r = (VtRendez)r;
- w = _threadlist(r.wfirst);
- if match(pid, w) >= 0 then
- print("\twaiting for wakeup\n");
- l = (VtLock)r.lk;
- q = _threadlist(l.qfirst);
- if match(pid, q) >= 0 then
- print("\tawakened; waiting for lock\n");
- print("\tr=(VtRendez)", r\X, "\n");
- print("\tl=(VtLock)", l\X, "\n");
- if l.writer != 0 then {
- t = (Thread)l.writer;
- print("\tvtLock is held by ", t.pid\D, "\n");
- }
- }
- // print info about a VtLock
- defn vtlock(l)
- {
- local t;
- l = (VtLock)l;
- print("\tl=(VtLock)", l\X, "\n");
- if l.writer then {
- t = (Thread)l.writer;
- print("\tvtLock is held by ", t.pid\D, "\n");
- } else if l.readers then
- print("\tvtLock is held by ", l.readers\D, " readers\n");
- else
- print("\tvtLock is not held!\n");
- }
- // try to say something intelligent about why a process is stuck.
- _pauses = {
- open,
- pread,
- pwrite,
- sleep,
- vtSleep,
- vtLock,
- vtRLock,
- };
- defn deadlocklist(l)
- {
- while l do {
- setproc(head l);
- deadlock();
- l = tail l;
- }
- }
- defn deadlock()
- {
- local stk, frame, name, stallframe, fossilframe, stallname;
- stk = strace(*PC, *SP, linkreg(0));
- print("setproc(", pid, ") // ", readfile("/proc/"+itoa(pid)+"/args"), "\n");
- stallframe = 0;
- stallname = "";
- fossilframe = 0;
- frame = {0};
- while stk do {
- lastframe = frame;
- frame = head stk;
- name = fmt(frame[0], 'a');
- if !stallframe && match(name, _pauses) >= 0 then {
- stallframe = frame;
- stallname = name;
- print("\t", fmt(frame[0], 'a'), "(");
- params(frame[2]);
- print(") ", pcfile(frame[0]), ":", pcline(frame[0]));
- print("\n\t\tcalled from ", fmt(frame[1], 'a'), " ");
- pfl(frame[1]);
- }
- if !fossilframe && regexp("^/sys/src/cmd/fossil/.*", pcfile(frame[0])) then {
- if !stallframe then {
- stallframe = lastframe;
- stallname = fmt(lastframe[0], 'a');
- print("\tunexpected stall: ", stallname, "\n");
- if match(stallname, _pauses) >= 0 then
- print("\t\t but it matches!\n");
- }
- fossilframe = frame;
- print("\t", fmt(frame[0], 'a'), "(");
- params(frame[2]);
- print(") ", pcfile(frame[0]), ":", pcline(frame[0]));
- print("\n\t\tcalled from ", fmt(frame[1], 'a'), " ");
- pfl(frame[1]);
- if name == cacheLocalLookup && stallname == vtLock then
- print("\twaiting to lock block b=(Block)", *cacheLocalLookup:b\X, "\n");
- if name == cacheLocal && stallname == vtSleep then
- print("\tsleeping on block b=(Block)", *cacheLocal:b\X, "\n");
- if name == blockWrite && stallname == vtSleep then
- print("\tsleeping on block b=(Block)", *blockFlush:b\X, "\n");
- }
- stk = tail stk;
- }
- if stallname == vtSleep then
- vtrendez(*vtSleep:q);
- if stallname == vtLock then
- vtlock(*vtLock:p);
- if !stallframe || !fossilframe then {
- print("\tconfused:");
- if !stallframe then print(" stallframe?");
- if !fossilframe then print(" fossilframe?");
- print("\n");
- }
- print("\n");
- }
- // fetch fsys
- defn
- fsysGet(name)
- {
- return fsysmain;
- }
- // dump information about the cache
- defn
- cacheDump(c)
- {
- local i, b, x;
- c = (Cache)c;
- x = c.blocks;
- i=0;
- loop 1,c.nblocks do {
- b = (Block)(x+i);
- print(b\X, " ", b.pc\X, " ", b.ref\D, "\n");
- i = i+sizeofBlock;
- }
- }
- // print block info
- defn
- printblist(bl)
- {
- bl = (BList)bl;
- while bl != 0 do {
- print("[", bl.part\D, " ", bl.addr\X, " ", bl.vers\D, "]");
- bl = bl.next;
- if bl != 0 then
- print(", ");
- }
- }
- defn
- block(b)
- {
- local i;
-
- b = (Block)b;
- print("b=(Block)", b\X, "\n");
- print("\tref ", b.ref\D, " nlock ", b.nlock\D, "\n");
- print("\tpav=[", b.part\D, " ", b.addr\X, " ", b.vers\D, "]\n");
- print("\tprior=");
- printblist(b.prior);
- print("\n");
- print("\tunlink=");
- printblist(b.uhead);
- print("\n");
- }
|