Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
// pick up the common data structures
2
 
3
rc("cd /sys/src/cmd/fossil; mk 9fsys.acid");
4
include("/sys/src/cmd/fossil/9fsys.acid");
5
rc("cd /sys/src/cmd/fossil; mk cache.acid");
6
include("/sys/src/cmd/fossil/cache.acid");
7
rc("cd /sys/src/cmd/fossil; mk disk.acid");
8
include("/sys/src/cmd/fossil/disk.acid");
9
rc("cd /sys/src/cmd/fossil; mk fs.acid");
10
include("/sys/src/cmd/fossil/fs.acid");
11
rc("cd /sys/src/liboventi; mk plan9-thread.acid");
12
include("/sys/src/liboventi/plan9-thread.acid");
13
 
14
// make a list of pids from a list of Thread structures
15
defn _threadlist(t)
16
{
17
	local l;
18
 
19
	l = {};
20
	while t do {
21
		t = (Thread)t;
22
		l = append l, t.pid;
23
		t = t.next;
24
	}
25
	return l;
26
}
27
 
28
// print info about a VtRendez
29
defn vtrendez(r)
30
{
31
	local l, t, w, q;
32
 
33
	r = (VtRendez)r;
34
	w = _threadlist(r.wfirst);
35
	if match(pid, w) >= 0 then
36
		print("\twaiting for wakeup\n");
37
 
38
	l = (VtLock)r.lk;
39
	q = _threadlist(l.qfirst);
40
	if match(pid, q) >= 0 then
41
		print("\tawakened; waiting for lock\n");
42
 
43
	print("\tr=(VtRendez)", r\X, "\n");
44
	print("\tl=(VtLock)", l\X, "\n");
45
	if l.writer != 0 then {
46
		t = (Thread)l.writer;
47
		print("\tvtLock is held by ", t.pid\D, "\n");
48
	}
49
}
50
 
51
// print info about a VtLock
52
defn vtlock(l)
53
{
54
	local t;
55
 
56
	l = (VtLock)l;
57
	print("\tl=(VtLock)", l\X, "\n");
58
	if l.writer then {
59
		t = (Thread)l.writer;
60
		print("\tvtLock is held by ", t.pid\D, "\n");
61
	} else if l.readers then
62
		print("\tvtLock is held by ", l.readers\D, " readers\n");
63
	else 
64
		print("\tvtLock is not held!\n");
65
}
66
 
67
// try to say something intelligent about why a process is stuck.
68
_pauses = {
69
	open,
70
	pread,
71
	pwrite,
72
	sleep,
73
	vtSleep,
74
	vtLock,
75
	vtRLock,
76
};
77
 
78
defn deadlocklist(l)
79
{
80
	while l do {
81
		setproc(head l);
82
		deadlock();
83
		l = tail l;
84
	}
85
}
86
 
87
defn deadlock()
88
{
89
	local stk, frame, name, stallframe, fossilframe, stallname;
90
 
91
	stk = strace(*PC, *SP, linkreg(0));
92
 
93
	print("setproc(", pid, ") // ", readfile("/proc/"+itoa(pid)+"/args"), "\n");
94
	stallframe = 0;
95
	stallname = "";
96
	fossilframe = 0;
97
	frame = {0};
98
	while stk do {
99
		lastframe = frame;
100
		frame = head stk;
101
		name = fmt(frame[0], 'a');
102
		if !stallframe && match(name, _pauses) >= 0 then {
103
			stallframe = frame;
104
			stallname = name;
105
			print("\t", fmt(frame[0], 'a'), "(");
106
			params(frame[2]);
107
			print(") ", pcfile(frame[0]), ":", pcline(frame[0]));
108
			print("\n\t\tcalled from ", fmt(frame[1], 'a'), " ");
109
			pfl(frame[1]);
110
		}
111
		if !fossilframe && regexp("^/sys/src/cmd/fossil/.*", pcfile(frame[0])) then {
112
			if !stallframe then {
113
				stallframe = lastframe;
114
				stallname = fmt(lastframe[0], 'a');
115
				print("\tunexpected stall: ", stallname, "\n");
116
				if match(stallname, _pauses) >= 0 then
117
					print("\t\t but it matches!\n");
118
			}
119
			fossilframe = frame;
120
			print("\t", fmt(frame[0], 'a'), "(");
121
			params(frame[2]);
122
			print(") ", pcfile(frame[0]), ":", pcline(frame[0]));
123
			print("\n\t\tcalled from ", fmt(frame[1], 'a'), " ");
124
			pfl(frame[1]);
125
 
126
			if name == cacheLocalLookup && stallname == vtLock then
127
				print("\twaiting to lock block b=(Block)", *cacheLocalLookup:b\X, "\n");
128
			if name == cacheLocal && stallname == vtSleep then
129
				print("\tsleeping on block b=(Block)", *cacheLocal:b\X, "\n");
130
			if name == blockWrite && stallname == vtSleep then
131
				print("\tsleeping on block b=(Block)", *blockFlush:b\X, "\n");
132
		}
133
		stk = tail stk;
134
	}
135
 
136
	if stallname == vtSleep then
137
		vtrendez(*vtSleep:q);
138
	if stallname == vtLock then
139
		vtlock(*vtLock:p);
140
	if !stallframe || !fossilframe then {
141
		print("\tconfused:");
142
		if !stallframe then print(" stallframe?");
143
		if !fossilframe then print(" fossilframe?");
144
		print("\n");
145
	}
146
	print("\n");
147
}
148
 
149
// fetch fsys
150
defn
151
fsysGet(name)
152
{
153
	return fsysmain;
154
}
155
 
156
// dump information about the cache
157
defn
158
cacheDump(c)
159
{
160
	local i, b, x;
161
 
162
	c = (Cache)c;
163
	x = c.blocks;
164
	i=0;
165
	loop 1,c.nblocks do {
166
		b = (Block)(x+i);
167
		print(b\X, " ", b.pc\X, " ", b.ref\D, "\n");
168
		i = i+sizeofBlock;
169
	}
170
}
171
 
172
// print block info
173
defn
174
printblist(bl)
175
{
176
	bl = (BList)bl;
177
	while bl != 0 do {
178
		print("[", bl.part\D, " ", bl.addr\X, " ", bl.vers\D, "]");
179
		bl = bl.next;
180
		if bl != 0 then
181
			print(", ");
182
	}
183
}
184
 
185
defn
186
block(b)
187
{
188
	local i;
189
 
190
	b = (Block)b;
191
	print("b=(Block)", b\X, "\n");
192
	print("\tref ", b.ref\D, " nlock ", b.nlock\D, "\n");
193
	print("\tpav=[", b.part\D, " ", b.addr\X, " ", b.vers\D, "]\n");
194
	print("\tprior=");
195
	printblist(b.prior);
196
	print("\n");
197
	print("\tunlink=");
198
	printblist(b.uhead);
199
	print("\n");
200
}