Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include	<u.h>
2
#include	<libc.h>
3
#include	<tos.h>
4
 
5
extern	long	_callpc(void**);
6
extern	long	_savearg(void);
7
 
8
static	ulong	khz;
9
static	ulong	perr;
10
static	int	havecycles;
11
 
12
typedef	struct	Plink	Plink;
13
struct	Plink
14
{
15
	Plink	*old;
16
	Plink	*down;
17
	Plink	*link;
18
	long	pc;
19
	long	count;
20
	vlong time;
21
};
22
 
23
#pragma profile off
24
 
25
ulong
26
_profin(void)
27
{
28
	void *dummy;
29
	long pc;
30
	Plink *pp, *p;
31
	ulong arg;
32
	vlong t;
33
 
34
	arg = _savearg();
35
	pc = _callpc(&dummy);
36
	pp = _tos->prof.pp;
37
	if(pp == 0 || (_tos->prof.pid && _tos->pid != _tos->prof.pid))
38
		return arg;
39
 
40
	for(p=pp->down; p; p=p->link)
41
		if(p->pc == pc)
42
			goto out;
43
	p = _tos->prof.next + 1;
44
	if(p >= _tos->prof.last) {
45
		_tos->prof.pp = 0;
46
		perr++;
47
		return arg;
48
	}
49
	_tos->prof.next = p;
50
	p->link = pp->down;
51
	pp->down = p;
52
	p->pc = pc;
53
	p->old = pp;
54
	p->down = 0;
55
	p->count = 0;
56
	p->time = 0LL;
57
 
58
out:
59
	_tos->prof.pp = p;
60
	p->count++;
61
	switch(_tos->prof.what){
62
	case Profkernel:
63
		p->time = p->time - _tos->pcycles;
64
		goto proftime;
65
	case Profuser:
66
		/* Add kernel cycles on proc entry */
67
		p->time = p->time + _tos->kcycles;
68
		/* fall through */
69
	case Proftime:	
70
	proftime:		/* Subtract cycle counter on proc entry */
71
		cycles((uvlong*)&t);
72
		p->time = p->time - t;
73
		break;
74
	case Profsample:
75
		p->time = p->time - _tos->clock;
76
		break;
77
	}
78
	return arg;		/* disgusting linkage */
79
}
80
 
81
ulong
82
_profout(void)
83
{
84
	Plink *p;
85
	ulong arg;
86
	vlong t;
87
 
88
	arg = _savearg();
89
	p = _tos->prof.pp;
90
	if (p == nil || (_tos->prof.pid != 0 && _tos->pid != _tos->prof.pid))
91
		return arg;	/* Not our process */
92
	switch(_tos->prof.what){
93
	case Profkernel:		/* Add proc cycles on proc entry */
94
		p->time = p->time + _tos->pcycles;
95
		goto proftime;
96
	case Profuser:			/* Subtract kernel cycles on proc entry */
97
		p->time = p->time - _tos->kcycles;
98
		/* fall through */
99
	case Proftime:	
100
	proftime:				/* Add cycle counter on proc entry */
101
		cycles((uvlong*)&t);
102
		p->time = p->time + t;
103
		break;
104
	case Profsample:
105
		p->time = p->time + _tos->clock;
106
		break;
107
	}
108
	_tos->prof.pp = p->old;
109
	return arg;
110
}
111
 
112
void
113
_profdump(void)
114
{
115
	int f;
116
	long n;
117
	Plink *p;
118
	char *vp;
119
	char filename[64];
120
 
121
	if (_tos->prof.what == 0)
122
		return;	/* No profiling */
123
	if (_tos->prof.pid != 0 && _tos->pid != _tos->prof.pid)
124
		return;	/* Not our process */
125
	if(perr)
126
		fprint(2, "%lud Prof errors\n", perr);
127
	_tos->prof.pp = nil;
128
	if (_tos->prof.pid)
129
		snprint(filename, sizeof filename - 1, "prof.%ld", _tos->prof.pid);
130
	else
131
		snprint(filename, sizeof filename - 1, "prof.out");
132
	f = create(filename, 1, 0666);
133
	if(f < 0) {
134
		perror("create prof.out");
135
		return;
136
	}
137
	_tos->prof.pid = ~0;	/* make sure data gets dumped once */
138
	switch(_tos->prof.what){
139
	case Profkernel:
140
		cycles((uvlong*)&_tos->prof.first->time);
141
		_tos->prof.first->time = _tos->prof.first->time + _tos->pcycles;
142
		break;
143
	case Profuser:
144
		cycles((uvlong*)&_tos->prof.first->time);
145
		_tos->prof.first->time = _tos->prof.first->time - _tos->kcycles;
146
		break;
147
	case Proftime:
148
		cycles((uvlong*)&_tos->prof.first->time);
149
		break;
150
	case Profsample:
151
		_tos->prof.first->time = _tos->clock;
152
		break;
153
	}
154
	vp = (char*)_tos->prof.first;
155
 
156
	for(p = _tos->prof.first; p <= _tos->prof.next; p++) {
157
 
158
		/*
159
		 * short down
160
		 */
161
		n = 0xffff;
162
		if(p->down)
163
			n = p->down - _tos->prof.first;
164
		vp[0] = n>>8;
165
		vp[1] = n;
166
 
167
		/*
168
		 * short right
169
		 */
170
		n = 0xffff;
171
		if(p->link)
172
			n = p->link - _tos->prof.first;
173
		vp[2] = n>>8;
174
		vp[3] = n;
175
		vp += 4;
176
 
177
		/*
178
		 * long pc
179
		 */
180
		n = p->pc;
181
		vp[0] = n>>24;
182
		vp[1] = n>>16;
183
		vp[2] = n>>8;
184
		vp[3] = n;
185
		vp += 4;
186
 
187
		/*
188
		 * long count
189
		 */
190
		n = p->count;
191
		vp[0] = n>>24;
192
		vp[1] = n>>16;
193
		vp[2] = n>>8;
194
		vp[3] = n;
195
		vp += 4;
196
 
197
		/*
198
		 * vlong time
199
		 */
200
		if (havecycles){
201
			n = (vlong)(p->time / (vlong)khz);
202
		}else
203
			n = p->time;
204
 
205
		vp[0] = n>>24;
206
		vp[1] = n>>16;
207
		vp[2] = n>>8;
208
		vp[3] = n;
209
		vp += 4;
210
	}
211
	write(f, (char*)_tos->prof.first, vp - (char*)_tos->prof.first);
212
	close(f);
213
}
214
 
215
void
216
_profinit(int entries, int what)
217
{
218
	if (_tos->prof.what == 0)
219
		return;	/* Profiling not linked in */
220
	_tos->prof.pp = nil;
221
	_tos->prof.first = mallocz(entries*sizeof(Plink),1);
222
	_tos->prof.last = _tos->prof.first + entries;
223
	_tos->prof.next = _tos->prof.first;
224
	_tos->prof.pid = _tos->pid;
225
	_tos->prof.what = what;
226
	_tos->clock = 1;
227
}
228
 
229
void
230
_profmain(void)
231
{
232
	char ename[50];
233
	int n, f;
234
 
235
	n = 2000;
236
	if (_tos->cyclefreq != 0LL){
237
		khz = _tos->cyclefreq / 1000;	/* Report times in milliseconds */
238
		havecycles = 1;
239
	}
240
	f = open("/env/profsize", OREAD);
241
	if(f >= 0) {
242
		memset(ename, 0, sizeof(ename));
243
		read(f, ename, sizeof(ename)-1);
244
		close(f);
245
		n = atol(ename);
246
	}
247
	_tos->prof.what = Profuser;
248
	f = open("/env/proftype", OREAD);
249
	if(f >= 0) {
250
		memset(ename, 0, sizeof(ename));
251
		read(f, ename, sizeof(ename)-1);
252
		close(f);
253
		if (strcmp(ename, "user") == 0)
254
			_tos->prof.what = Profuser;
255
		else if (strcmp(ename, "kernel") == 0)
256
			_tos->prof.what = Profkernel;
257
		else if (strcmp(ename, "elapsed") == 0 || strcmp(ename, "time") == 0)
258
			_tos->prof.what = Proftime;
259
		else if (strcmp(ename, "sample") == 0)
260
			_tos->prof.what = Profsample;
261
	}
262
	_tos->prof.first = sbrk(n*sizeof(Plink));
263
	_tos->prof.last = sbrk(0);
264
	_tos->prof.next = _tos->prof.first;
265
	_tos->prof.pp = nil;
266
	_tos->prof.pid = _tos->pid;
267
	atexit(_profdump);
268
	_tos->clock = 1;
269
}
270
 
271
void
272
prof(void (*fn)(void*), void *arg, int entries, int what)
273
{
274
	_profinit(entries, what);
275
	_tos->prof.pp = _tos->prof.next;
276
	fn(arg);
277
	_profdump();
278
}
279
 
280
#pragma profile on
281