diff options
author | aiju <devnull@localhost> | 2018-11-10 13:46:16 +0000 |
---|---|---|
committer | aiju <devnull@localhost> | 2018-11-10 13:46:16 +0000 |
commit | e6d99771e5c1eef3f69fc847253d4709ffaa84be (patch) | |
tree | 16161401edc25c084ad24533519e094716965635 /sys/src/libdtracy/chan.c | |
parent | 8c097ae84a500eae9c8e4ee21b7b3ea8f8d23259 (diff) |
adding dtracy (crude early version)
Diffstat (limited to 'sys/src/libdtracy/chan.c')
-rw-r--r-- | sys/src/libdtracy/chan.c | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/sys/src/libdtracy/chan.c b/sys/src/libdtracy/chan.c new file mode 100644 index 000000000..16414834f --- /dev/null +++ b/sys/src/libdtracy/chan.c @@ -0,0 +1,222 @@ +#include <u.h> +#include <libc.h> +#include <dtracy.h> + +int dtnmach; + +void +dtinit(int nmach) +{ + DTProvider **p; + + dtnmach = nmach; + + /* sanity */ + for(p = dtproviders; *p != nil; p++){ + assert((*p)->name != nil); + assert((*p)->provide != nil); + assert((*p)->enable != nil); + assert((*p)->disable != nil); + } +} + +void +dtsync(void) +{ + int i; + + for(i = 0; i < dtnmach; i++){ + dtmachlock(i); + dtmachunlock(i); + } +} + +DTChan * +dtcnew(void) +{ + DTChan *c; + int i; + + c = dtmalloc(sizeof(DTChan)); + c->rdbufs = dtmalloc(sizeof(DTBuf *) * dtnmach); + c->wrbufs = dtmalloc(sizeof(DTBuf *) * dtnmach); + for(i = 0; i < dtnmach; i++){ + c->rdbufs[i] = dtmalloc(sizeof(DTBuf)); + c->wrbufs[i] = dtmalloc(sizeof(DTBuf)); + } + return c; +} + +void +dtcfree(DTChan *ch) +{ + int i; + + if(ch == nil) return; + + dtcrun(ch, DTCSTOP); + dtcreset(ch); + dtsync(); + for(i = 0; i < dtnmach; i++){ + free(ch->rdbufs[i]); + free(ch->wrbufs[i]); + } + free(ch->rdbufs); + free(ch->wrbufs); + free(ch); +} + +int +dtcaddgr(DTChan *c, DTName name, DTActGr *gr) +{ + DTProbe **l, *p; + DTEnab *ep; + int i, nl, n; + + if(dtgverify(gr) < 0) + return -1; + gr->chan = c; + + nl = dtpmatch(name, &l); + n = 0; + for(i = 0; i < nl; i++){ + p = l[i]; + if(p->nenable == 0) + if(p->prov->enable(p) < 0) + continue; + ep = dtmalloc(sizeof(DTEnab)); + ep->epid = c->epidalloc++; + ep->gr = gr; + ep->prob = p; + ep->probnext = &p->enablist; + ep->probprev = p->enablist.probprev; + ep->probnext->probprev = ep; + ep->channext = c->enab; + c->enab = ep; + gr->ref++; + n++; + p->nenable++; + /* careful, has to be atomic for dtptrigger */ + dtcoherence(); + ep->probprev->probnext = ep; + } + dtfree(l); + 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); + } + return rc; +} + +static void +dtcbufswap(DTChan *c, int n) +{ + DTBuf *z; + + dtmachlock(n); + z = c->rdbufs[n]; + c->rdbufs[n] = c->wrbufs[n]; + c->wrbufs[n] = z; + dtmachunlock(n); +} + +int +dtcread(DTChan *c, void *buf, int n) +{ + int i, swapped; + + if(c->state == DTCFAULT){ + werrstr("%s", c->errstr); + return -1; + } + for(i = 0; i < dtnmach; i++){ + if(swapped = c->rdbufs[i]->wr == 0) + dtcbufswap(c, i); + if(c->rdbufs[i]->wr != 0){ + if(c->rdbufs[i]->wr > n){ + werrstr("short read"); + return -1; + } + n = c->rdbufs[i]->wr; + memmove(buf, c->rdbufs[i]->data, n); + c->rdbufs[i]->wr = 0; + if(!swapped) + dtcbufswap(c, i); + return n; + } + } + return 0; +} + +void +dtcreset(DTChan *c) +{ + DTEnab *ep, *eq; + + for(ep = c->enab; ep != nil; ep = ep->channext){ + /* careful! has to look atomic for etptrigger */ + ep->probprev->probnext = ep->probnext; + ep->probnext->probprev = ep->probprev; + } + dtsync(); + for(ep = c->enab; ep != nil; eq = ep->channext, free(ep), ep = eq){ + if(--ep->gr->ref == 0) + dtgfree(ep->gr); + if(--ep->prob->nenable == 0) + ep->prob->prov->disable(ep->prob); + } + c->enab = nil; +} + +void +dtcrun(DTChan *c, int newstate) +{ + assert(newstate == DTCSTOP || newstate == DTCGO); + c->state = newstate; +} |