static long
handleread(DTChan *c, void *a, long n, int(*readf)(DTChan *, void *, int))
{
long rc, m;
int i;
for(;;){
rc = lockedread(c, a, n, readf);
if(rc < 0) return -1;
if(rc > 0) break;
tsleep(&up->sleep, return0, 0, 250);
}
m = rc;
for(i = 0; i < 3 && m < n/2; i++){
tsleep(&up->sleep, return0, 0, 50);
rc = lockedread(c, (uchar *)a + m, n - m, readf);
if(rc < 0) break;
m += rc;
}
return m;
}
static long
probesread(DTKAux *aux, char *a, long n, vlong off)
{
Fmt f;
DTProbe **l;
int i, nl;
if(aux->str == nil){
fmtstrinit(&f);
nl = dtplist(&l);
for(i = 0; i < nl; i++)
fmtprint(&f, "%s\n", l[i]->name);
dtfree(l);
aux->str = fmtstrflush(&f);
}
return readstr(off, a, n, aux->str);
}
static long
dtracyread(Chan *c, void *a, long n, vlong off)
{
int rc;
DTKChan *p;
DTChan *ch;
eqlock(&dtracylock);
if(waserror()){
qunlock(&dtracylock);
nexterror();
}
if(SLOT(c->qid) == -1)
switch((int)c->qid.path){
case Qdir:
rc = devdirread(c, a, n, nil, 0, dtracygen);
goto out;
case Qprobes:
rc = probesread(c->aux, a, n, off);
goto out;
default:
error(Egreg);
}
p = dtklook(SLOT(c->qid));
if(p == nil) error(Enonexist);
switch(FILE(c->qid)){
case Qdir:
rc = devdirread(c, a, n, nil, 0, dtracygen);
break;
case Qctl:
sprint(up->genbuf, "%d", p->idx);
rc = readstr(off, a, n, up->genbuf);
break;
case Qbuf:
ch = p->ch;
qunlock(&dtracylock);
poperror();
return handleread(ch, a, n, dtcread);
case Qaggbuf:
ch = p->ch;
qunlock(&dtracylock);
poperror();
return handleread(ch, a, n, dtcaggread);
case Qepid:
rc = epidread(c->aux, p->ch, a, n, off);
break;
default:
error(Egreg);
return 0;
}
out:
qunlock(&dtracylock);
poperror();
return rc;
}
static long
dtracywrite(Chan *c, void *a, long n, vlong)
{
int rc;
DTKChan *p;
Cmdbuf *cb;
Cmdtab *ct;
eqlock(&dtracylock);
if(waserror()){
qunlock(&dtracylock);
nexterror();
}
if(SLOT(c->qid) == -1)
switch((int)c->qid.path){
case Qdir:
error(Eperm);
default:
error(Egreg);
}
p = dtklook(SLOT(c->qid));
if(p == nil) error(Enonexist);
switch(FILE(c->qid)){
case Qdir:
error(Eperm);
return 0;
case Qctl:
cb = parsecmd(a, n);
if(waserror()){
free(cb);
nexterror();
}
ct = lookupcmd(cb, dtracyctlmsg, nelem(dtracyctlmsg));
switch(ct->index){
case CMstop: dtcrun(p->ch, DTCSTOP); break;
case CMgo: dtcrun(p->ch, DTCGO); break;
default:
error(Egreg);
}
poperror();
free(cb);
rc = n;
break;
case Qprog:
{
char *buf;