]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libdtracy/chan.c
dtracy: add support for aggregations
[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         c->aggrdbufs = dtmalloc(sizeof(DTBuf *) * dtnmach);
48         c->aggwrbufs = dtmalloc(sizeof(DTBuf *) * dtnmach);
49         for(i = 0; i < dtnmach; i++){
50                 c->aggrdbufs[i] = dtmalloc(sizeof(DTBuf));
51                 c->aggwrbufs[i] = dtmalloc(sizeof(DTBuf));
52                 memset(c->aggrdbufs[i]->data, -1, DTBUFSZ);
53                 memset(c->aggwrbufs[i]->data, -1, DTBUFSZ);
54         }
55         return c;
56 }
57
58 void
59 dtcfree(DTChan *ch)
60 {
61         int i;
62
63         if(ch == nil) return;
64
65         dtcrun(ch, DTCSTOP);
66         dtcreset(ch);
67         dtsync();
68         for(i = 0; i < dtnmach; i++){
69                 free(ch->rdbufs[i]);
70                 free(ch->wrbufs[i]);
71         }
72         free(ch->rdbufs);
73         free(ch->wrbufs);
74         for(i = 0; i < dtnmach; i++){
75                 free(ch->aggrdbufs[i]);
76                 free(ch->aggwrbufs[i]);
77         }
78         free(ch->aggrdbufs);
79         free(ch->aggwrbufs);
80         free(ch);
81 }
82
83 int
84 dtcaddgr(DTChan *c, DTName name, DTActGr *gr)
85 {
86         DTProbe **l, *p;
87         DTEnab *ep;
88         int i, nl, n;
89         
90         if(dtgverify(c, gr) < 0)
91                 return -1;
92         gr->chan = c;
93         
94         nl = dtpmatch(name, &l);
95         n = 0;
96         for(i = 0; i < nl; i++){
97                 p = l[i];
98                 if(p->nenable == 0)
99                         if(p->prov->enable(p) < 0)
100                                 continue;
101                 ep = dtmalloc(sizeof(DTEnab));
102                 ep->epid = c->epidalloc++;
103                 ep->gr = gr;
104                 ep->prob = p;
105                 ep->probnext = &p->enablist;
106                 ep->probprev = p->enablist.probprev;
107                 ep->probnext->probprev = ep;
108                 ep->channext = c->enab;
109                 c->enab = ep;
110                 gr->ref++;
111                 n++;
112                 p->nenable++;
113                 /* careful, has to be atomic for dtptrigger */
114                 dtcoherence();
115                 ep->probprev->probnext = ep;
116         }
117         dtfree(l);
118         return n;
119 }
120
121 static int
122 dtnamesplit(char *s, DTName *rp)
123 {
124         char *p;
125         
126         p = strchr(s, ':');
127         if(p == nil) return -1;
128         rp->provider = dtmalloc(p - s + 1);
129         memcpy(rp->provider, s, p - s);
130         s = p + 1;
131         p = strchr(s, ':');
132         if(p == nil){
133                 free(rp->provider);
134                 rp->provider = nil;
135                 return -1;
136         }
137         rp->function = dtmalloc(p - s + 1);
138         memcpy(rp->function, s, p - s);
139         s = p + 1;
140         if(strchr(s, ':') != nil){
141                 free(rp->provider);
142                 rp->provider = nil;
143                 free(rp->function);
144                 rp->function = nil;
145                 return -1;
146         }
147         rp->name = dtstrdup(s);
148         return 0;
149 }
150
151 int
152 dtcaddcl(DTChan *c, DTClause *cl)
153 {
154         DTName n;
155         int i, rc;
156
157         rc = 0;
158         for(i = 0; i < cl->nprob; i++){
159                 if(dtnamesplit(cl->probs[i], &n) < 0){
160                         werrstr("invalid probe name '%s'", cl->probs[i]);
161                         return -1;
162                 }
163                 rc += dtcaddgr(c, n, cl->gr);
164                 dtfree(n.provider);
165                 dtfree(n.function);
166                 dtfree(n.name);
167         }
168         return rc;
169 }
170
171 static void
172 dtcbufswap(DTChan *c, int n)
173 {
174         DTBuf *z;
175
176         dtmachlock(n);
177         z = c->rdbufs[n];
178         c->rdbufs[n] = c->wrbufs[n];
179         c->wrbufs[n] = z;
180         dtmachunlock(n);
181 }
182
183 int
184 dtcread(DTChan *c, void *buf, int n)
185 {
186         int i, swapped;
187         
188         if(c->state == DTCFAULT){
189                 werrstr("%s", c->errstr);
190                 return -1;
191         }
192         for(i = 0; i < dtnmach; i++){
193                 if(swapped = c->rdbufs[i]->wr == 0)
194                         dtcbufswap(c, i);
195                 if(c->rdbufs[i]->wr != 0){
196                         if(c->rdbufs[i]->wr > n){
197                                 werrstr("short read");
198                                 return -1;
199                         }
200                         n = c->rdbufs[i]->wr;
201                         memmove(buf, c->rdbufs[i]->data, n);
202                         c->rdbufs[i]->wr = 0;
203                         if(!swapped)
204                                 dtcbufswap(c, i);
205                         return n;
206                 }
207         }
208         return 0;
209 }
210
211 static void
212 dtcaggbufswap(DTChan *c, int n)
213 {
214         DTBuf *z;
215
216         dtmachlock(n);
217         z = c->aggrdbufs[n];
218         c->aggrdbufs[n] = c->aggwrbufs[n];
219         c->aggwrbufs[n] = z;
220         dtmachunlock(n);
221 }
222
223 int
224 dtcaggread(DTChan *c, void *buf, int n)
225 {
226         int i, swapped;
227         
228         if(c->state == DTCFAULT){
229                 werrstr("%s", c->errstr);
230                 return -1;
231         }
232         for(i = 0; i < dtnmach; i++){
233                 if(swapped = c->aggrdbufs[i]->wr == 0)
234                         dtcaggbufswap(c, i);
235                 if(c->aggrdbufs[i]->wr != 0){
236                         if(c->aggrdbufs[i]->wr > n){
237                                 werrstr("short read");
238                                 return -1;
239                         }
240                         n = c->aggrdbufs[i]->wr;
241                         memmove(buf, c->aggrdbufs[i]->data, n);
242                         c->aggrdbufs[i]->wr = 0;
243                         memset(c->aggrdbufs[i]->data + DTABUCKETS, -1, 4 * DTANUMBUCKETS);
244                         if(!swapped)
245                                 dtcaggbufswap(c, i);
246                         return n;
247                 }
248         }
249         return 0;
250 }
251
252 void
253 dtcreset(DTChan *c)
254 {
255         DTEnab *ep, *eq;
256         
257         for(ep = c->enab; ep != nil; ep = ep->channext){
258                 /* careful! has to look atomic for dtptrigger */
259                 ep->probprev->probnext = ep->probnext;
260                 ep->probnext->probprev = ep->probprev;
261         }
262         dtsync();
263         for(ep = c->enab; ep != nil; eq = ep->channext, free(ep), ep = eq){
264                 if(--ep->gr->ref == 0)
265                         dtgfree(ep->gr);
266                 if(--ep->prob->nenable == 0)
267                         ep->prob->prov->disable(ep->prob);
268         }
269         c->enab = nil;
270 }
271
272 void
273 dtcrun(DTChan *c, int newstate)
274 {
275         assert(newstate == DTCSTOP || newstate == DTCGO);
276         c->state = newstate;
277 }