2 #include "../port/lib.h"
6 #include "../port/error.h"
12 typedef struct DTKChan DTKChan;
13 typedef struct DTKAux DTKAux;
26 prog(DTKChan *p, char *s)
31 dtcrun(p->ch, DTCSTOP);
34 s = dtclunpack(s, &c);
36 error("invalid program");
37 rc = dtcaddcl(p->ch, c);
60 static Dirtab dtracydir[] = {
61 "ctl", { Qctl, 0, 0 }, 0, 0660,
62 "prog", { Qprog, 0, 0 }, 0, 0660,
63 "buf", { Qbuf, 0, 0, }, 0, 0440,
64 "epid", { Qepid, 0, 0 }, 0, 0440,
65 "aggbuf", { Qaggbuf, 0, 0 }, 0, 0440,
73 static Cmdtab dtracyctlmsg[] = {
84 if((uvlong)n >= ndtktab) return nil;
87 #define QIDPATH(q,e) ((q) + 1 << 8 | (e))
88 #define SLOT(q) ((vlong)((q).path >> 8) - 1)
89 #define FILE(q) ((int)(q).path & 0xff)
98 p = malloc(sizeof(DTKChan));
99 if(p == nil) error(Enomem);
100 for(i = 0; i < ndtktab; i++)
101 if(dtktab[i] == nil){
107 newtab = realloc(dtktab, (ndtktab + 1) * sizeof(DTKChan *));
108 if(newtab == nil) error(Enomem);
133 dtracyen = getconf("*dtracy") != nil;
134 if(!dtracyen) return;
135 machlocks = smalloc(sizeof(Lock) * conf.nmach);
140 dtracyattach(char *spec)
143 error("*dtracy= not set");
144 return devattach(L'Δ', spec);
148 dtracygen(Chan *c, char *, Dirtab *, int, int s, Dir *dp)
154 devdir(c, (Qid){Qdir, 0, QTDIR}, "#Δ", 0, eve, 0555, dp);
157 if(c->qid.path == Qdir){
158 if(s-- == 0) goto clone;
159 if(s >= ndtktab) return -1;
160 if(dtklook(s) == nil) return 0;
161 sprint(up->genbuf, "%d", s);
162 devdir(c, (Qid){QIDPATH(s, Qdir), 0, QTDIR}, up->genbuf, 0, eve, DMDIR|0555, dp);
165 if(c->qid.path == Qclone){
167 strcpy(up->genbuf, "clone");
168 devdir(c, (Qid){Qclone, 0, QTFILE}, up->genbuf, 0, eve, 0444, dp);
171 if(s >= nelem(dtracydir))
174 path = QIDPATH(SLOT(c->qid), 0);
175 devdir(c, (Qid){tab->qid.path|path, tab->qid.vers, tab->qid.type}, tab->name, tab->length, eve, tab->perm, dp);
180 dtracywalk(Chan *c, Chan *nc, char **name, int nname)
186 qunlock(&dtracylock);
189 rc = devwalk(c, nc, name, nname, nil, 0, dtracygen);
190 qunlock(&dtracylock);
196 dtracystat(Chan *c, uchar *dp, int n)
202 qunlock(&dtracylock);
205 rc = devstat(c, dp, n, nil, 0, dtracygen);
206 qunlock(&dtracylock);
212 dtracyopen(Chan *c, int omode)
219 qunlock(&dtracylock);
222 if(c->qid.path == Qclone){
223 if(!iseve()) error(Eperm);
225 c->qid.path = QIDPATH(p->idx, Qctl);
227 p = dtklook(SLOT(c->qid));
228 if(SLOT(c->qid) >= 0 && p == nil) error(Enonexist);
229 if(FILE(c->qid) != Qdir && !iseve()) error(Eperm);
230 ch = devopen(c, omode, nil, 0, dtracygen);
231 if(p != nil) p->ref++;
232 qunlock(&dtracylock);
234 ch->aux = smalloc(sizeof(DTKAux));
239 dtracyclose(Chan *ch)
246 p = dtklook(SLOT(ch->qid));
247 if(p != nil && --p->ref == 0)
249 qunlock(&dtracylock);
258 epidread(DTKAux *aux, DTChan *c, char *a, long n, vlong off)
269 for(e = c->enab; e != nil; e = e->channext){
270 fmtprint(&f, "%d %d %d %s:%s:%s\n", e->epid, e->gr->id, e->gr->reclen,
271 e->prob->provider == nil ? "" : e->prob->provider,
272 e->prob->function == nil ? "" : e->prob->function,
273 e->prob->name == nil ? "" : e->prob->name);
275 aux->str = fmtstrflush(&f);
277 return readstr(off, a, n, aux->str);
281 lockedread(DTChan *c, void *a, long n, int(*readf)(DTChan *, void *, int))
286 qunlock(&dtracylock);
291 qunlock(&dtracylock);
297 handleread(DTChan *c, void *a, long n, int(*readf)(DTChan *, void *, int))
303 rc = lockedread(c, a, n, readf);
304 if(rc < 0) return -1;
306 tsleep(&up->sleep, return0, 0, 250);
309 for(i = 0; i < 3 && m < n/2; i++){
310 tsleep(&up->sleep, return0, 0, 50);
311 rc = lockedread(c, (uchar *)a + m, n - m, readf);
319 dtracyread(Chan *c, void *a, long n, vlong off)
327 qunlock(&dtracylock);
330 if(SLOT(c->qid) == -1)
331 switch((int)c->qid.path){
333 rc = devdirread(c, a, n, nil, 0, dtracygen);
338 p = dtklook(SLOT(c->qid));
339 if(p == nil) error(Enonexist);
340 switch(FILE(c->qid)){
342 rc = devdirread(c, a, n, nil, 0, dtracygen);
345 sprint(up->genbuf, "%d", p->idx);
346 rc = readstr(off, a, n, up->genbuf);
350 qunlock(&dtracylock);
352 return handleread(ch, a, n, dtcread);
355 qunlock(&dtracylock);
357 return handleread(ch, a, n, dtcaggread);
359 rc = epidread(c->aux, p->ch, a, n, off);
366 qunlock(&dtracylock);
372 dtracywrite(Chan *c, void *a, long n, vlong)
381 qunlock(&dtracylock);
384 if(SLOT(c->qid) == -1)
385 switch((int)c->qid.path){
391 p = dtklook(SLOT(c->qid));
392 if(p == nil) error(Enonexist);
393 switch(FILE(c->qid)){
403 ct = lookupcmd(cb, dtracyctlmsg, nelem(dtracyctlmsg));
405 case CMstop: dtcrun(p->ch, DTCSTOP); break;
406 case CMgo: dtcrun(p->ch, DTCGO); break;
434 qunlock(&dtracylock);
467 setmalloctag(v, getcallerpc(&n));
478 dtrealloc(void *v, ulong n)
482 setrealloctag(v, getcallerpc(&v));
489 ilock(&machlocks[i]);
495 iunlock(&machlocks[i]);
507 return fastticks(nil);
515 return up != nil ? up->pid : 0;
522 dtpeek(uvlong addr, void *buf, int len)
524 if((uintptr)addr != addr || up == nil || !okaddr((uintptr) addr, len, 0)) return -1;
525 memmove(buf, (void *) addr, len);