[BACK]Return to abuf.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / aucat

Annotation of src/usr.bin/aucat/abuf.c, Revision 1.25

1.25    ! ratchov     1: /*     $OpenBSD$       */
1.1       ratchov     2: /*
                      3:  * Copyright (c) 2008 Alexandre Ratchov <alex@caoua.org>
                      4:  *
                      5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice and this permission notice appear in all copies.
                      8:  *
                      9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     16:  */
                     17: /*
                     18:  * Simple byte fifo. It has one reader and one writer. The abuf
                     19:  * structure is used to interconnect audio processing units (aproc
                     20:  * structures).
                     21:  *
                     22:  * The abuf data is split in two parts: (1) valid data available to the reader
                     23:  * (2) space available to the writer, which is not necessarily unused. It works
                     24:  * as follows: the write starts filling at offset (start + used), once the data
                     25:  * is ready, the writer adds to used the count of bytes available.
1.7       ratchov    26:  */
                     27: /*
                     28:  * TODO
1.1       ratchov    29:  *
1.7       ratchov    30:  *     use blocks instead of frames for WOK and ROK macros. If necessary
                     31:  *     (unlikely) define reader block size and writer blocks size to
                     32:  *     ease pipe/socket implementation
1.1       ratchov    33:  */
                     34: #include <err.h>
1.11      ratchov    35: #include <stdarg.h>
1.1       ratchov    36: #include <stdio.h>
                     37: #include <stdlib.h>
1.4       ratchov    38: #include <string.h>
1.1       ratchov    39:
1.13      ratchov    40: #include "abuf.h"
1.8       ratchov    41: #include "aparams.h"
1.1       ratchov    42: #include "aproc.h"
1.13      ratchov    43: #include "conf.h"
1.17      ratchov    44: #ifdef DEBUG
                     45: #include "dbg.h"
                     46: #endif
1.25    ! ratchov    47:
        !            48: void abuf_dump(struct abuf *);
        !            49: int abuf_flush_do(struct abuf *);
        !            50: int abuf_fill_do(struct abuf *);
        !            51: void abuf_eof_do(struct abuf *);
        !            52: void abuf_hup_do(struct abuf *);
1.1       ratchov    53:
1.17      ratchov    54: #ifdef DEBUG
                     55: void
                     56: abuf_dbg(struct abuf *buf)
                     57: {
                     58:        if (buf->wproc) {
                     59:                aproc_dbg(buf->wproc);
                     60:        } else {
                     61:                dbg_puts("none");
                     62:        }
                     63:        dbg_puts(buf->inuse ? "=>" : "->");
                     64:        if (buf->rproc) {
                     65:                aproc_dbg(buf->rproc);
                     66:        } else {
                     67:                dbg_puts("none");
                     68:        }
                     69: }
                     70:
                     71: void
                     72: abuf_dump(struct abuf *buf)
                     73: {
                     74:        abuf_dbg(buf);
                     75:        dbg_puts(": used = ");
                     76:        dbg_putu(buf->used);
                     77:        dbg_puts("/");
                     78:        dbg_putu(buf->len);
                     79:        dbg_puts(" start = ");
                     80:        dbg_putu(buf->start);
                     81:        dbg_puts("\n");
                     82: }
                     83: #endif
1.7       ratchov    84:
1.1       ratchov    85: struct abuf *
1.24      ratchov    86: abuf_new(unsigned int nfr, struct aparams *par)
1.1       ratchov    87: {
                     88:        struct abuf *buf;
1.24      ratchov    89:        unsigned int len, bpf;
1.1       ratchov    90:
1.8       ratchov    91:        bpf = aparams_bpf(par);
1.1       ratchov    92:        len = nfr * bpf;
                     93:        buf = malloc(sizeof(struct abuf) + len);
                     94:        if (buf == NULL) {
1.17      ratchov    95: #ifdef DEBUG
                     96:                dbg_puts("couldn't allocate abuf of ");
                     97:                dbg_putu(nfr);
                     98:                dbg_puts("fr * ");
                     99:                dbg_putu(bpf);
                    100:                dbg_puts("bpf\n");
                    101:                dbg_panic();
                    102: #else
1.15      ratchov   103:                err(1, "malloc");
1.17      ratchov   104: #endif
1.1       ratchov   105:        }
                    106:        buf->bpf = bpf;
1.8       ratchov   107:        buf->cmin = par->cmin;
                    108:        buf->cmax = par->cmax;
1.7       ratchov   109:        buf->inuse = 0;
1.1       ratchov   110:
                    111:        /*
                    112:         * fill fifo pointers
                    113:         */
1.21      ratchov   114:        buf->len = nfr;
1.1       ratchov   115:        buf->used = 0;
                    116:        buf->start = 0;
                    117:        buf->rproc = NULL;
                    118:        buf->wproc = NULL;
1.7       ratchov   119:        buf->duplex = NULL;
1.1       ratchov   120:        return buf;
                    121: }
                    122:
                    123: void
                    124: abuf_del(struct abuf *buf)
                    125: {
1.7       ratchov   126:        if (buf->duplex)
                    127:                buf->duplex->duplex = NULL;
1.17      ratchov   128: #ifdef DEBUG
                    129:        if (buf->rproc || buf->wproc) {
                    130:                abuf_dbg(buf);
                    131:                dbg_puts(": can't delete referenced buffer\n");
                    132:                dbg_panic();
                    133:        }
                    134:        if (ABUF_ROK(buf)) {
                    135:                /*
1.23      ratchov   136:                 * XXX: we should call abort(), here.
1.17      ratchov   137:                 * However, poll() doesn't seem to return POLLHUP,
                    138:                 * so the reader is never destroyed; instead it appears
                    139:                 * as blocked. Fix file_poll(), if fixable, and add
                    140:                 * a call to abord() here.
                    141:                 */
                    142:                if (debug_level >= 3) {
                    143:                        abuf_dbg(buf);
                    144:                        dbg_puts(": deleting non-empty buffer, used = ");
                    145:                        dbg_putu(buf->used);
                    146:                        dbg_puts("\n");
                    147:                }
                    148:        }
                    149: #endif
1.1       ratchov   150:        free(buf);
1.9       ratchov   151: }
                    152:
                    153: /*
1.13      ratchov   154:  * Clear buffer contents.
1.9       ratchov   155:  */
                    156: void
                    157: abuf_clear(struct abuf *buf)
                    158: {
1.17      ratchov   159: #ifdef DEBUG
                    160:        if (debug_level >= 3) {
                    161:                abuf_dbg(buf);
                    162:                dbg_puts(": cleared\n");
                    163:        }
                    164: #endif
1.9       ratchov   165:        buf->used = 0;
                    166:        buf->start = 0;
1.1       ratchov   167: }
                    168:
                    169: /*
                    170:  * Get a pointer to the readable block at the given offset.
                    171:  */
                    172: unsigned char *
1.24      ratchov   173: abuf_rgetblk(struct abuf *buf, unsigned int *rsize, unsigned int ofs)
1.1       ratchov   174: {
1.24      ratchov   175:        unsigned int count, start, used;
1.1       ratchov   176:
                    177:        start = buf->start + ofs;
                    178:        used = buf->used - ofs;
1.6       ratchov   179:        if (start >= buf->len)
                    180:                start -= buf->len;
1.17      ratchov   181: #ifdef DEBUG
                    182:        if (start >= buf->len || used > buf->used) {
                    183:                abuf_dump(buf);
                    184:                dbg_puts(": rgetblk: bad ofs = ");
                    185:                dbg_putu(ofs);
                    186:                dbg_puts("\n");
                    187:                dbg_panic();
                    188:        }
                    189: #endif
1.1       ratchov   190:        count = buf->len - start;
                    191:        if (count > used)
                    192:                count = used;
                    193:        *rsize = count;
1.21      ratchov   194:        return (unsigned char *)buf + sizeof(struct abuf) + start * buf->bpf;
1.3       ratchov   195: }
                    196:
                    197: /*
1.13      ratchov   198:  * Discard the block at the start postion.
1.3       ratchov   199:  */
                    200: void
1.24      ratchov   201: abuf_rdiscard(struct abuf *buf, unsigned int count)
1.3       ratchov   202: {
1.17      ratchov   203: #ifdef DEBUG
                    204:        if (count > buf->used) {
                    205:                abuf_dump(buf);
                    206:                dbg_puts(": rdiscard: bad count = ");
                    207:                dbg_putu(count);
                    208:                dbg_puts("\n");
                    209:                dbg_panic();
                    210:        }
1.22      ratchov   211:        if (debug_level >= 4) {
                    212:                abuf_dbg(buf);
                    213:                dbg_puts(": discard(");
                    214:                dbg_putu(count);
                    215:                dbg_puts(")\n");
                    216:        }
1.17      ratchov   217: #endif
1.3       ratchov   218:        buf->used -= count;
                    219:        buf->start += count;
                    220:        if (buf->start >= buf->len)
                    221:                buf->start -= buf->len;
                    222: }
                    223:
                    224: /*
1.13      ratchov   225:  * Commit the data written at the end postion.
1.3       ratchov   226:  */
                    227: void
1.24      ratchov   228: abuf_wcommit(struct abuf *buf, unsigned int count)
1.3       ratchov   229: {
1.17      ratchov   230: #ifdef DEBUG
                    231:        if (count > (buf->len - buf->used)) {
                    232:                abuf_dump(buf);
                    233:                dbg_puts(": rdiscard: bad count = ");
                    234:                dbg_putu(count);
                    235:                dbg_puts("\n");
                    236:                dbg_panic();
1.22      ratchov   237:        }
                    238:        if (debug_level >= 4) {
                    239:                abuf_dbg(buf);
                    240:                dbg_puts(": commit(");
                    241:                dbg_putu(count);
                    242:                dbg_puts(")\n");
1.17      ratchov   243:        }
                    244: #endif
1.3       ratchov   245:        buf->used += count;
1.1       ratchov   246: }
                    247:
                    248: /*
                    249:  * Get a pointer to the writable block at offset ofs.
                    250:  */
                    251: unsigned char *
1.24      ratchov   252: abuf_wgetblk(struct abuf *buf, unsigned int *rsize, unsigned int ofs)
1.1       ratchov   253: {
1.24      ratchov   254:        unsigned int end, avail, count;
1.1       ratchov   255:
                    256:
                    257:        end = buf->start + buf->used + ofs;
                    258:        if (end >= buf->len)
                    259:                end -= buf->len;
1.17      ratchov   260: #ifdef DEBUG
                    261:        if (end >= buf->len) {
                    262:                abuf_dump(buf);
1.18      ratchov   263:                dbg_puts(": wgetblk: bad ofs = ");
1.17      ratchov   264:                dbg_putu(ofs);
                    265:                dbg_puts("\n");
                    266:                dbg_panic();
                    267:        }
                    268: #endif
1.1       ratchov   269:        avail = buf->len - (buf->used + ofs);
                    270:        count = buf->len - end;
                    271:        if (count > avail)
                    272:                        count = avail;
                    273:        *rsize = count;
1.21      ratchov   274:        return (unsigned char *)buf + sizeof(struct abuf) + end * buf->bpf;
1.1       ratchov   275: }
                    276:
                    277: /*
1.13      ratchov   278:  * Flush buffer either by dropping samples or by calling the aproc
                    279:  * call-back to consume data. Return 0 if blocked, 1 otherwise.
1.4       ratchov   280:  */
                    281: int
                    282: abuf_flush_do(struct abuf *buf)
                    283: {
                    284:        struct aproc *p;
                    285:
1.21      ratchov   286:        p = buf->rproc;
                    287:        if (!p)
                    288:                return 0;
1.20      ratchov   289: #ifdef DEBUG
1.21      ratchov   290:        if (debug_level >= 4) {
                    291:                aproc_dbg(p);
                    292:                dbg_puts(": in\n");
                    293:        }
1.20      ratchov   294: #endif
1.21      ratchov   295:        return p->ops->in(p, buf);
1.4       ratchov   296: }
                    297:
                    298: /*
1.13      ratchov   299:  * Fill the buffer either by generating silence or by calling the aproc
                    300:  * call-back to provide data. Return 0 if blocked, 1 otherwise.
1.4       ratchov   301:  */
                    302: int
                    303: abuf_fill_do(struct abuf *buf)
                    304: {
                    305:        struct aproc *p;
                    306:
1.21      ratchov   307:        p = buf->wproc;
                    308:        if (!p)
                    309:                return 0;
1.20      ratchov   310: #ifdef DEBUG
1.21      ratchov   311:        if (debug_level >= 4) {
                    312:                aproc_dbg(p);
                    313:                dbg_puts(": out\n");
                    314:        }
1.20      ratchov   315: #endif
1.21      ratchov   316:        return p->ops->out(p, buf);
1.7       ratchov   317: }
                    318:
                    319: /*
                    320:  * Notify the reader that there will be no more input (producer
1.13      ratchov   321:  * disappeared) and destroy the buffer.
1.7       ratchov   322:  */
                    323: void
                    324: abuf_eof_do(struct abuf *buf)
                    325: {
                    326:        struct aproc *p;
                    327:
                    328:        p = buf->rproc;
                    329:        if (p) {
                    330:                buf->rproc = NULL;
                    331:                LIST_REMOVE(buf, ient);
                    332:                buf->inuse++;
1.17      ratchov   333: #ifdef DEBUG
                    334:                if (debug_level >= 4) {
                    335:                        aproc_dbg(p);
                    336:                        dbg_puts(": eof\n");
                    337:                }
                    338: #endif
1.7       ratchov   339:                p->ops->eof(p, buf);
                    340:                buf->inuse--;
1.15      ratchov   341:        }
1.7       ratchov   342:        abuf_del(buf);
                    343: }
                    344:
                    345: /*
                    346:  * Notify the writer that the buffer has no more consumer,
1.13      ratchov   347:  * and destroy the buffer.
1.7       ratchov   348:  */
                    349: void
                    350: abuf_hup_do(struct abuf *buf)
                    351: {
                    352:        struct aproc *p;
                    353:
                    354:        if (ABUF_ROK(buf)) {
1.17      ratchov   355: #ifdef DEBUG
                    356:                if (debug_level >= 3) {
                    357:                        abuf_dbg(buf);
                    358:                        dbg_puts(": hup: lost ");
                    359:                        dbg_putu(buf->used);
                    360:                        dbg_puts(" bytes\n");
                    361:                }
                    362: #endif
1.7       ratchov   363:                buf->used = 0;
                    364:        }
                    365:        p = buf->wproc;
                    366:        if (p != NULL) {
                    367:                buf->wproc = NULL;
                    368:                LIST_REMOVE(buf, oent);
                    369:                buf->inuse++;
1.17      ratchov   370: #ifdef DEBUG
                    371:                if (debug_level >= 3) {
                    372:                        aproc_dbg(p);
                    373:                        dbg_puts(": hup\n");
                    374:                }
                    375: #endif
1.7       ratchov   376:                p->ops->hup(p, buf);
                    377:                buf->inuse--;
1.15      ratchov   378:        }
1.7       ratchov   379:        abuf_del(buf);
                    380: }
                    381:
                    382: /*
                    383:  * Notify the read end of the buffer that there is input available
                    384:  * and that data can be processed again.
                    385:  */
                    386: int
                    387: abuf_flush(struct abuf *buf)
1.10      ratchov   388: {
1.7       ratchov   389:        if (buf->inuse) {
1.17      ratchov   390: #ifdef DEBUG
                    391:                if (debug_level >= 4) {
                    392:                        abuf_dbg(buf);
                    393:                        dbg_puts(": flush blocked (inuse)\n");
                    394:                }
                    395: #endif
1.7       ratchov   396:        } else {
                    397:                buf->inuse++;
                    398:                for (;;) {
                    399:                        if (!abuf_flush_do(buf))
                    400:                                break;
                    401:                }
                    402:                buf->inuse--;
                    403:                if (ABUF_HUP(buf)) {
                    404:                        abuf_hup_do(buf);
                    405:                        return 0;
                    406:                }
1.4       ratchov   407:        }
                    408:        return 1;
                    409: }
                    410:
                    411: /*
1.1       ratchov   412:  * Notify the write end of the buffer that there is room and data can be
                    413:  * written again. This routine can only be called from the out()
                    414:  * call-back of the reader.
                    415:  *
1.7       ratchov   416:  * Return 1 if the buffer was filled, and 0 if eof condition occured. The
1.13      ratchov   417:  * reader must detach the buffer on EOF condition, since its aproc->eof()
1.7       ratchov   418:  * call-back will never be called.
1.1       ratchov   419:  */
1.7       ratchov   420: int
1.1       ratchov   421: abuf_fill(struct abuf *buf)
                    422: {
1.7       ratchov   423:        if (buf->inuse) {
1.17      ratchov   424: #ifdef DEBUG
                    425:                if (debug_level >= 4) {
                    426:                        abuf_dbg(buf);
                    427:                        dbg_puts(": fill blocked (inuse)\n");
                    428:                }
                    429: #endif
1.7       ratchov   430:        } else {
                    431:                buf->inuse++;
                    432:                for (;;) {
                    433:                        if (!abuf_fill_do(buf))
                    434:                                break;
                    435:                }
                    436:                buf->inuse--;
                    437:                if (ABUF_EOF(buf)) {
                    438:                        abuf_eof_do(buf);
                    439:                        return 0;
                    440:                }
1.1       ratchov   441:        }
1.7       ratchov   442:        return 1;
1.1       ratchov   443: }
                    444:
                    445: /*
                    446:  * Run a read/write loop on the buffer until either the reader or the
1.13      ratchov   447:  * writer blocks, or until the buffer reaches eofs. We can not get hup here,
1.1       ratchov   448:  * since hup() is only called from terminal nodes, from the main loop.
                    449:  *
                    450:  * NOTE: The buffer may disappear (ie. be free()ed) if eof is reached, so
                    451:  * do not keep references to the buffer or to its writer or reader.
                    452:  */
                    453: void
                    454: abuf_run(struct abuf *buf)
                    455: {
                    456:        int canfill = 1, canflush = 1;
                    457:
1.7       ratchov   458:        if (buf->inuse) {
1.17      ratchov   459: #ifdef DEBUG
                    460:                if (debug_level >= 4) {
                    461:                        abuf_dbg(buf);
                    462:                        dbg_puts(": run blocked (inuse)\n");
                    463:                }
                    464: #endif
1.7       ratchov   465:                return;
                    466:        }
                    467:        buf->inuse++;
1.1       ratchov   468:        for (;;) {
1.7       ratchov   469:                if (canfill) {
                    470:                        if (!abuf_fill_do(buf))
                    471:                                canfill = 0;
                    472:                        else
                    473:                                canflush = 1;
                    474:                } else if (canflush) {
                    475:                        if (!abuf_flush_do(buf))
                    476:                                canflush = 0;
                    477:                        else
                    478:                                canfill = 1;
1.1       ratchov   479:                } else
1.7       ratchov   480:                        break;
                    481:        }
                    482:        buf->inuse--;
                    483:        if (ABUF_EOF(buf)) {
                    484:                abuf_eof_do(buf);
                    485:                return;
                    486:        }
                    487:        if (ABUF_HUP(buf)) {
                    488:                abuf_hup_do(buf);
                    489:                return;
1.1       ratchov   490:        }
                    491: }
                    492:
                    493: /*
                    494:  * Notify the reader that there will be no more input (producer
                    495:  * disappeared). The buffer is flushed and eof() is called only if all
                    496:  * data is flushed.
                    497:  */
                    498: void
                    499: abuf_eof(struct abuf *buf)
                    500: {
1.17      ratchov   501: #ifdef DEBUG
                    502:        if (debug_level >= 3) {
                    503:                abuf_dbg(buf);
                    504:                dbg_puts(": eof requested\n");
                    505:        }
                    506:        if (buf->wproc == NULL) {
                    507:                abuf_dbg(buf);
                    508:                dbg_puts(": eof, no writer\n");
                    509:                dbg_panic();
                    510:        }
                    511: #endif
1.7       ratchov   512:        LIST_REMOVE(buf, oent);
1.1       ratchov   513:        buf->wproc = NULL;
                    514:        if (buf->rproc != NULL) {
1.7       ratchov   515:                if (!abuf_flush(buf))
1.10      ratchov   516:                        return;
1.1       ratchov   517:                if (ABUF_ROK(buf)) {
                    518:                        /*
                    519:                         * Could not flush everything, the reader will
                    520:                         * have a chance to delete the abuf later.
                    521:                         */
1.17      ratchov   522: #ifdef DEBUG
                    523:                        if (debug_level >= 3) {
                    524:                                abuf_dbg(buf);
                    525:                                dbg_puts(": eof, blocked (drain)\n");
                    526:                        }
                    527: #endif
1.1       ratchov   528:                        return;
                    529:                }
                    530:        }
1.7       ratchov   531:        if (buf->inuse) {
1.17      ratchov   532: #ifdef DEBUG
                    533:                if (debug_level >= 3) {
                    534:                        abuf_dbg(buf);
                    535:                        dbg_puts(": eof, blocked (inuse)\n");
                    536:                }
                    537: #endif
1.7       ratchov   538:                return;
                    539:        }
                    540:        abuf_eof_do(buf);
1.1       ratchov   541: }
                    542:
                    543: /*
                    544:  * Notify the writer that the buffer has no more consumer,
                    545:  * and that no more data will accepted.
                    546:  */
                    547: void
                    548: abuf_hup(struct abuf *buf)
                    549: {
1.17      ratchov   550: #ifdef DEBUG
                    551:        if (debug_level >= 3) {
                    552:                abuf_dbg(buf);
                    553:                dbg_puts(": hup requested\n");
                    554:        }
                    555:        if (buf->rproc == NULL) {
                    556:                abuf_dbg(buf);
                    557:                dbg_puts(": hup, no reader\n");
                    558:                dbg_panic();
                    559:        }
                    560: #endif
1.1       ratchov   561:        buf->rproc = NULL;
1.7       ratchov   562:        LIST_REMOVE(buf, ient);
1.1       ratchov   563:        if (buf->wproc != NULL) {
1.7       ratchov   564:                if (buf->inuse) {
1.17      ratchov   565: #ifdef DEBUG
                    566:                        if (debug_level >= 3) {
                    567:                                abuf_dbg(buf);
                    568:                                dbg_puts(": eof, blocked (inuse)\n");
                    569:                        }
                    570: #endif
1.7       ratchov   571:                        return;
1.1       ratchov   572:                }
                    573:        }
1.7       ratchov   574:        abuf_hup_do(buf);
                    575: }
                    576:
                    577: /*
                    578:  * Notify the reader of the change of its real-time position
                    579:  */
                    580: void
                    581: abuf_ipos(struct abuf *buf, int delta)
                    582: {
                    583:        struct aproc *p = buf->rproc;
                    584:
                    585:        if (p && p->ops->ipos) {
                    586:                buf->inuse++;
1.17      ratchov   587: #ifdef DEBUG
                    588:                if (debug_level >= 4) {
                    589:                        aproc_dbg(p);
                    590:                        dbg_puts(": ipos delta = ");
                    591:                        dbg_puti(delta);
                    592:                        dbg_puts("\n");
                    593:                }
                    594: #endif
1.10      ratchov   595:                p->ops->ipos(p, buf, delta);
1.7       ratchov   596:                buf->inuse--;
                    597:        }
                    598:        if (ABUF_HUP(buf))
                    599:                abuf_hup_do(buf);
                    600: }
                    601:
                    602: /*
                    603:  * Notify the writer of the change of its real-time position
                    604:  */
                    605: void
                    606: abuf_opos(struct abuf *buf, int delta)
                    607: {
                    608:        struct aproc *p = buf->wproc;
1.10      ratchov   609:
1.7       ratchov   610:        if (p && p->ops->opos) {
                    611:                buf->inuse++;
1.17      ratchov   612: #ifdef DEBUG
                    613:                if (debug_level >= 4) {
                    614:                        aproc_dbg(p);
                    615:                        dbg_puts(": opos delta = ");
                    616:                        dbg_puti(delta);
                    617:                        dbg_puts("\n");
                    618:                }
                    619: #endif
1.7       ratchov   620:                p->ops->opos(p, buf, delta);
                    621:                buf->inuse--;
                    622:        }
                    623:        if (ABUF_HUP(buf))
                    624:                abuf_hup_do(buf);
1.1       ratchov   625: }