xref: /plan9/sys/src/cmd/fossil/fossil-acid (revision 588b1baa64338d634bd996f0711914a959505073)
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