[BACK]Return to framebuf.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libpuffs

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>