Annotation of src/lib/libpuffs/framebuf.c, Revision 1.17
1.17 ! pooka 1: /* $NetBSD: framebuf.c,v 1.16 2007/07/08 17:24:41 pooka Exp $ */
1.1 pooka 2:
3: /*
4: * Copyright (c) 2007 Antti Kantee. All Rights Reserved.
5: *
6: * Development of this software was supported by the
7: * Finnish Cultural Foundation.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: *
18: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
19: * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28: * SUCH DAMAGE.
29: */
30:
1.17 ! pooka 31: /*
! 32: * The event portion of this code is a twisty maze of pointers,
! 33: * flags, yields and continues. Sincere aplogies.
! 34: */
! 35:
1.1 pooka 36: #include <sys/cdefs.h>
37: #if !defined(lint)
1.17 ! pooka 38: __RCSID("$NetBSD: framebuf.c,v 1.16 2007/07/08 17:24:41 pooka Exp $");
1.1 pooka 39: #endif /* !lint */
40:
41: #include <sys/types.h>
42: #include <sys/queue.h>
43:
44: #include <assert.h>
45: #include <errno.h>
46: #include <poll.h>
47: #include <puffs.h>
48: #include <stdlib.h>
1.5 pooka 49: #include <unistd.h>
1.1 pooka 50:
51: #include "puffs_priv.h"
52:
53: struct puffs_framebuf {
54: struct puffs_cc *pcc; /* pcc to continue with */
55: /* OR */
1.8 pooka 56: puffs_framev_cb fcb; /* non-blocking callback */
1.1 pooka 57: void *fcb_arg; /* argument for previous */
58:
59: uint8_t *buf; /* buffer base */
60: size_t len; /* total length */
61:
62: size_t offset; /* cursor, telloff() */
63: size_t maxoff; /* maximum offset for data, tellsize() */
64:
1.8 pooka 65: volatile int rv; /* errno value */
1.1 pooka 66:
67: int istat;
68:
69: TAILQ_ENTRY(puffs_framebuf) pfb_entries;
70: };
71: #define ISTAT_NODESTROY 0x01 /* indestructible by framebuf_destroy() */
72: #define ISTAT_INTERNAL 0x02 /* never leaves library */
73: #define ISTAT_NOREPLY 0x04 /* nuke after sending */
1.14 pooka 74: #define ISTAT_DIRECT 0x08 /* receive directly, no moveinfo */
1.1 pooka 75:
1.13 pooka 76: #define ISTAT_ONQUEUE ISTAT_NODESTROY /* alias */
77:
1.11 pooka 78: #define PUFBUF_INCRALLOC 4096
1.1 pooka 79: #define PUFBUF_REMAIN(p) (p->len - p->offset)
80:
1.17 ! pooka 81: /* for poll/kqueue */
! 82: struct puffs_fbevent {
! 83: struct puffs_cc *pcc;
! 84: int what;
! 85: volatile int rv;
! 86:
! 87: LIST_ENTRY(puffs_fbevent) pfe_entries;
! 88: };
! 89:
1.5 pooka 90: static struct puffs_fctrl_io *
91: getfiobyfd(struct puffs_usermount *pu, int fd)
92: {
1.6 pooka 93: struct puffs_framectrl *pfctrl = &pu->pu_framectrl;
1.5 pooka 94: struct puffs_fctrl_io *fio;
95:
1.6 pooka 96: LIST_FOREACH(fio, &pfctrl->fb_ios, fio_entries)
1.5 pooka 97: if (fio->io_fd == fd)
98: return fio;
99: return NULL;
100: }
101:
1.1 pooka 102: struct puffs_framebuf *
103: puffs_framebuf_make()
104: {
105: struct puffs_framebuf *pufbuf;
106:
107: pufbuf = malloc(sizeof(struct puffs_framebuf));
108: if (pufbuf == NULL)
109: return NULL;
110: memset(pufbuf, 0, sizeof(struct puffs_framebuf));
111:
112: pufbuf->buf = malloc(PUFBUF_INCRALLOC);
113: if (pufbuf->buf == NULL) {
114: free(pufbuf);
115: return NULL;
116: }
1.11 pooka 117: pufbuf->len = PUFBUF_INCRALLOC;
1.1 pooka 118:
119: puffs_framebuf_recycle(pufbuf);
120: return pufbuf;
121: }
122:
123: void
124: puffs_framebuf_destroy(struct puffs_framebuf *pufbuf)
125: {
126:
127: assert((pufbuf->istat & ISTAT_NODESTROY) == 0);
128:
129: free(pufbuf->buf);
130: free(pufbuf);
131: }
132:
133: void
134: puffs_framebuf_recycle(struct puffs_framebuf *pufbuf)
135: {
136:
137: assert((pufbuf->istat & ISTAT_NODESTROY) == 0);
138:
139: pufbuf->offset = 0;
140: pufbuf->maxoff = 0;
141: pufbuf->istat = 0;
142: }
143:
144: static int
145: reservespace(struct puffs_framebuf *pufbuf, size_t off, size_t wantsize)
146: {
147: size_t incr;
148: void *nd;
149:
150: if (off <= pufbuf->len && pufbuf->len - off >= wantsize)
151: return 0;
152:
153: for (incr = PUFBUF_INCRALLOC;
154: pufbuf->len + incr < off + wantsize;
155: incr += PUFBUF_INCRALLOC)
156: continue;
157:
158: nd = realloc(pufbuf->buf, pufbuf->offset + incr);
159: if (nd == NULL)
160: return -1;
161:
162: pufbuf->buf = nd;
163: pufbuf->len += incr;
164:
165: return 0;
166: }
167:
168: int
169: puffs_framebuf_reserve_space(struct puffs_framebuf *pufbuf, size_t wantsize)
170: {
171:
172: return reservespace(pufbuf, pufbuf->offset, wantsize);
173: }
174:
175: int
176: puffs_framebuf_putdata(struct puffs_framebuf *pufbuf,
177: const void *data, size_t dlen)
178: {
179:
180: if (PUFBUF_REMAIN(pufbuf) < dlen)
181: if (puffs_framebuf_reserve_space(pufbuf, dlen) == -1)
182: return -1;
183:
184: memcpy(pufbuf->buf + pufbuf->offset, data, dlen);
185: pufbuf->offset += dlen;
186:
187: if (pufbuf->offset > pufbuf->maxoff)
188: pufbuf->maxoff = pufbuf->offset;
189:
190: return 0;
191: }
192:
193: int
194: puffs_framebuf_putdata_atoff(struct puffs_framebuf *pufbuf, size_t offset,
195: const void *data, size_t dlen)
196: {
197:
198: if (reservespace(pufbuf, offset, dlen) == -1)
199: return -1;
200:
201: memcpy(pufbuf->buf + offset, data, dlen);
202:
203: if (offset + dlen > pufbuf->maxoff)
204: pufbuf->maxoff = offset + dlen;
205:
206: return 0;
207: }
208:
209: int
210: puffs_framebuf_getdata(struct puffs_framebuf *pufbuf, void *data, size_t dlen)
211: {
212:
213: if (pufbuf->maxoff < pufbuf->offset + dlen) {
214: errno = ENOBUFS;
215: return -1;
216: }
217:
218: memcpy(data, pufbuf->buf + pufbuf->offset, dlen);
219: pufbuf->offset += dlen;
220:
221: return 0;
222: }
223:
224: int
225: puffs_framebuf_getdata_atoff(struct puffs_framebuf *pufbuf, size_t offset,
226: void *data, size_t dlen)
227: {
228:
229: if (pufbuf->maxoff < offset + dlen) {
230: errno = ENOBUFS;
231: return -1;
232: }
233:
234: memcpy(data, pufbuf->buf + offset, dlen);
235: return 0;
236: }
237:
238: size_t
239: puffs_framebuf_telloff(struct puffs_framebuf *pufbuf)
240: {
241:
242: return pufbuf->offset;
243: }
244:
245: size_t
246: puffs_framebuf_tellsize(struct puffs_framebuf *pufbuf)
247: {
248:
249: return pufbuf->maxoff;
250: }
251:
1.3 pooka 252: size_t
253: puffs_framebuf_remaining(struct puffs_framebuf *pufbuf)
254: {
255:
256: return puffs_framebuf_tellsize(pufbuf) - puffs_framebuf_telloff(pufbuf);
257: }
258:
1.1 pooka 259: int
260: puffs_framebuf_seekset(struct puffs_framebuf *pufbuf, size_t newoff)
261: {
262:
263: if (reservespace(pufbuf, newoff, 0) == -1)
264: return -1;
265:
266: pufbuf->offset = newoff;
267: return 0;
268: }
269:
270: int
271: puffs_framebuf_getwindow(struct puffs_framebuf *pufbuf, size_t winoff,
272: void **data, size_t *dlen)
273: {
274: size_t winlen;
275:
276: #ifdef WINTESTING
277: winlen = MIN(*dlen, 32);
278: #else
279: winlen = *dlen;
280: #endif
281:
282: if (reservespace(pufbuf, winoff, winlen) == -1)
283: return -1;
284:
285: *data = pufbuf->buf + winoff;
286: if (pufbuf->maxoff < winoff + winlen)
287: pufbuf->maxoff = winoff + winlen;
288:
289: return 0;
290: }
291:
1.8 pooka 292: static void
293: errnotify(struct puffs_framebuf *pufbuf, int error)
294: {
295:
296: pufbuf->rv = error;
297: if (pufbuf->pcc) {
298: puffs_goto(pufbuf->pcc);
299: } else if (pufbuf->fcb) {
300: pufbuf->istat &= ~ISTAT_NODESTROY;
301: pufbuf->fcb(puffs_cc_getusermount(pufbuf->pcc),
1.10 pooka 302: pufbuf, pufbuf->fcb_arg, error);
1.8 pooka 303: } else {
304: pufbuf->istat &= ~ISTAT_NODESTROY;
305: puffs_framebuf_destroy(pufbuf);
306: }
307: }
308:
309: #define GETFIO(fd) \
310: do { \
311: fio = getfiobyfd(pu, fd); \
312: if (fio == NULL) { \
313: errno = EINVAL; \
314: return -1; \
315: } \
316: if (fio->stat & FIO_WRGONE) { \
317: errno = ESHUTDOWN; \
318: return -1; \
319: } \
320: } while (/*CONSTCOND*/0)
321:
1.1 pooka 322: int
1.8 pooka 323: puffs_framev_enqueue_cc(struct puffs_cc *pcc, int fd,
1.14 pooka 324: struct puffs_framebuf *pufbuf, int flags)
1.1 pooka 325: {
326: struct puffs_usermount *pu = puffs_cc_getusermount(pcc);
1.5 pooka 327: struct puffs_fctrl_io *fio;
328:
1.8 pooka 329: /*
330: * Technically we shouldn't allow this is RDGONE, but it's
331: * difficult to trap write close without allowing writes.
332: * And besides, there's probably a disconnect sequence in
333: * the protocol, so unexpectedly getting a closed fd is
334: * most likely an error condition.
335: */
336: GETFIO(fd);
1.1 pooka 337:
338: pufbuf->pcc = pcc;
339: pufbuf->fcb = NULL;
340: pufbuf->fcb_arg = NULL;
341:
342: pufbuf->offset = 0;
343: pufbuf->istat |= ISTAT_NODESTROY;
344:
1.14 pooka 345: if (flags & PUFFS_FBQUEUE_URGENT)
346: TAILQ_INSERT_HEAD(&fio->snd_qing, pufbuf, pfb_entries);
347: else
348: TAILQ_INSERT_TAIL(&fio->snd_qing, pufbuf, pfb_entries);
1.1 pooka 349:
350: puffs_cc_yield(pcc);
351: if (pufbuf->rv) {
1.8 pooka 352: pufbuf->istat &= ~ISTAT_NODESTROY;
1.1 pooka 353: errno = pufbuf->rv;
354: return -1;
355: }
356:
357: return 0;
358: }
359:
1.5 pooka 360: int
1.8 pooka 361: puffs_framev_enqueue_cb(struct puffs_usermount *pu, int fd,
1.14 pooka 362: struct puffs_framebuf *pufbuf, puffs_framev_cb fcb, void *arg,
363: int flags)
1.1 pooka 364: {
1.5 pooka 365: struct puffs_fctrl_io *fio;
366:
1.8 pooka 367: /* see enqueue_cc */
368: GETFIO(fd);
1.1 pooka 369:
370: pufbuf->pcc = NULL;
371: pufbuf->fcb = fcb;
372: pufbuf->fcb_arg = arg;
373:
374: pufbuf->offset = 0;
375: pufbuf->istat |= ISTAT_NODESTROY;
376:
1.14 pooka 377: if (flags & PUFFS_FBQUEUE_URGENT)
378: TAILQ_INSERT_HEAD(&fio->snd_qing, pufbuf, pfb_entries);
379: else
380: TAILQ_INSERT_TAIL(&fio->snd_qing, pufbuf, pfb_entries);
1.5 pooka 381:
382: return 0;
1.1 pooka 383: }
384:
1.5 pooka 385: int
1.8 pooka 386: puffs_framev_enqueue_justsend(struct puffs_usermount *pu, int fd,
1.14 pooka 387: struct puffs_framebuf *pufbuf, int reply, int flags)
1.1 pooka 388: {
1.5 pooka 389: struct puffs_fctrl_io *fio;
390:
1.8 pooka 391: GETFIO(fd);
1.1 pooka 392:
393: pufbuf->pcc = NULL;
394: pufbuf->fcb = NULL;
395: pufbuf->fcb_arg = NULL;
396:
397: pufbuf->offset = 0;
398: pufbuf->istat |= ISTAT_NODESTROY;
399: if (!reply)
400: pufbuf->istat |= ISTAT_NOREPLY;
401:
1.14 pooka 402: if (flags & PUFFS_FBQUEUE_URGENT)
403: TAILQ_INSERT_HEAD(&fio->snd_qing, pufbuf, pfb_entries);
404: else
405: TAILQ_INSERT_TAIL(&fio->snd_qing, pufbuf, pfb_entries);
406:
407: return 0;
408: }
409:
410: /* ARGSUSED */
411: int
412: puffs_framev_enqueue_directreceive(struct puffs_cc *pcc, int fd,
413: struct puffs_framebuf *pufbuf, int flags /* used in the future */)
414: {
415: struct puffs_usermount *pu = puffs_cc_getusermount(pcc);
416: struct puffs_fctrl_io *fio;
417:
418: fio = getfiobyfd(pu, fd);
419: if (fio == NULL) {
420: errno = EINVAL;
421: return -1;
422: }
423:
424: /* XXX: should have cur_in queue */
425: assert(fio->cur_in == NULL);
426: fio->cur_in = pufbuf;
427:
428: pufbuf->pcc = pcc;
429: pufbuf->fcb = NULL;
430: pufbuf->fcb_arg = NULL;
431:
432: pufbuf->offset = 0;
433: pufbuf->istat |= ISTAT_NODESTROY | ISTAT_DIRECT;
434:
435: puffs_cc_yield(pcc);
436: pufbuf->istat &= ~ISTAT_NODESTROY; /* XXX: not the right place */
437: if (pufbuf->rv) {
438: errno = pufbuf->rv;
439: return -1;
440: }
441:
442: return 0;
443: }
444:
445: int
446: puffs_framev_enqueue_directsend(struct puffs_cc *pcc, int fd,
447: struct puffs_framebuf *pufbuf, int flags)
448: {
449: struct puffs_usermount *pu = puffs_cc_getusermount(pcc);
450: struct puffs_fctrl_io *fio;
451:
452: if (flags & PUFFS_FBQUEUE_URGENT)
453: abort(); /* EOPNOTSUPP for now */
454:
455: GETFIO(fd);
456:
457: pufbuf->pcc = pcc;
458: pufbuf->fcb = NULL;
459: pufbuf->fcb_arg = NULL;
460:
461: pufbuf->offset = 0;
462: pufbuf->istat |= ISTAT_NODESTROY | ISTAT_DIRECT;
463:
1.5 pooka 464: TAILQ_INSERT_TAIL(&fio->snd_qing, pufbuf, pfb_entries);
465:
1.14 pooka 466: puffs_cc_yield(pcc);
467: if (pufbuf->rv) {
468: pufbuf->istat &= ~ISTAT_NODESTROY;
469: errno = pufbuf->rv;
470: return -1;
471: }
472:
1.5 pooka 473: return 0;
1.1 pooka 474: }
475:
1.13 pooka 476: /*
477: * this beauty shall remain undocumented for now
478: */
479: int
480: puffs_framev_framebuf_ccpromote(struct puffs_framebuf *pufbuf,
481: struct puffs_cc *pcc)
482: {
483:
484: if ((pufbuf->istat & ISTAT_ONQUEUE) == 0) {
485: errno = EBUSY;
486: return -1;
487: }
488:
489: pufbuf->pcc = pcc;
490: pufbuf->fcb = NULL;
491: pufbuf->fcb_arg = NULL;
492: pufbuf->istat &= ~ISTAT_NOREPLY;
493:
494: puffs_cc_yield(pcc);
495:
496: return 0;
497: }
498:
1.17 ! pooka 499: int
! 500: puffs_framev_enqueue_waitevent(struct puffs_cc *pcc, int fd, int *what)
! 501: {
! 502: struct puffs_usermount *pu = puffs_cc_getusermount(pcc);
! 503: struct puffs_fctrl_io *fio;
! 504: struct puffs_fbevent feb;
! 505: struct kevent kev;
! 506: int rv, svwhat;
! 507:
! 508: svwhat = *what;
! 509:
! 510: if (*what == 0) {
! 511: errno = EINVAL;
! 512: return -1;
! 513: }
! 514:
! 515: fio = getfiobyfd(pu, fd);
! 516: if (fio == NULL) {
! 517: errno = EINVAL;
! 518: return -1;
! 519: }
! 520:
! 521: feb.pcc = pcc;
! 522: feb.what = *what & (PUFFS_FBIO_READ|PUFFS_FBIO_WRITE|PUFFS_FBIO_ERROR);
! 523:
! 524: if (*what & PUFFS_FBIO_READ)
! 525: if ((fio->stat & FIO_ENABLE_R) == 0)
! 526: EV_SET(&kev, fd, EVFILT_READ, EV_ENABLE,
! 527: 0, 0, (uintptr_t)fio);
! 528:
! 529: rv = kevent(pu->pu_kq, &kev, 1, NULL, 0, NULL);
! 530: if (rv != 0)
! 531: return errno;
! 532:
! 533: if (*what & PUFFS_FBIO_READ)
! 534: fio->rwait++;
! 535: if (*what & PUFFS_FBIO_WRITE)
! 536: fio->wwait++;
! 537:
! 538: LIST_INSERT_HEAD(&fio->ev_qing, &feb, pfe_entries);
! 539: puffs_cc_yield(pcc);
! 540:
! 541: assert(svwhat == *what);
! 542:
! 543: if (*what & PUFFS_FBIO_READ) {
! 544: fio->rwait--;
! 545: if (fio->rwait == 0 && (fio->stat & FIO_ENABLE_R) == 0) {
! 546: EV_SET(&kev, fd, EVFILT_READ, EV_DISABLE,
! 547: 0, 0, (uintptr_t)fio);
! 548: rv = kevent(pu->pu_kq, &kev, 1, NULL, 0, NULL);
! 549: #if 0
! 550: if (rv != 0)
! 551: /* XXXXX oh dear */;
! 552: #endif
! 553: }
! 554: }
! 555: if (*what & PUFFS_FBIO_WRITE)
! 556: fio->wwait--;
! 557:
! 558: if (feb.rv == 0)
! 559: *what = feb.what;
! 560: else
! 561: *what = POLLERR;
! 562:
! 563: return feb.rv;
! 564: }
! 565:
! 566: void
! 567: puffs_framev_notify(struct puffs_fctrl_io *fio, int what)
! 568: {
! 569: struct puffs_fbevent *fbevp;
! 570:
! 571: restart:
! 572: LIST_FOREACH(fbevp, &fio->ev_qing, pfe_entries) {
! 573: if (fbevp->what & what) {
! 574: fbevp->what = what;
! 575: fbevp->rv = 0;
! 576: LIST_REMOVE(fbevp, pfe_entries);
! 577: puffs_cc_continue(fbevp->pcc);
! 578: goto restart;
! 579: }
! 580: }
! 581: }
! 582:
1.1 pooka 583: static struct puffs_framebuf *
584: findbuf(struct puffs_usermount *pu, struct puffs_framectrl *fctrl,
1.5 pooka 585: struct puffs_fctrl_io *fio, struct puffs_framebuf *findme)
1.1 pooka 586: {
587: struct puffs_framebuf *cand;
588:
1.5 pooka 589: TAILQ_FOREACH(cand, &fio->res_qing, pfb_entries)
1.12 pooka 590: if (fctrl->cmpfb(pu, findme, cand) == 0)
1.1 pooka 591: break;
592:
593: if (cand == NULL)
594: return NULL;
595:
1.5 pooka 596: TAILQ_REMOVE(&fio->res_qing, cand, pfb_entries);
1.1 pooka 597: return cand;
598: }
599:
600: static void
601: moveinfo(struct puffs_framebuf *from, struct puffs_framebuf *to)
602: {
603:
604: assert(from->istat & ISTAT_INTERNAL);
605:
606: /* migrate buffer */
607: free(to->buf);
608: to->buf = from->buf;
609: from->buf = NULL;
610:
611: /* migrate buffer info */
612: to->len = from->len;
613: to->offset = from->offset;
614: to->maxoff = from->maxoff;
615: }
616:
1.8 pooka 617: void
618: puffs_framev_input(struct puffs_usermount *pu, struct puffs_framectrl *fctrl,
1.5 pooka 619: struct puffs_fctrl_io *fio, struct puffs_putreq *ppr)
1.1 pooka 620: {
621: struct puffs_framebuf *pufbuf, *appbuf;
622: int rv, complete;
623:
1.14 pooka 624: while ((fio->stat & FIO_DEAD) == 0 && (fio->stat & FIO_ENABLE_R)) {
1.5 pooka 625: if ((pufbuf = fio->cur_in) == NULL) {
1.1 pooka 626: pufbuf = puffs_framebuf_make();
627: if (pufbuf == NULL)
1.8 pooka 628: return;
1.1 pooka 629: pufbuf->istat |= ISTAT_INTERNAL;
1.5 pooka 630: fio->cur_in = pufbuf;
1.1 pooka 631: }
632:
633: complete = 0;
1.5 pooka 634: rv = fctrl->rfb(pu, pufbuf, fio->io_fd, &complete);
1.1 pooka 635:
636: /* error */
637: if (rv) {
1.8 pooka 638: puffs_framev_readclose(pu, fio, rv);
1.17 ! pooka 639: fio->cur_in = NULL;
! 640: if ((pufbuf->istat & ISTAT_DIRECT) == 0) {
! 641: assert((pufbuf->istat & ISTAT_NODESTROY) == 0);
! 642: puffs_framebuf_destroy(pufbuf);
! 643: }
1.8 pooka 644: return;
1.1 pooka 645: }
646:
647: /* partial read, come back to fight another day */
648: if (complete == 0)
649: break;
650:
651: /* else: full read, process */
1.14 pooka 652: if ((pufbuf->istat & ISTAT_DIRECT) == 0) {
653: appbuf = findbuf(pu, fctrl, fio, pufbuf);
1.1 pooka 654:
1.14 pooka 655: /* XXX: error delivery? */
656: if (appbuf == NULL) {
657: /* errno = ENOMSG; */
658: return;
659: }
660:
661: moveinfo(pufbuf, appbuf);
662: puffs_framebuf_destroy(pufbuf);
663: } else {
664: appbuf = pufbuf;
1.1 pooka 665: }
666: appbuf->istat &= ~ISTAT_NODESTROY;
1.14 pooka 667: fio->cur_in = NULL;
668:
1.1 pooka 669: if (appbuf->pcc) {
670: puffs_docc(appbuf->pcc, ppr);
671: } else if (appbuf->fcb) {
1.10 pooka 672: appbuf->fcb(pu, appbuf, appbuf->fcb_arg, 0);
1.1 pooka 673: } else {
674: puffs_framebuf_destroy(appbuf);
675: }
676:
677: /* hopeless romantics, here we go again */
678: }
679: }
680:
1.6 pooka 681: int
1.8 pooka 682: puffs_framev_output(struct puffs_usermount *pu, struct puffs_framectrl *fctrl,
1.14 pooka 683: struct puffs_fctrl_io *fio, struct puffs_putreq *ppr)
1.1 pooka 684: {
685: struct puffs_framebuf *pufbuf, *pufbuf_next;
1.14 pooka 686: int rv, complete, done;
1.8 pooka 687:
688: if (fio->stat & FIO_DEAD)
689: return 0;
1.1 pooka 690:
1.14 pooka 691: for (pufbuf = TAILQ_FIRST(&fio->snd_qing), done = 0;
692: pufbuf && (fio->stat & FIO_DEAD) == 0 && fio->stat & FIO_ENABLE_W;
1.1 pooka 693: pufbuf = pufbuf_next) {
694: complete = 0;
695: pufbuf_next = TAILQ_NEXT(pufbuf, pfb_entries);
1.5 pooka 696: rv = fctrl->wfb(pu, pufbuf, fio->io_fd, &complete);
1.1 pooka 697:
698: if (rv) {
1.8 pooka 699: puffs_framev_writeclose(pu, fio, rv);
1.14 pooka 700: done = 1;
1.8 pooka 701: break;
1.1 pooka 702: }
703:
704: /* partial write */
705: if (complete == 0)
1.14 pooka 706: return done;
1.1 pooka 707:
708: /* else, complete write */
1.5 pooka 709: TAILQ_REMOVE(&fio->snd_qing, pufbuf, pfb_entries);
1.1 pooka 710:
1.8 pooka 711: /* can't wait for result if we can't read */
712: if (fio->stat & FIO_RDGONE) {
713: errnotify(pufbuf, ENXIO);
1.14 pooka 714: done = 1;
715: } else if ((pufbuf->istat & ISTAT_DIRECT)) {
716: pufbuf->istat &= ~ISTAT_NODESTROY;
717: puffs_docc(pufbuf->pcc, ppr);
718: done = 1;
719: } else if ((pufbuf->istat & ISTAT_NOREPLY) == 0) {
1.5 pooka 720: TAILQ_INSERT_TAIL(&fio->res_qing, pufbuf,
1.1 pooka 721: pfb_entries);
722: } else {
723: pufbuf->istat &= ~ISTAT_NODESTROY;
724: puffs_framebuf_destroy(pufbuf);
725: }
1.8 pooka 726:
727: /* omstart! */
1.1 pooka 728: }
729:
1.14 pooka 730: return done;
1.1 pooka 731: }
732:
733: int
1.14 pooka 734: puffs_framev_addfd(struct puffs_usermount *pu, int fd, int what)
1.5 pooka 735: {
1.6 pooka 736: struct puffs_framectrl *pfctrl = &pu->pu_framectrl;
1.5 pooka 737: struct puffs_fctrl_io *fio;
1.14 pooka 738: struct kevent *newevs;
1.5 pooka 739: struct kevent kev[2];
1.7 pooka 740: size_t nfds;
1.14 pooka 741: int rv, readenable;
1.5 pooka 742:
1.6 pooka 743: nfds = pfctrl->nfds+1;
744: newevs = realloc(pfctrl->evs, (2*nfds+1) * sizeof(struct kevent));
1.5 pooka 745: if (newevs == NULL)
746: return -1;
747: pfctrl->evs = newevs;
748:
749: fio = malloc(sizeof(struct puffs_fctrl_io));
750: if (fio == NULL)
751: return -1;
1.17 ! pooka 752: memset(fio, 0, sizeof(struct puffs_fctrl_io));
1.14 pooka 753: fio->io_fd = fd;
754: fio->cur_in = NULL;
755: TAILQ_INIT(&fio->snd_qing);
756: TAILQ_INIT(&fio->res_qing);
1.17 ! pooka 757: LIST_INIT(&fio->ev_qing);
1.14 pooka 758:
759: readenable = 0;
760: if ((what & PUFFS_FBIO_READ) == 0)
761: readenable = EV_DISABLE;
1.5 pooka 762:
1.6 pooka 763: if (pu->pu_state & PU_INLOOP) {
1.14 pooka 764: EV_SET(&kev[0], fd, EVFILT_READ,
765: EV_ADD|readenable, 0, 0, (intptr_t)fio);
766: EV_SET(&kev[1], fd, EVFILT_WRITE,
767: EV_ADD|EV_DISABLE, 0, 0, (intptr_t)fio);
1.6 pooka 768: rv = kevent(pu->pu_kq, kev, 2, NULL, 0, NULL);
769: if (rv == -1) {
770: free(fio);
771: return -1;
772: }
1.5 pooka 773: }
1.14 pooka 774: if (what & PUFFS_FBIO_READ)
775: fio->stat |= FIO_ENABLE_R;
776: if (what & PUFFS_FBIO_WRITE)
777: fio->stat |= FIO_ENABLE_W;
1.5 pooka 778:
779: LIST_INSERT_HEAD(&pfctrl->fb_ios, fio, fio_entries);
1.6 pooka 780: pfctrl->nfds = nfds;
1.5 pooka 781:
782: return 0;
783: }
784:
1.14 pooka 785: /*
786: * XXX: the following en/disable should be coalesced and executed
1.17 ! pooka 787: * only during the actual kevent call. So feel free to fix if
1.14 pooka 788: * threatened by mindblowing boredom.
789: */
790:
791: int
792: puffs_framev_enablefd(struct puffs_usermount *pu, int fd, int what)
793: {
794: struct kevent kev;
795: struct puffs_fctrl_io *fio;
1.17 ! pooka 796: int rv = 0;
1.14 pooka 797:
798: assert((what & (PUFFS_FBIO_READ | PUFFS_FBIO_WRITE)) != 0);
799:
800: fio = getfiobyfd(pu, fd);
801: if (fio == NULL) {
802: errno = ENXIO;
803: return -1;
804: }
805:
806: /* write is enabled in the event loop if there is output */
1.17 ! pooka 807: if (what & PUFFS_FBIO_READ && fio->rwait == 0) {
! 808: EV_SET(&kev, fd, EVFILT_READ, EV_ENABLE, 0, 0, (uintptr_t)fio);
! 809: rv = kevent(pu->pu_kq, &kev, 1, NULL, 0, NULL);
! 810: }
1.14 pooka 811:
812: if (rv == 0) {
813: if (what & PUFFS_FBIO_READ)
814: fio->stat |= FIO_ENABLE_R;
815: if (what & PUFFS_FBIO_WRITE)
816: fio->stat |= FIO_ENABLE_W;
817: }
818:
819: return rv;
820: }
821:
822: int
823: puffs_framev_disablefd(struct puffs_usermount *pu, int fd, int what)
824: {
825: struct kevent kev[2];
826: struct puffs_fctrl_io *fio;
827: size_t i;
828: int rv;
829:
830: assert((what & (PUFFS_FBIO_READ | PUFFS_FBIO_WRITE)) != 0);
831:
832: fio = getfiobyfd(pu, fd);
833: if (fio == NULL) {
834: errno = ENXIO;
835: return -1;
836: }
837:
838: i = 0;
1.17 ! pooka 839: if (what & PUFFS_FBIO_READ && fio->rwait == 0) {
1.14 pooka 840: EV_SET(&kev[0], fd,
841: EVFILT_READ, EV_DISABLE, 0, 0, (uintptr_t)fio);
842: i++;
843: }
1.17 ! pooka 844: if (what & PUFFS_FBIO_WRITE && fio->stat & FIO_WR && fio->wwait == 0) {
1.14 pooka 845: EV_SET(&kev[1], fd,
846: EVFILT_WRITE, EV_DISABLE, 0, 0, (uintptr_t)fio);
847: i++;
848: }
1.17 ! pooka 849: if (i)
! 850: rv = kevent(pu->pu_kq, kev, i, NULL, 0, NULL);
! 851: else
! 852: rv = 0;
1.14 pooka 853:
854: if (rv == 0) {
855: if (what & PUFFS_FBIO_READ)
856: fio->stat &= ~FIO_ENABLE_R;
857: if (what & PUFFS_FBIO_WRITE)
858: fio->stat &= ~FIO_ENABLE_W;
859: }
860:
861: return rv;
862: }
863:
1.8 pooka 864: void
865: puffs_framev_readclose(struct puffs_usermount *pu,
866: struct puffs_fctrl_io *fio, int error)
1.5 pooka 867: {
868: struct puffs_framebuf *pufbuf;
1.8 pooka 869: struct kevent kev;
870: int notflag;
871:
872: if (fio->stat & FIO_RDGONE || fio->stat & FIO_DEAD)
873: return;
874: fio->stat |= FIO_RDGONE;
875:
876: if (fio->cur_in) {
1.14 pooka 877: if ((fio->cur_in->istat & ISTAT_DIRECT) == 0) {
878: puffs_framebuf_destroy(fio->cur_in);
879: fio->cur_in = NULL;
880: } else {
881: errnotify(fio->cur_in, error);
882: }
1.8 pooka 883: }
1.5 pooka 884:
1.8 pooka 885: while ((pufbuf = TAILQ_FIRST(&fio->res_qing)) != NULL) {
886: TAILQ_REMOVE(&fio->res_qing, pufbuf, pfb_entries);
887: errnotify(pufbuf, error);
1.6 pooka 888: }
1.5 pooka 889:
1.8 pooka 890: EV_SET(&kev, fio->io_fd, EVFILT_READ, EV_DELETE, 0, 0, 0);
891: (void) kevent(pu->pu_kq, &kev, 1, NULL, 0, NULL);
892:
1.14 pooka 893: notflag = PUFFS_FBIO_READ;
1.8 pooka 894: if (fio->stat & FIO_WRGONE)
1.14 pooka 895: notflag |= PUFFS_FBIO_WRITE;
1.8 pooka 896:
1.15 pooka 897: if (pu->pu_framectrl.fdnotfn)
898: pu->pu_framectrl.fdnotfn(pu, fio->io_fd, notflag);
1.8 pooka 899: }
900:
901: void
902: puffs_framev_writeclose(struct puffs_usermount *pu,
903: struct puffs_fctrl_io *fio, int error)
904: {
905: struct puffs_framebuf *pufbuf;
906: struct kevent kev;
907: int notflag;
908:
909: if (fio->stat & FIO_WRGONE || fio->stat & FIO_DEAD)
910: return;
911: fio->stat |= FIO_WRGONE;
1.5 pooka 912:
913: while ((pufbuf = TAILQ_FIRST(&fio->snd_qing)) != NULL) {
914: TAILQ_REMOVE(&fio->snd_qing, pufbuf, pfb_entries);
1.8 pooka 915: errnotify(pufbuf, error);
1.5 pooka 916: }
1.8 pooka 917:
918: EV_SET(&kev, fio->io_fd, EVFILT_WRITE, EV_DELETE, 0, 0, 0);
919: (void) kevent(pu->pu_kq, &kev, 1, NULL, 0, NULL);
920:
1.14 pooka 921: notflag = PUFFS_FBIO_WRITE;
1.8 pooka 922: if (fio->stat & FIO_RDGONE)
1.14 pooka 923: notflag |= PUFFS_FBIO_READ;
1.8 pooka 924:
1.15 pooka 925: if (pu->pu_framectrl.fdnotfn)
926: pu->pu_framectrl.fdnotfn(pu, fio->io_fd, notflag);
1.8 pooka 927: }
928:
929: static int
930: removefio(struct puffs_usermount *pu, struct puffs_fctrl_io *fio, int error)
931: {
932: struct puffs_framectrl *pfctrl = &pu->pu_framectrl;
1.17 ! pooka 933: struct puffs_fbevent *fbevp;
1.8 pooka 934:
935: LIST_REMOVE(fio, fio_entries);
936: if (pu->pu_state & PU_INLOOP) {
937: puffs_framev_readclose(pu, fio, error);
938: puffs_framev_writeclose(pu, fio, error);
1.5 pooka 939: }
940:
1.17 ! pooka 941: while ((fbevp = LIST_FIRST(&fio->ev_qing)) != NULL) {
! 942: fbevp->rv = error;
! 943: LIST_REMOVE(fbevp, pfe_entries);
! 944: puffs_goto(fbevp->pcc);
! 945: }
! 946:
1.5 pooka 947: /* don't bother with realloc */
1.6 pooka 948: pfctrl->nfds--;
1.5 pooka 949:
1.8 pooka 950: /* don't free us yet, might have some references in event arrays */
951: fio->stat |= FIO_DEAD;
952: LIST_INSERT_HEAD(&pfctrl->fb_ios_rmlist, fio, fio_entries);
953:
1.5 pooka 954: return 0;
955:
956: }
957:
958: int
1.8 pooka 959: puffs_framev_removefd(struct puffs_usermount *pu, int fd, int error)
1.5 pooka 960: {
961: struct puffs_fctrl_io *fio;
962:
963: fio = getfiobyfd(pu, fd);
964: if (fio == NULL) {
965: errno = ENXIO;
966: return -1;
967: }
968:
1.9 pooka 969: return removefio(pu, fio, error ? error : ECONNRESET);
1.8 pooka 970: }
971:
1.15 pooka 972: void
973: puffs_framev_removeonclose(struct puffs_usermount *pu, int fd, int what)
1.8 pooka 974: {
975:
1.16 pooka 976: if (what == (PUFFS_FBIO_READ | PUFFS_FBIO_WRITE))
1.9 pooka 977: (void) puffs_framev_removefd(pu, fd, ECONNRESET);
1.5 pooka 978: }
979:
1.8 pooka 980: void
981: puffs_framev_unmountonclose(struct puffs_usermount *pu, int fd, int what)
982: {
983:
984: /* XXX & X: unmount is non-sensible */
1.15 pooka 985: puffs_framev_removeonclose(pu, fd, what);
1.16 pooka 986: if (what == (PUFFS_FBIO_READ | PUFFS_FBIO_WRITE))
1.8 pooka 987: PU_SETSTATE(pu, PUFFS_STATE_UNMOUNTED);
988: }
989:
990: void
991: puffs_framev_init(struct puffs_usermount *pu,
992: puffs_framev_readframe_fn rfb, puffs_framev_writeframe_fn wfb,
1.12 pooka 993: puffs_framev_cmpframe_fn cmpfb, puffs_framev_fdnotify_fn fdnotfn)
1.1 pooka 994: {
1.6 pooka 995: struct puffs_framectrl *pfctrl;
996:
997: pfctrl = &pu->pu_framectrl;
1.1 pooka 998: pfctrl->rfb = rfb;
999: pfctrl->wfb = wfb;
1000: pfctrl->cmpfb = cmpfb;
1.15 pooka 1001: pfctrl->fdnotfn = fdnotfn;
1.6 pooka 1002: }
1.1 pooka 1003:
1.6 pooka 1004: void
1.8 pooka 1005: puffs_framev_exit(struct puffs_usermount *pu)
1.6 pooka 1006: {
1007: struct puffs_framectrl *pfctrl = &pu->pu_framectrl;
1008: struct puffs_fctrl_io *fio;
1.1 pooka 1009:
1.6 pooka 1010: while ((fio = LIST_FIRST(&pfctrl->fb_ios)) != NULL)
1.8 pooka 1011: removefio(pu, fio, ENXIO);
1.6 pooka 1012: free(pfctrl->evs);
1.1 pooka 1013:
1.6 pooka 1014: /* closing pu->pu_kq takes care of puffsfd */
1.1 pooka 1015: }
CVSweb <webmaster@jp.NetBSD.org>