Blame


1 619085f0 2004-12-25 devnull #include "threadimpl.h"
2 619085f0 2004-12-25 devnull
3 619085f0 2004-12-25 devnull /*
4 619085f0 2004-12-25 devnull * One can go through a lot of effort to avoid this global lock.
5 619085f0 2004-12-25 devnull * You have to put locks in all the channels and all the Alt
6 619085f0 2004-12-25 devnull * structures. At the beginning of an alt you have to lock all
7 619085f0 2004-12-25 devnull * the channels, but then to try to actually exec an op you
8 fa325e9b 2020-01-10 cross * have to lock the other guy's alt structure, so that other
9 619085f0 2004-12-25 devnull * people aren't trying to use him in some other op at the
10 619085f0 2004-12-25 devnull * same time.
11 fa325e9b 2020-01-10 cross *
12 619085f0 2004-12-25 devnull * For Plan 9 apps, it's just not worth the extra effort.
13 619085f0 2004-12-25 devnull */
14 619085f0 2004-12-25 devnull static QLock chanlock;
15 619085f0 2004-12-25 devnull
16 619085f0 2004-12-25 devnull Channel*
17 619085f0 2004-12-25 devnull chancreate(int elemsize, int bufsize)
18 619085f0 2004-12-25 devnull {
19 619085f0 2004-12-25 devnull Channel *c;
20 619085f0 2004-12-25 devnull
21 619085f0 2004-12-25 devnull c = malloc(sizeof *c+bufsize*elemsize);
22 73722a8b 2004-12-27 devnull if(c == nil)
23 73722a8b 2004-12-27 devnull sysfatal("chancreate malloc: %r");
24 619085f0 2004-12-25 devnull memset(c, 0, sizeof *c);
25 619085f0 2004-12-25 devnull c->elemsize = elemsize;
26 619085f0 2004-12-25 devnull c->bufsize = bufsize;
27 619085f0 2004-12-25 devnull c->nbuf = 0;
28 619085f0 2004-12-25 devnull c->buf = (uchar*)(c+1);
29 619085f0 2004-12-25 devnull return c;
30 619085f0 2004-12-25 devnull }
31 619085f0 2004-12-25 devnull
32 619085f0 2004-12-25 devnull void
33 619085f0 2004-12-25 devnull chansetname(Channel *c, char *fmt, ...)
34 619085f0 2004-12-25 devnull {
35 619085f0 2004-12-25 devnull char *name;
36 619085f0 2004-12-25 devnull va_list arg;
37 619085f0 2004-12-25 devnull
38 619085f0 2004-12-25 devnull va_start(arg, fmt);
39 619085f0 2004-12-25 devnull name = vsmprint(fmt, arg);
40 619085f0 2004-12-25 devnull va_end(arg);
41 619085f0 2004-12-25 devnull free(c->name);
42 619085f0 2004-12-25 devnull c->name = name;
43 619085f0 2004-12-25 devnull }
44 619085f0 2004-12-25 devnull
45 619085f0 2004-12-25 devnull /* bug - work out races */
46 619085f0 2004-12-25 devnull void
47 619085f0 2004-12-25 devnull chanfree(Channel *c)
48 619085f0 2004-12-25 devnull {
49 619085f0 2004-12-25 devnull if(c == nil)
50 619085f0 2004-12-25 devnull return;
51 619085f0 2004-12-25 devnull free(c->name);
52 619085f0 2004-12-25 devnull free(c->arecv.a);
53 619085f0 2004-12-25 devnull free(c->asend.a);
54 619085f0 2004-12-25 devnull free(c);
55 619085f0 2004-12-25 devnull }
56 619085f0 2004-12-25 devnull
57 619085f0 2004-12-25 devnull static void
58 619085f0 2004-12-25 devnull addarray(_Altarray *a, Alt *alt)
59 619085f0 2004-12-25 devnull {
60 619085f0 2004-12-25 devnull if(a->n == a->m){
61 619085f0 2004-12-25 devnull a->m += 16;
62 619085f0 2004-12-25 devnull a->a = realloc(a->a, a->m*sizeof a->a[0]);
63 619085f0 2004-12-25 devnull }
64 619085f0 2004-12-25 devnull a->a[a->n++] = alt;
65 619085f0 2004-12-25 devnull }
66 619085f0 2004-12-25 devnull
67 619085f0 2004-12-25 devnull static void
68 619085f0 2004-12-25 devnull delarray(_Altarray *a, int i)
69 619085f0 2004-12-25 devnull {
70 619085f0 2004-12-25 devnull --a->n;
71 619085f0 2004-12-25 devnull a->a[i] = a->a[a->n];
72 619085f0 2004-12-25 devnull }
73 619085f0 2004-12-25 devnull
74 619085f0 2004-12-25 devnull /*
75 619085f0 2004-12-25 devnull * doesn't really work for things other than CHANSND and CHANRCV
76 619085f0 2004-12-25 devnull * but is only used as arg to chanarray, which can handle it
77 619085f0 2004-12-25 devnull */
78 619085f0 2004-12-25 devnull #define otherop(op) (CHANSND+CHANRCV-(op))
79 619085f0 2004-12-25 devnull
80 619085f0 2004-12-25 devnull static _Altarray*
81 619085f0 2004-12-25 devnull chanarray(Channel *c, uint op)
82 619085f0 2004-12-25 devnull {
83 619085f0 2004-12-25 devnull switch(op){
84 619085f0 2004-12-25 devnull default:
85 619085f0 2004-12-25 devnull return nil;
86 619085f0 2004-12-25 devnull case CHANSND:
87 619085f0 2004-12-25 devnull return &c->asend;
88 619085f0 2004-12-25 devnull case CHANRCV:
89 619085f0 2004-12-25 devnull return &c->arecv;
90 619085f0 2004-12-25 devnull }
91 619085f0 2004-12-25 devnull }
92 619085f0 2004-12-25 devnull
93 619085f0 2004-12-25 devnull static int
94 619085f0 2004-12-25 devnull altcanexec(Alt *a)
95 619085f0 2004-12-25 devnull {
96 619085f0 2004-12-25 devnull _Altarray *ar;
97 619085f0 2004-12-25 devnull Channel *c;
98 619085f0 2004-12-25 devnull
99 80f2165d 2008-05-06 rsc if(a->op == CHANNOP || (c=a->c) == nil)
100 619085f0 2004-12-25 devnull return 0;
101 619085f0 2004-12-25 devnull if(c->bufsize == 0){
102 619085f0 2004-12-25 devnull ar = chanarray(c, otherop(a->op));
103 619085f0 2004-12-25 devnull return ar && ar->n;
104 619085f0 2004-12-25 devnull }else{
105 619085f0 2004-12-25 devnull switch(a->op){
106 619085f0 2004-12-25 devnull default:
107 619085f0 2004-12-25 devnull return 0;
108 619085f0 2004-12-25 devnull case CHANSND:
109 619085f0 2004-12-25 devnull return c->nbuf < c->bufsize;
110 619085f0 2004-12-25 devnull case CHANRCV:
111 619085f0 2004-12-25 devnull return c->nbuf > 0;
112 619085f0 2004-12-25 devnull }
113 619085f0 2004-12-25 devnull }
114 619085f0 2004-12-25 devnull }
115 619085f0 2004-12-25 devnull
116 619085f0 2004-12-25 devnull static void
117 619085f0 2004-12-25 devnull altqueue(Alt *a)
118 619085f0 2004-12-25 devnull {
119 619085f0 2004-12-25 devnull _Altarray *ar;
120 619085f0 2004-12-25 devnull
121 80f2165d 2008-05-06 rsc if(a->c == nil)
122 80f2165d 2008-05-06 rsc return;
123 619085f0 2004-12-25 devnull ar = chanarray(a->c, a->op);
124 619085f0 2004-12-25 devnull addarray(ar, a);
125 619085f0 2004-12-25 devnull }
126 619085f0 2004-12-25 devnull
127 619085f0 2004-12-25 devnull static void
128 619085f0 2004-12-25 devnull altdequeue(Alt *a)
129 619085f0 2004-12-25 devnull {
130 619085f0 2004-12-25 devnull int i;
131 619085f0 2004-12-25 devnull _Altarray *ar;
132 619085f0 2004-12-25 devnull
133 619085f0 2004-12-25 devnull ar = chanarray(a->c, a->op);
134 619085f0 2004-12-25 devnull if(ar == nil){
135 619085f0 2004-12-25 devnull fprint(2, "bad use of altdequeue op=%d\n", a->op);
136 619085f0 2004-12-25 devnull abort();
137 619085f0 2004-12-25 devnull }
138 619085f0 2004-12-25 devnull
139 619085f0 2004-12-25 devnull for(i=0; i<ar->n; i++)
140 619085f0 2004-12-25 devnull if(ar->a[i] == a){
141 619085f0 2004-12-25 devnull delarray(ar, i);
142 619085f0 2004-12-25 devnull return;
143 619085f0 2004-12-25 devnull }
144 baef953d 2020-05-18 rsc fprint(2, "cannot find self in altdequeue\n");
145 619085f0 2004-12-25 devnull abort();
146 619085f0 2004-12-25 devnull }
147 619085f0 2004-12-25 devnull
148 619085f0 2004-12-25 devnull static void
149 619085f0 2004-12-25 devnull altalldequeue(Alt *a)
150 619085f0 2004-12-25 devnull {
151 619085f0 2004-12-25 devnull int i;
152 619085f0 2004-12-25 devnull
153 619085f0 2004-12-25 devnull for(i=0; a[i].op!=CHANEND && a[i].op!=CHANNOBLK; i++)
154 619085f0 2004-12-25 devnull if(a[i].op != CHANNOP)
155 619085f0 2004-12-25 devnull altdequeue(&a[i]);
156 619085f0 2004-12-25 devnull }
157 619085f0 2004-12-25 devnull
158 619085f0 2004-12-25 devnull static void
159 619085f0 2004-12-25 devnull amove(void *dst, void *src, uint n)
160 619085f0 2004-12-25 devnull {
161 619085f0 2004-12-25 devnull if(dst){
162 619085f0 2004-12-25 devnull if(src == nil)
163 619085f0 2004-12-25 devnull memset(dst, 0, n);
164 619085f0 2004-12-25 devnull else
165 619085f0 2004-12-25 devnull memmove(dst, src, n);
166 619085f0 2004-12-25 devnull }
167 619085f0 2004-12-25 devnull }
168 619085f0 2004-12-25 devnull
169 619085f0 2004-12-25 devnull /*
170 619085f0 2004-12-25 devnull * Actually move the data around. There are up to three
171 619085f0 2004-12-25 devnull * players: the sender, the receiver, and the channel itself.
172 619085f0 2004-12-25 devnull * If the channel is unbuffered or the buffer is empty,
173 619085f0 2004-12-25 devnull * data goes from sender to receiver. If the channel is full,
174 619085f0 2004-12-25 devnull * the receiver removes some from the channel and the sender
175 619085f0 2004-12-25 devnull * gets to put some in.
176 619085f0 2004-12-25 devnull */
177 619085f0 2004-12-25 devnull static void
178 619085f0 2004-12-25 devnull altcopy(Alt *s, Alt *r)
179 619085f0 2004-12-25 devnull {
180 619085f0 2004-12-25 devnull Alt *t;
181 619085f0 2004-12-25 devnull Channel *c;
182 619085f0 2004-12-25 devnull uchar *cp;
183 619085f0 2004-12-25 devnull
184 619085f0 2004-12-25 devnull /*
185 619085f0 2004-12-25 devnull * Work out who is sender and who is receiver
186 619085f0 2004-12-25 devnull */
187 619085f0 2004-12-25 devnull if(s == nil && r == nil)
188 619085f0 2004-12-25 devnull return;
189 619085f0 2004-12-25 devnull assert(s != nil);
190 619085f0 2004-12-25 devnull c = s->c;
191 619085f0 2004-12-25 devnull if(s->op == CHANRCV){
192 619085f0 2004-12-25 devnull t = s;
193 619085f0 2004-12-25 devnull s = r;
194 619085f0 2004-12-25 devnull r = t;
195 619085f0 2004-12-25 devnull }
196 619085f0 2004-12-25 devnull assert(s==nil || s->op == CHANSND);
197 619085f0 2004-12-25 devnull assert(r==nil || r->op == CHANRCV);
198 619085f0 2004-12-25 devnull
199 619085f0 2004-12-25 devnull /*
200 619085f0 2004-12-25 devnull * Channel is empty (or unbuffered) - copy directly.
201 619085f0 2004-12-25 devnull */
202 619085f0 2004-12-25 devnull if(s && r && c->nbuf == 0){
203 619085f0 2004-12-25 devnull amove(r->v, s->v, c->elemsize);
204 619085f0 2004-12-25 devnull return;
205 619085f0 2004-12-25 devnull }
206 619085f0 2004-12-25 devnull
207 619085f0 2004-12-25 devnull /*
208 619085f0 2004-12-25 devnull * Otherwise it's always okay to receive and then send.
209 619085f0 2004-12-25 devnull */
210 619085f0 2004-12-25 devnull if(r){
211 619085f0 2004-12-25 devnull cp = c->buf + c->off*c->elemsize;
212 619085f0 2004-12-25 devnull amove(r->v, cp, c->elemsize);
213 619085f0 2004-12-25 devnull --c->nbuf;
214 619085f0 2004-12-25 devnull if(++c->off == c->bufsize)
215 619085f0 2004-12-25 devnull c->off = 0;
216 619085f0 2004-12-25 devnull }
217 619085f0 2004-12-25 devnull if(s){
218 619085f0 2004-12-25 devnull cp = c->buf + (c->off+c->nbuf)%c->bufsize*c->elemsize;
219 619085f0 2004-12-25 devnull amove(cp, s->v, c->elemsize);
220 619085f0 2004-12-25 devnull ++c->nbuf;
221 619085f0 2004-12-25 devnull }
222 619085f0 2004-12-25 devnull }
223 619085f0 2004-12-25 devnull
224 619085f0 2004-12-25 devnull static void
225 619085f0 2004-12-25 devnull altexec(Alt *a)
226 619085f0 2004-12-25 devnull {
227 619085f0 2004-12-25 devnull int i;
228 619085f0 2004-12-25 devnull _Altarray *ar;
229 619085f0 2004-12-25 devnull Alt *other;
230 619085f0 2004-12-25 devnull Channel *c;
231 619085f0 2004-12-25 devnull
232 619085f0 2004-12-25 devnull c = a->c;
233 619085f0 2004-12-25 devnull ar = chanarray(c, otherop(a->op));
234 619085f0 2004-12-25 devnull if(ar && ar->n){
235 619085f0 2004-12-25 devnull i = rand()%ar->n;
236 619085f0 2004-12-25 devnull other = ar->a[i];
237 619085f0 2004-12-25 devnull altcopy(a, other);
238 47ede89e 2007-08-22 rsc altalldequeue(other->thread->alt);
239 47ede89e 2007-08-22 rsc other->thread->alt = other;
240 619085f0 2004-12-25 devnull _threadready(other->thread);
241 619085f0 2004-12-25 devnull }else
242 619085f0 2004-12-25 devnull altcopy(a, nil);
243 619085f0 2004-12-25 devnull }
244 619085f0 2004-12-25 devnull
245 619085f0 2004-12-25 devnull #define dbgalt 0
246 619085f0 2004-12-25 devnull int
247 619085f0 2004-12-25 devnull chanalt(Alt *a)
248 619085f0 2004-12-25 devnull {
249 619085f0 2004-12-25 devnull int i, j, ncan, n, canblock;
250 619085f0 2004-12-25 devnull Channel *c;
251 619085f0 2004-12-25 devnull _Thread *t;
252 619085f0 2004-12-25 devnull
253 c8b6342d 2005-01-13 devnull needstack(512);
254 619085f0 2004-12-25 devnull for(i=0; a[i].op != CHANEND && a[i].op != CHANNOBLK; i++)
255 619085f0 2004-12-25 devnull ;
256 619085f0 2004-12-25 devnull n = i;
257 619085f0 2004-12-25 devnull canblock = a[i].op == CHANEND;
258 619085f0 2004-12-25 devnull
259 619085f0 2004-12-25 devnull t = proc()->thread;
260 47ede89e 2007-08-22 rsc for(i=0; i<n; i++)
261 619085f0 2004-12-25 devnull a[i].thread = t;
262 47ede89e 2007-08-22 rsc t->alt = a;
263 619085f0 2004-12-25 devnull qlock(&chanlock);
264 619085f0 2004-12-25 devnull if(dbgalt) print("alt ");
265 619085f0 2004-12-25 devnull ncan = 0;
266 619085f0 2004-12-25 devnull for(i=0; i<n; i++){
267 619085f0 2004-12-25 devnull c = a[i].c;
268 619085f0 2004-12-25 devnull if(dbgalt) print(" %c:", "esrnb"[a[i].op]);
269 619085f0 2004-12-25 devnull if(dbgalt) if(c->name) print("%s", c->name); else print("%p", c);
270 619085f0 2004-12-25 devnull if(altcanexec(&a[i])){
271 619085f0 2004-12-25 devnull if(dbgalt) print("*");
272 619085f0 2004-12-25 devnull ncan++;
273 619085f0 2004-12-25 devnull }
274 619085f0 2004-12-25 devnull }
275 619085f0 2004-12-25 devnull if(ncan){
276 619085f0 2004-12-25 devnull j = rand()%ncan;
277 619085f0 2004-12-25 devnull for(i=0; i<n; i++){
278 619085f0 2004-12-25 devnull if(altcanexec(&a[i])){
279 619085f0 2004-12-25 devnull if(j-- == 0){
280 619085f0 2004-12-25 devnull if(dbgalt){
281 619085f0 2004-12-25 devnull c = a[i].c;
282 619085f0 2004-12-25 devnull print(" => %c:", "esrnb"[a[i].op]);
283 619085f0 2004-12-25 devnull if(c->name) print("%s", c->name); else print("%p", c);
284 619085f0 2004-12-25 devnull print("\n");
285 619085f0 2004-12-25 devnull }
286 619085f0 2004-12-25 devnull altexec(&a[i]);
287 619085f0 2004-12-25 devnull qunlock(&chanlock);
288 619085f0 2004-12-25 devnull return i;
289 619085f0 2004-12-25 devnull }
290 619085f0 2004-12-25 devnull }
291 619085f0 2004-12-25 devnull }
292 619085f0 2004-12-25 devnull }
293 619085f0 2004-12-25 devnull if(dbgalt)print("\n");
294 619085f0 2004-12-25 devnull
295 619085f0 2004-12-25 devnull if(!canblock){
296 619085f0 2004-12-25 devnull qunlock(&chanlock);
297 619085f0 2004-12-25 devnull return -1;
298 619085f0 2004-12-25 devnull }
299 619085f0 2004-12-25 devnull
300 619085f0 2004-12-25 devnull for(i=0; i<n; i++){
301 619085f0 2004-12-25 devnull if(a[i].op != CHANNOP)
302 619085f0 2004-12-25 devnull altqueue(&a[i]);
303 619085f0 2004-12-25 devnull }
304 619085f0 2004-12-25 devnull qunlock(&chanlock);
305 619085f0 2004-12-25 devnull
306 619085f0 2004-12-25 devnull _threadswitch();
307 619085f0 2004-12-25 devnull
308 619085f0 2004-12-25 devnull /*
309 619085f0 2004-12-25 devnull * the guy who ran the op took care of dequeueing us
310 47ede89e 2007-08-22 rsc * and then set t->alt to the one that was executed.
311 619085f0 2004-12-25 devnull */
312 47ede89e 2007-08-22 rsc if(t->alt < a || t->alt >= a+n)
313 47ede89e 2007-08-22 rsc sysfatal("channel bad alt");
314 47ede89e 2007-08-22 rsc return t->alt - a;
315 619085f0 2004-12-25 devnull }
316 619085f0 2004-12-25 devnull
317 619085f0 2004-12-25 devnull static int
318 619085f0 2004-12-25 devnull _chanop(Channel *c, int op, void *p, int canblock)
319 619085f0 2004-12-25 devnull {
320 619085f0 2004-12-25 devnull Alt a[2];
321 619085f0 2004-12-25 devnull
322 619085f0 2004-12-25 devnull a[0].c = c;
323 619085f0 2004-12-25 devnull a[0].op = op;
324 619085f0 2004-12-25 devnull a[0].v = p;
325 619085f0 2004-12-25 devnull a[1].op = canblock ? CHANEND : CHANNOBLK;
326 619085f0 2004-12-25 devnull if(chanalt(a) < 0)
327 619085f0 2004-12-25 devnull return -1;
328 619085f0 2004-12-25 devnull return 1;
329 619085f0 2004-12-25 devnull }
330 619085f0 2004-12-25 devnull
331 619085f0 2004-12-25 devnull int
332 619085f0 2004-12-25 devnull chansend(Channel *c, void *v)
333 619085f0 2004-12-25 devnull {
334 619085f0 2004-12-25 devnull return _chanop(c, CHANSND, v, 1);
335 619085f0 2004-12-25 devnull }
336 619085f0 2004-12-25 devnull
337 619085f0 2004-12-25 devnull int
338 619085f0 2004-12-25 devnull channbsend(Channel *c, void *v)
339 619085f0 2004-12-25 devnull {
340 619085f0 2004-12-25 devnull return _chanop(c, CHANSND, v, 0);
341 619085f0 2004-12-25 devnull }
342 619085f0 2004-12-25 devnull
343 619085f0 2004-12-25 devnull int
344 619085f0 2004-12-25 devnull chanrecv(Channel *c, void *v)
345 619085f0 2004-12-25 devnull {
346 619085f0 2004-12-25 devnull return _chanop(c, CHANRCV, v, 1);
347 619085f0 2004-12-25 devnull }
348 619085f0 2004-12-25 devnull
349 619085f0 2004-12-25 devnull int
350 619085f0 2004-12-25 devnull channbrecv(Channel *c, void *v)
351 619085f0 2004-12-25 devnull {
352 619085f0 2004-12-25 devnull return _chanop(c, CHANRCV, v, 0);
353 619085f0 2004-12-25 devnull }
354 619085f0 2004-12-25 devnull
355 619085f0 2004-12-25 devnull int
356 619085f0 2004-12-25 devnull chansendp(Channel *c, void *v)
357 619085f0 2004-12-25 devnull {
358 619085f0 2004-12-25 devnull return _chanop(c, CHANSND, (void*)&v, 1);
359 619085f0 2004-12-25 devnull }
360 619085f0 2004-12-25 devnull
361 619085f0 2004-12-25 devnull void*
362 619085f0 2004-12-25 devnull chanrecvp(Channel *c)
363 619085f0 2004-12-25 devnull {
364 619085f0 2004-12-25 devnull void *v;
365 619085f0 2004-12-25 devnull
366 0215811d 2008-05-06 rsc if(_chanop(c, CHANRCV, (void*)&v, 1) > 0)
367 0215811d 2008-05-06 rsc return v;
368 0215811d 2008-05-06 rsc return nil;
369 619085f0 2004-12-25 devnull }
370 619085f0 2004-12-25 devnull
371 619085f0 2004-12-25 devnull int
372 619085f0 2004-12-25 devnull channbsendp(Channel *c, void *v)
373 619085f0 2004-12-25 devnull {
374 619085f0 2004-12-25 devnull return _chanop(c, CHANSND, (void*)&v, 0);
375 619085f0 2004-12-25 devnull }
376 619085f0 2004-12-25 devnull
377 619085f0 2004-12-25 devnull void*
378 619085f0 2004-12-25 devnull channbrecvp(Channel *c)
379 619085f0 2004-12-25 devnull {
380 619085f0 2004-12-25 devnull void *v;
381 619085f0 2004-12-25 devnull
382 0215811d 2008-05-06 rsc if(_chanop(c, CHANRCV, (void*)&v, 0) > 0)
383 0215811d 2008-05-06 rsc return v;
384 0215811d 2008-05-06 rsc return nil;
385 619085f0 2004-12-25 devnull }
386 619085f0 2004-12-25 devnull
387 619085f0 2004-12-25 devnull int
388 619085f0 2004-12-25 devnull chansendul(Channel *c, ulong val)
389 619085f0 2004-12-25 devnull {
390 619085f0 2004-12-25 devnull return _chanop(c, CHANSND, &val, 1);
391 619085f0 2004-12-25 devnull }
392 619085f0 2004-12-25 devnull
393 619085f0 2004-12-25 devnull ulong
394 619085f0 2004-12-25 devnull chanrecvul(Channel *c)
395 619085f0 2004-12-25 devnull {
396 619085f0 2004-12-25 devnull ulong val;
397 619085f0 2004-12-25 devnull
398 0215811d 2008-05-06 rsc if(_chanop(c, CHANRCV, &val, 1) > 0)
399 0215811d 2008-05-06 rsc return val;
400 369923f6 2020-01-13 rsc return 0;
401 619085f0 2004-12-25 devnull }
402 619085f0 2004-12-25 devnull
403 619085f0 2004-12-25 devnull int
404 619085f0 2004-12-25 devnull channbsendul(Channel *c, ulong val)
405 619085f0 2004-12-25 devnull {
406 619085f0 2004-12-25 devnull return _chanop(c, CHANSND, &val, 0);
407 619085f0 2004-12-25 devnull }
408 619085f0 2004-12-25 devnull
409 619085f0 2004-12-25 devnull ulong
410 619085f0 2004-12-25 devnull channbrecvul(Channel *c)
411 619085f0 2004-12-25 devnull {
412 619085f0 2004-12-25 devnull ulong val;
413 619085f0 2004-12-25 devnull
414 0215811d 2008-05-06 rsc if(_chanop(c, CHANRCV, &val, 0) > 0)
415 0215811d 2008-05-06 rsc return val;
416 369923f6 2020-01-13 rsc return 0;
417 619085f0 2004-12-25 devnull }