plan9front/sys/src/libdtracy/chan.c

244 lines
4.2 KiB
C

#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));
}
c->aggrdbufs = dtmalloc(sizeof(DTBuf *) * dtnmach);
c->aggwrbufs = dtmalloc(sizeof(DTBuf *) * dtnmach);
for(i = 0; i < dtnmach; i++){
c->aggrdbufs[i] = dtmalloc(sizeof(DTBuf));
c->aggwrbufs[i] = dtmalloc(sizeof(DTBuf));
memset(c->aggrdbufs[i]->data, -1, DTBUFSZ);
memset(c->aggwrbufs[i]->data, -1, DTBUFSZ);
}
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);
for(i = 0; i < dtnmach; i++){
free(ch->aggrdbufs[i]);
free(ch->aggwrbufs[i]);
}
free(ch->aggrdbufs);
free(ch->aggwrbufs);
free(ch);
}
int
dtcaddgr(DTChan *c, char *name, DTActGr *gr)
{
DTProbe **l, *p;
DTEnab *ep;
int i, nl, n;
if(dtgverify(c, gr) < 0)
return -1;
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];
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;
}
int
dtcaddcl(DTChan *c, DTClause *cl)
{
int i, rc;
rc = 0;
for(i = 0; i < cl->nprob; i++)
rc += dtcaddgr(c, cl->probs[i], cl->gr);
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;
}
static void
dtcaggbufswap(DTChan *c, int n)
{
DTBuf *z;
dtmachlock(n);
z = c->aggrdbufs[n];
c->aggrdbufs[n] = c->aggwrbufs[n];
c->aggwrbufs[n] = z;
dtmachunlock(n);
}
int
dtcaggread(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->aggrdbufs[i]->wr == 0)
dtcaggbufswap(c, i);
if(c->aggrdbufs[i]->wr != 0){
if(c->aggrdbufs[i]->wr > n){
werrstr("short read");
return -1;
}
n = c->aggrdbufs[i]->wr;
memmove(buf, c->aggrdbufs[i]->data, n);
c->aggrdbufs[i]->wr = 0;
memset(c->aggrdbufs[i]->data + DTABUCKETS, -1, 4 * DTANUMBUCKETS);
if(!swapped)
dtcaggbufswap(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 dtptrigger */
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;
}