]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libdtracy/chan.c
merge
[plan9front.git] / sys / src / libdtracy / chan.c
1 #include <u.h>
2 #include <libc.h>
3 #include <dtracy.h>
4
5 int dtnmach;
6
7 void
8 dtinit(int nmach)
9 {
10         DTProvider **p;
11
12         dtnmach = nmach;
13         
14         /* sanity */
15         for(p = dtproviders; *p != nil; p++){
16                 assert((*p)->name != nil);
17                 assert((*p)->provide != nil);
18                 assert((*p)->enable != nil);
19                 assert((*p)->disable != nil);
20         }
21 }
22
23 void
24 dtsync(void)
25 {
26         int i;
27         
28         for(i = 0; i < dtnmach; i++){
29                 dtmachlock(i);
30                 dtmachunlock(i);
31         }
32 }
33
34 DTChan *
35 dtcnew(void)
36 {
37         DTChan *c;
38         int i;
39         
40         c = dtmalloc(sizeof(DTChan));
41         c->rdbufs = dtmalloc(sizeof(DTBuf *) * dtnmach);
42         c->wrbufs = dtmalloc(sizeof(DTBuf *) * dtnmach);
43         for(i = 0; i < dtnmach; i++){
44                 c->rdbufs[i] = dtmalloc(sizeof(DTBuf));
45                 c->wrbufs[i] = dtmalloc(sizeof(DTBuf));
46         }
47         return c;
48 }
49
50 void
51 dtcfree(DTChan *ch)
52 {
53         int i;
54
55         if(ch == nil) return;
56
57         dtcrun(ch, DTCSTOP);
58         dtcreset(ch);
59         dtsync();
60         for(i = 0; i < dtnmach; i++){
61                 free(ch->rdbufs[i]);
62                 free(ch->wrbufs[i]);
63         }
64         free(ch->rdbufs);
65         free(ch->wrbufs);
66         free(ch);
67 }
68
69 int
70 dtcaddgr(DTChan *c, DTName name, DTActGr *gr)
71 {
72         DTProbe **l, *p;
73         DTEnab *ep;
74         int i, nl, n;
75         
76         if(dtgverify(gr) < 0)
77                 return -1;
78         gr->chan = c;
79         
80         nl = dtpmatch(name, &l);
81         n = 0;
82         for(i = 0; i < nl; i++){
83                 p = l[i];
84                 if(p->nenable == 0)
85                         if(p->prov->enable(p) < 0)
86                                 continue;
87                 ep = dtmalloc(sizeof(DTEnab));
88                 ep->epid = c->epidalloc++;
89                 ep->gr = gr;
90                 ep->prob = p;
91                 ep->probnext = &p->enablist;
92                 ep->probprev = p->enablist.probprev;
93                 ep->probnext->probprev = ep;
94                 ep->channext = c->enab;
95                 c->enab = ep;
96                 gr->ref++;
97                 n++;
98                 p->nenable++;
99                 /* careful, has to be atomic for dtptrigger */
100                 dtcoherence();
101                 ep->probprev->probnext = ep;
102         }
103         dtfree(l);
104         return n;
105 }
106
107 static int
108 dtnamesplit(char *s, DTName *rp)
109 {
110         char *p;
111         
112         p = strchr(s, ':');
113         if(p == nil) return -1;
114         rp->provider = dtmalloc(p - s + 1);
115         memcpy(rp->provider, s, p - s);
116         s = p + 1;
117         p = strchr(s, ':');
118         if(p == nil){
119                 free(rp->provider);
120                 rp->provider = nil;
121                 return -1;
122         }
123         rp->function = dtmalloc(p - s + 1);
124         memcpy(rp->function, s, p - s);
125         s = p + 1;
126         if(strchr(s, ':') != nil){
127                 free(rp->provider);
128                 rp->provider = nil;
129                 free(rp->function);
130                 rp->function = nil;
131                 return -1;
132         }
133         rp->name = dtstrdup(s);
134         return 0;
135 }
136
137 int
138 dtcaddcl(DTChan *c, DTClause *cl)
139 {
140         DTName n;
141         int i, rc;
142
143         rc = 0;
144         for(i = 0; i < cl->nprob; i++){
145                 if(dtnamesplit(cl->probs[i], &n) < 0){
146                         werrstr("invalid probe name '%s'", cl->probs[i]);
147                         return -1;
148                 }
149                 rc += dtcaddgr(c, n, cl->gr);
150                 dtfree(n.provider);
151                 dtfree(n.function);
152                 dtfree(n.name);
153         }
154         return rc;
155 }
156
157 static void
158 dtcbufswap(DTChan *c, int n)
159 {
160         DTBuf *z;
161
162         dtmachlock(n);
163         z = c->rdbufs[n];
164         c->rdbufs[n] = c->wrbufs[n];
165         c->wrbufs[n] = z;
166         dtmachunlock(n);
167 }
168
169 int
170 dtcread(DTChan *c, void *buf, int n)
171 {
172         int i, swapped;
173         
174         if(c->state == DTCFAULT){
175                 werrstr("%s", c->errstr);
176                 return -1;
177         }
178         for(i = 0; i < dtnmach; i++){
179                 if(swapped = c->rdbufs[i]->wr == 0)
180                         dtcbufswap(c, i);
181                 if(c->rdbufs[i]->wr != 0){
182                         if(c->rdbufs[i]->wr > n){
183                                 werrstr("short read");
184                                 return -1;
185                         }
186                         n = c->rdbufs[i]->wr;
187                         memmove(buf, c->rdbufs[i]->data, n);
188                         c->rdbufs[i]->wr = 0;
189                         if(!swapped)
190                                 dtcbufswap(c, i);
191                         return n;
192                 }
193         }
194         return 0;
195 }
196
197 void
198 dtcreset(DTChan *c)
199 {
200         DTEnab *ep, *eq;
201         
202         for(ep = c->enab; ep != nil; ep = ep->channext){
203                 /* careful! has to look atomic for etptrigger */
204                 ep->probprev->probnext = ep->probnext;
205                 ep->probnext->probprev = ep->probprev;
206         }
207         dtsync();
208         for(ep = c->enab; ep != nil; eq = ep->channext, free(ep), ep = eq){
209                 if(--ep->gr->ref == 0)
210                         dtgfree(ep->gr);
211                 if(--ep->prob->nenable == 0)
212                         ep->prob->prov->disable(ep->prob);
213         }
214         c->enab = nil;
215 }
216
217 void
218 dtcrun(DTChan *c, int newstate)
219 {
220         assert(newstate == DTCSTOP || newstate == DTCGO);
221         c->state = newstate;
222 }