]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libdtracy/chan.c
upas/*: cleanup mkfiles (thanks amavect)
[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, char *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         if(nl == 0){
96                 dtfree(l);
97                 werrstr("no match for %s", name);
98                 return -1;
99         }
100         n = 0;
101         for(i = 0; i < nl; i++){
102                 p = l[i];
103                 if(p->nenable == 0)
104                         if(p->prov->enable(p) < 0)
105                                 continue;
106                 ep = dtmalloc(sizeof(DTEnab));
107                 ep->epid = c->epidalloc++;
108                 ep->gr = gr;
109                 ep->prob = p;
110                 ep->probnext = &p->enablist;
111                 ep->probprev = p->enablist.probprev;
112                 ep->probnext->probprev = ep;
113                 ep->channext = c->enab;
114                 c->enab = ep;
115                 gr->ref++;
116                 n++;
117                 p->nenable++;
118                 /* careful, has to be atomic for dtptrigger */
119                 dtcoherence();
120                 ep->probprev->probnext = ep;
121         }
122         dtfree(l);
123         return n;
124 }
125
126 int
127 dtcaddcl(DTChan *c, DTClause *cl)
128 {
129         int i, rc;
130
131         rc = 0;
132         for(i = 0; i < cl->nprob; i++)
133                 rc += dtcaddgr(c, cl->probs[i], cl->gr);
134         return rc;
135 }
136
137 static void
138 dtcbufswap(DTChan *c, int n)
139 {
140         DTBuf *z;
141
142         dtmachlock(n);
143         z = c->rdbufs[n];
144         c->rdbufs[n] = c->wrbufs[n];
145         c->wrbufs[n] = z;
146         dtmachunlock(n);
147 }
148
149 int
150 dtcread(DTChan *c, void *buf, int n)
151 {
152         int i, swapped;
153         
154         if(c->state == DTCFAULT){
155                 werrstr("%s", c->errstr);
156                 return -1;
157         }
158         for(i = 0; i < dtnmach; i++){
159                 if(swapped = c->rdbufs[i]->wr == 0)
160                         dtcbufswap(c, i);
161                 if(c->rdbufs[i]->wr != 0){
162                         if(c->rdbufs[i]->wr > n){
163                                 werrstr("short read");
164                                 return -1;
165                         }
166                         n = c->rdbufs[i]->wr;
167                         memmove(buf, c->rdbufs[i]->data, n);
168                         c->rdbufs[i]->wr = 0;
169                         if(!swapped)
170                                 dtcbufswap(c, i);
171                         return n;
172                 }
173         }
174         return 0;
175 }
176
177 static void
178 dtcaggbufswap(DTChan *c, int n)
179 {
180         DTBuf *z;
181
182         dtmachlock(n);
183         z = c->aggrdbufs[n];
184         c->aggrdbufs[n] = c->aggwrbufs[n];
185         c->aggwrbufs[n] = z;
186         dtmachunlock(n);
187 }
188
189 int
190 dtcaggread(DTChan *c, void *buf, int n)
191 {
192         int i, swapped;
193         
194         if(c->state == DTCFAULT){
195                 werrstr("%s", c->errstr);
196                 return -1;
197         }
198         for(i = 0; i < dtnmach; i++){
199                 if(swapped = c->aggrdbufs[i]->wr == 0)
200                         dtcaggbufswap(c, i);
201                 if(c->aggrdbufs[i]->wr != 0){
202                         if(c->aggrdbufs[i]->wr > n){
203                                 werrstr("short read");
204                                 return -1;
205                         }
206                         n = c->aggrdbufs[i]->wr;
207                         memmove(buf, c->aggrdbufs[i]->data, n);
208                         c->aggrdbufs[i]->wr = 0;
209                         memset(c->aggrdbufs[i]->data + DTABUCKETS, -1, 4 * DTANUMBUCKETS);
210                         if(!swapped)
211                                 dtcaggbufswap(c, i);
212                         return n;
213                 }
214         }
215         return 0;
216 }
217
218 void
219 dtcreset(DTChan *c)
220 {
221         DTEnab *ep, *eq;
222         
223         for(ep = c->enab; ep != nil; ep = ep->channext){
224                 /* careful! has to look atomic for dtptrigger */
225                 ep->probprev->probnext = ep->probnext;
226                 ep->probnext->probprev = ep->probprev;
227         }
228         dtsync();
229         for(ep = c->enab; ep != nil; eq = ep->channext, free(ep), ep = eq){
230                 if(--ep->gr->ref == 0)
231                         dtgfree(ep->gr);
232                 if(--ep->prob->nenable == 0)
233                         ep->prob->prov->disable(ep->prob);
234         }
235         c->enab = nil;
236 }
237
238 void
239 dtcrun(DTChan *c, int newstate)
240 {
241         assert(newstate == DTCSTOP || newstate == DTCGO);
242         c->state = newstate;
243 }