summaryrefslogtreecommitdiff
path: root/sys/src
diff options
context:
space:
mode:
authoraiju <devnull@localhost>2018-12-13 10:42:49 +0000
committeraiju <devnull@localhost>2018-12-13 10:42:49 +0000
commitc7304ea03caf68cf035d14f50f6e24e0c16ccdfe (patch)
treef4b5e8047078c41caa0d98cc0ea3d5012c4d17f9 /sys/src
parentdae5a44111dfb21a714824a5cec2abee4f9f9080 (diff)
dtracy: get rid of DTName struct, support more than three parts in a probe name, wildcard matching
Diffstat (limited to 'sys/src')
-rw-r--r--sys/src/9/port/devdtracy.c47
-rw-r--r--sys/src/9/port/dtracysys.c13
-rw-r--r--sys/src/9/port/dtracytimer.c8
-rw-r--r--sys/src/cmd/dtracy/act.c24
-rw-r--r--sys/src/cmd/dtracy/parse.y8
-rw-r--r--sys/src/libdtracy/chan.c50
-rw-r--r--sys/src/libdtracy/prov.c126
7 files changed, 189 insertions, 87 deletions
diff --git a/sys/src/9/port/devdtracy.c b/sys/src/9/port/devdtracy.c
index 4bd47ca0e..018bad624 100644
--- a/sys/src/9/port/devdtracy.c
+++ b/sys/src/9/port/devdtracy.c
@@ -46,6 +46,7 @@ prog(DTKChan *p, char *s)
enum {
/* Qdir */
Qclone = 1,
+ Qprobes = 2,
};
enum {
@@ -156,6 +157,7 @@ dtracygen(Chan *c, char *, Dirtab *, int, int s, Dir *dp)
}
if(c->qid.path == Qdir){
if(s-- == 0) goto clone;
+ if(s-- == 0) goto probes;
if(s >= ndtktab) return -1;
if(dtklook(s) == nil) return 0;
sprint(up->genbuf, "%d", s);
@@ -168,6 +170,12 @@ dtracygen(Chan *c, char *, Dirtab *, int, int s, Dir *dp)
devdir(c, (Qid){Qclone, 0, QTFILE}, up->genbuf, 0, eve, 0444, dp);
return 1;
}
+ if(c->qid.path == Qprobes){
+ probes:
+ strcpy(up->genbuf, "probes");
+ devdir(c, (Qid){Qprobes, 0, QTFILE}, up->genbuf, 0, eve, 0444, dp);
+ return 1;
+ }
if(s >= nelem(dtracydir))
return -1;
tab = &dtracydir[s];
@@ -224,9 +232,13 @@ dtracyopen(Chan *c, int omode)
p = dtknew();
c->qid.path = QIDPATH(p->idx, Qctl);
}
- p = dtklook(SLOT(c->qid));
- if(SLOT(c->qid) >= 0 && p == nil) error(Enonexist);
- if(FILE(c->qid) != Qdir && !iseve()) error(Eperm);
+ if(c->qid.path == Qprobes){
+ p = nil;
+ }else{
+ p = dtklook(SLOT(c->qid));
+ if(SLOT(c->qid) >= 0 && p == nil) error(Enonexist);
+ if(FILE(c->qid) != Qdir && !iseve()) error(Eperm);
+ }
ch = devopen(c, omode, nil, 0, dtracygen);
if(p != nil) p->ref++;
qunlock(&dtracylock);
@@ -266,12 +278,8 @@ epidread(DTKAux *aux, DTChan *c, char *a, long n, vlong off)
}
if(aux->str == nil){
fmtstrinit(&f);
- for(e = c->enab; e != nil; e = e->channext){
- fmtprint(&f, "%d %d %d %s:%s:%s\n", e->epid, e->gr->id, e->gr->reclen,
- e->prob->provider == nil ? "" : e->prob->provider,
- e->prob->function == nil ? "" : e->prob->function,
- e->prob->name == nil ? "" : e->prob->name);
- }
+ for(e = c->enab; e != nil; e = e->channext)
+ fmtprint(&f, "%d %d %d %s\n", e->epid, e->gr->id, e->gr->reclen, e->prob->name);
aux->str = fmtstrflush(&f);
}
return readstr(off, a, n, aux->str);
@@ -316,6 +324,24 @@ handleread(DTChan *c, void *a, long n, int(*readf)(DTChan *, void *, int))
}
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;
@@ -332,6 +358,9 @@ dtracyread(Chan *c, void *a, long n, vlong off)
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);
}
diff --git a/sys/src/9/port/dtracysys.c b/sys/src/9/port/dtracysys.c
index 859dd9f84..1e525052d 100644
--- a/sys/src/9/port/dtracysys.c
+++ b/sys/src/9/port/dtracysys.c
@@ -215,14 +215,11 @@ static Syscall *wraptab[]={
};
static void
-sysprovide(DTProvider *prov, DTName)
+sysprovide(DTProvider *prov)
{
- static int provided;
- char buf[32];
+ char buf[32], pname[32];
int i;
- if(provided) return;
- provided = 1;
dtpsysentry = smalloc(sizeof(Syscall *) * nsyscall);
dtpsysreturn = smalloc(sizeof(Syscall *) * nsyscall);
for(i = 0; i < nsyscall; i++){
@@ -230,8 +227,10 @@ sysprovide(DTProvider *prov, DTName)
strecpy(buf, buf + sizeof(buf), sysctab[i]);
if(isupper(buf[0])) buf[0] += 'a' - 'A';
if(i == SYSR1) strcpy(buf, "r1");
- dtpsysentry[i] = dtpnew((DTName){"sys", buf, "entry"}, prov, (void *) i);
- dtpsysreturn[i] = dtpnew((DTName){"sys", buf, "return"}, prov, (void *) i);
+ snprint(pname, sizeof(pname), "sys:%s:entry", buf);
+ dtpsysentry[i] = dtpnew(pname, prov, (void *) i);
+ snprint(pname, sizeof(pname), "sys:%s:return", buf);
+ dtpsysreturn[i] = dtpnew(pname, prov, (void *) i);
}
}
diff --git a/sys/src/9/port/dtracytimer.c b/sys/src/9/port/dtracytimer.c
index cb3b636f6..0c39a1042 100644
--- a/sys/src/9/port/dtracytimer.c
+++ b/sys/src/9/port/dtracytimer.c
@@ -22,13 +22,9 @@ dtracytimer(void *)
}
static void
-timerprovide(DTProvider *prov, DTName)
+timerprovide(DTProvider *prov)
{
- static int provided;
-
- if(provided) return;
- provided = 1;
- timerprobe = dtpnew((DTName){"timer", "", "1s"}, prov, nil);
+ timerprobe = dtpnew("timer::1s", prov, nil);
}
static int
diff --git a/sys/src/cmd/dtracy/act.c b/sys/src/cmd/dtracy/act.c
index 3412382c3..dde47ae57 100644
--- a/sys/src/cmd/dtracy/act.c
+++ b/sys/src/cmd/dtracy/act.c
@@ -41,6 +41,28 @@ mkval(int type, ...)
return r;
}
+static char *
+insertstars(char *n)
+{
+ Fmt f;
+ int partlen;
+
+ fmtstrinit(&f);
+ partlen = 0;
+ for(; *n != 0; n++){
+ if(*n == ':'){
+ if(partlen == 0)
+ fmtrune(&f, '*');
+ partlen = 0;
+ }else
+ partlen++;
+ fmtrune(&f, *n);
+ }
+ if(partlen == 0)
+ fmtrune(&f, '*');
+ return fmtstrflush(&f);
+}
+
void
clausebegin(void)
{
@@ -52,7 +74,7 @@ void
addprobe(char *s)
{
clause->probs = erealloc(clause->probs, sizeof(char *) * (clause->nprob + 1));
- clause->probs[clause->nprob++] = strdup(s);
+ clause->probs[clause->nprob++] = insertstars(s);
}
static char *aggtypes[] = {
diff --git a/sys/src/cmd/dtracy/parse.y b/sys/src/cmd/dtracy/parse.y
index 81a57f79b..893d6dac3 100644
--- a/sys/src/cmd/dtracy/parse.y
+++ b/sys/src/cmd/dtracy/parse.y
@@ -19,6 +19,7 @@
%type <n> expr optexpr
%type <sym> optsym
%type <t> type
+%type <str> probe
%token <sym> TSYM
%token <num> TNUM
@@ -119,8 +120,11 @@ type:
| TSTRING { $$ = type(TYPSTRING); }
probes:
- TSYM { addprobe($1->name); }
- | probes ',' TSYM { addprobe($3->name); }
+ probe { addprobe($1); }
+ | probes ',' probe { addprobe($3); }
+probe:
+ TSYM { $$ = $1->name; }
+ | TSTR { $$ = $1; }
%%
diff --git a/sys/src/libdtracy/chan.c b/sys/src/libdtracy/chan.c
index c29f24eb4..b926c965e 100644
--- a/sys/src/libdtracy/chan.c
+++ b/sys/src/libdtracy/chan.c
@@ -81,7 +81,7 @@ dtcfree(DTChan *ch)
}
int
-dtcaddgr(DTChan *c, DTName name, DTActGr *gr)
+dtcaddgr(DTChan *c, char *name, DTActGr *gr)
{
DTProbe **l, *p;
DTEnab *ep;
@@ -92,6 +92,11 @@ dtcaddgr(DTChan *c, DTName name, DTActGr *gr)
gr->chan = c;
nl = dtpmatch(name, &l);
+ if(nl == 0){
+ dtfree(l);
+ werrstr("no match for %s", name);
+ return -1;
+ }
n = 0;
for(i = 0; i < nl; i++){
p = l[i];
@@ -118,53 +123,14 @@ dtcaddgr(DTChan *c, DTName name, DTActGr *gr)
return n;
}
-static int
-dtnamesplit(char *s, DTName *rp)
-{
- char *p;
-
- p = strchr(s, ':');
- if(p == nil) return -1;
- rp->provider = dtmalloc(p - s + 1);
- memcpy(rp->provider, s, p - s);
- s = p + 1;
- p = strchr(s, ':');
- if(p == nil){
- free(rp->provider);
- rp->provider = nil;
- return -1;
- }
- rp->function = dtmalloc(p - s + 1);
- memcpy(rp->function, s, p - s);
- s = p + 1;
- if(strchr(s, ':') != nil){
- free(rp->provider);
- rp->provider = nil;
- free(rp->function);
- rp->function = nil;
- return -1;
- }
- rp->name = dtstrdup(s);
- return 0;
-}
-
int
dtcaddcl(DTChan *c, DTClause *cl)
{
- DTName n;
int i, rc;
rc = 0;
- for(i = 0; i < cl->nprob; i++){
- if(dtnamesplit(cl->probs[i], &n) < 0){
- werrstr("invalid probe name '%s'", cl->probs[i]);
- return -1;
- }
- rc += dtcaddgr(c, n, cl->gr);
- dtfree(n.provider);
- dtfree(n.function);
- dtfree(n.name);
- }
+ for(i = 0; i < cl->nprob; i++)
+ rc += dtcaddgr(c, cl->probs[i], cl->gr);
return rc;
}
diff --git a/sys/src/libdtracy/prov.c b/sys/src/libdtracy/prov.c
index 8becbc756..c9e4f822c 100644
--- a/sys/src/libdtracy/prov.c
+++ b/sys/src/libdtracy/prov.c
@@ -14,14 +14,12 @@ dtstrdup(char *n)
}
DTProbe *
-dtpnew(DTName name, DTProvider *prov, void *aux)
+dtpnew(char *name, DTProvider *prov, void *aux)
{
DTProbe *p, **pp;
p = dtmalloc(sizeof(DTProbe));
- p->provider = dtstrdup(name.provider);
- p->function = dtstrdup(name.function);
- p->name = dtstrdup(name.name);
+ p->name = dtstrdup(name);
p->prov = prov;
p->aux = aux;
p->enablist.probnext = p->enablist.probprev = &p->enablist;
@@ -31,46 +29,134 @@ dtpnew(DTName name, DTProvider *prov, void *aux)
return p;
}
+/* does the pattern match at most one probe (or provider if provonly)? */
+static int
+patunique(char *pat, int provonly)
+{
+ for(;; pat++)
+ switch(*pat){
+ case ':':
+ if(provonly){
+ case 0:
+ return 1;
+ }
+ break;
+ case '?':
+ case '*':
+ return 0;
+ }
+}
+
+static char *
+partmatch(char *pat, char *str, int provonly)
+{
+ for(;; pat++, str++){
+ if(*pat == '*')
+ return pat;
+ if(*pat != *str && (*pat != '?' || *str == ':') && (!provonly || *pat != ':' || *str != 0))
+ return nil;
+ if(*pat == 0 || *pat == ':' && provonly)
+ return (void*)-1;
+ }
+}
+
+/*
+ do a wildcard match with * and ?, but don't match : against a wildcard
+ if provonly, stop at the first :
+
+ replacing empty parts with * is done in user space
+*/
int
-dtstrmatch(char *a, char *b)
+dtnamematch(char *pat, char *str, int provonly)
{
- if(a == nil || *a == 0) return 1;
- if(b == nil) return 0;
- return strcmp(a, b) == 0;
+ char *patp, *strp, *p;
+
+ patp = partmatch(pat, str, provonly);
+ if(patp == nil) return 0;
+ if(patp == (void*)-1) return 1;
+ /* reached a * */
+ strp = str + (patp - pat);
+ patp++;
+ for(;;){
+ /* try the rest of the pattern against each position */
+ p = partmatch(patp, strp, provonly);
+ if(p == nil){
+ if(*strp == 0 || *strp == ':') return 0;
+ strp++;
+ continue;
+ }
+ if(p == (void*)-1)
+ return 1;
+ /* reached another * */
+ strp += p - patp;
+ patp = p + 1;
+ }
}
int
-dtpmatch(DTName name, DTProbe ***ret)
+dtpmatch(char *name, DTProbe ***ret)
{
DTProbe **l;
int nl;
DTProvider **provp, *prov;
DTProbe **pp, *p;
+ int unique, uniqueprov;
l = nil;
nl = 0;
+ unique = patunique(name, 0);
+ uniqueprov = patunique(name, 1);
for(provp = dtproviders; prov = *provp, prov != nil; provp++){
- if(!dtstrmatch(name.provider, prov->name))
+ if(!dtnamematch(name, prov->name, 1))
continue;
- for(pp = &prov->probes; p = *pp, p != nil; pp = &p->provnext)
- if(dtstrmatch(name.function, p->function) && dtstrmatch(name.name, p->name)){
+ if(!prov->provided){
+ prov->provided = 1;
+ prov->provide(prov);
+ }
+ for(pp = &prov->probes; p = *pp, p != nil; pp = &p->provnext){
+ if(dtnamematch(name, p->name, 0)){
if(ret != nil){
l = dtrealloc(l, (nl + 1) * sizeof(DTProbe *));
l[nl] = p;
}
nl++;
+ if(unique) goto out;
}
- prov->provide(prov, name);
- for(; p = *pp, p != nil; pp = &p->provnext)
- if(dtstrmatch(name.function, p->function) && dtstrmatch(name.name, p->name)){
- if(ret != nil){
- l = dtrealloc(l, (nl + 1) * sizeof(DTProbe *));
- l[nl] = p;
- }
- nl++;
+ }
+ if(uniqueprov) goto out;
+ }
+out:
+ if(ret != nil)
+ *ret = l;
+ return nl;
+}
+
+int
+dtplist(DTProbe ***ret)
+{
+ DTProbe **l;
+ int nl;
+ DTProvider **provp, *prov;
+ DTProbe **pp, *p;
+
+ l = nil;
+ nl = 0;
+ for(provp = dtproviders; prov = *provp, prov != nil; provp++){
+ if(!prov->provided){
+ prov->provided = 1;
+ prov->provide(prov);
+ }
+ for(pp = &prov->probes; p = *pp, p != nil; pp = &p->provnext){
+ if(ret != nil){
+ l = dtrealloc(l, (nl + 1) * sizeof(DTProbe *));
+ l[nl] = p;
}
+ nl++;
+ }
}
if(ret != nil)
*ret = l;
+ else
+ dtfree(l);
return nl;
}