5 extern uintptr _callpc(void**);
6 extern uintptr _saveret(void);
7 extern uintptr _savearg(void);
11 static int havecycles;
13 typedef struct Plink Plink;
27 _restore(uintptr, uintptr ret)
45 if(pp == 0 || (_tos->prof.pid && _tos->pid != _tos->prof.pid))
46 return _restore(arg, ret);
47 for(p=pp->down; p; p=p->link)
50 p = _tos->prof.next + 1;
51 if(p >= _tos->prof.last) {
54 return _restore(arg, ret);
68 switch(_tos->prof.what){
70 p->time = p->time - _tos->pcycles;
73 /* Add kernel cycles on proc entry */
74 p->time = p->time + _tos->kcycles;
77 proftime: /* Subtract cycle counter on proc entry */
79 p->time = p->time - t;
82 p->time = p->time - _tos->clock;
85 return _restore(arg, ret);
98 if (p == nil || (_tos->prof.pid != 0 && _tos->pid != _tos->prof.pid))
99 return _restore(arg, ret); /* Not our process */
100 switch(_tos->prof.what){
101 case Profkernel: /* Add proc cycles on proc entry */
102 p->time = p->time + _tos->pcycles;
104 case Profuser: /* Subtract kernel cycles on proc entry */
105 p->time = p->time - _tos->kcycles;
108 proftime: /* Add cycle counter on proc entry */
110 p->time = p->time + t;
113 p->time = p->time + _tos->clock;
116 _tos->prof.pp = p->old;
117 return _restore(arg, ret);
129 if (_tos->prof.what == 0)
130 return; /* No profiling */
131 if (_tos->prof.pid != 0 && _tos->pid != _tos->prof.pid)
132 return; /* Not our process */
134 fprint(2, "%lud Prof errors\n", perr);
137 snprint(filename, sizeof filename - 1, "prof.%ld", _tos->prof.pid);
139 snprint(filename, sizeof filename - 1, "prof.out");
140 f = create(filename, 1, 0666);
142 perror("create prof.out");
145 _tos->prof.pid = ~0; /* make sure data gets dumped once */
146 switch(_tos->prof.what){
148 cycles((uvlong*)&_tos->prof.first->time);
149 _tos->prof.first->time = _tos->prof.first->time + _tos->pcycles;
152 cycles((uvlong*)&_tos->prof.first->time);
153 _tos->prof.first->time = _tos->prof.first->time - _tos->kcycles;
156 cycles((uvlong*)&_tos->prof.first->time);
159 _tos->prof.first->time = _tos->clock;
162 vp = (char*)_tos->prof.first;
164 for(p = _tos->prof.first; p <= _tos->prof.next; p++) {
171 n = p->down - _tos->prof.first;
180 n = p->link - _tos->prof.first;
209 n = (vlong)(p->time / (vlong)khz);
219 write(f, (char*)_tos->prof.first, vp - (char*)_tos->prof.first);
224 _profinit(int entries, int what)
226 if (_tos->prof.what == 0)
227 return; /* Profiling not linked in */
229 _tos->prof.first = mallocz(entries*sizeof(Plink),1);
230 _tos->prof.last = _tos->prof.first + entries;
231 _tos->prof.next = _tos->prof.first;
232 _tos->prof.pid = _tos->pid;
233 _tos->prof.what = what;
244 if (_tos->cyclefreq != 0LL){
245 khz = _tos->cyclefreq / 1000; /* Report times in milliseconds */
248 f = open("/env/profsize", OREAD);
250 memset(ename, 0, sizeof(ename));
251 read(f, ename, sizeof(ename)-1);
255 _tos->prof.what = Profuser;
256 f = open("/env/proftype", OREAD);
258 memset(ename, 0, sizeof(ename));
259 read(f, ename, sizeof(ename)-1);
261 if (strcmp(ename, "user") == 0)
262 _tos->prof.what = Profuser;
263 else if (strcmp(ename, "kernel") == 0)
264 _tos->prof.what = Profkernel;
265 else if (strcmp(ename, "elapsed") == 0 || strcmp(ename, "time") == 0)
266 _tos->prof.what = Proftime;
267 else if (strcmp(ename, "sample") == 0)
268 _tos->prof.what = Profsample;
270 _tos->prof.first = sbrk(n*sizeof(Plink));
271 _tos->prof.last = sbrk(0);
272 _tos->prof.next = _tos->prof.first;
274 _tos->prof.pid = _tos->pid;
279 void prof(void (*fn)(void*), void *arg, int entries, int what)
281 _profinit(entries, what);
282 _tos->prof.pp = _tos->prof.next;