Index: sys/sys/msgbuf.h =================================================================== RCS file: /dump/FreeBSD-CVS/src/sys/sys/msgbuf.h,v retrieving revision 1.20 diff -u -r1.20 msgbuf.h --- sys/sys/msgbuf.h 28 Mar 2003 02:50:10 -0000 1.20 +++ sys/sys/msgbuf.h 18 May 2003 04:08:51 -0000 @@ -41,16 +41,32 @@ #define MSG_MAGIC 0x063062 u_int msg_magic; int msg_size; /* size of buffer area */ - int msg_bufx; /* write pointer */ - int msg_bufr; /* read pointer */ + int msg_wseq; /* write sequence number */ + int msg_rseq; /* read sequence number */ + int msg_seqmod; /* range for sequence numbers */ char *msg_ptr; /* pointer to buffer */ u_int msg_cksum; /* checksum of contents */ }; +#define MSGBUF_SEQNORM(mbp, seq) ((seq) % (mbp)->msg_seqmod + ((seq) < 0 ? \ + (mbp)->msg_seqmod : 0)) +#define MSGBUF_SEQ_TO_POS(mbp, seq) ((int)((u_int)(seq) % \ + (u_int)(mbp)->msg_size)) +#define MSGBUF_SEQSUB(mbp, seq1, seq2) (MSGBUF_SEQNORM(mbp, (seq1) - (seq2))) + #ifdef _KERNEL extern int msgbuftrigger; extern struct msgbuf *msgbufp; void msgbufinit(void *ptr, int size); +void msgbuf_addchar(struct msgbuf *mbp, int c); +void msgbuf_clear(struct msgbuf *mbp); +void msgbuf_copy(struct msgbuf *src, struct msgbuf *dst); +int msgbuf_getbytes(struct msgbuf *mbp, char *buf, int buflen); +int msgbuf_getchar(struct msgbuf *mbp); +int msgbuf_getcount(struct msgbuf *mbp); +void msgbuf_init(struct msgbuf *mbp, void *ptr, int size); +void msgbuf_reinit(struct msgbuf *mbp, void *ptr, int size); +int msgbuf_peekbytes(struct msgbuf *mbp, char *buf, int buflen, int *seqp); #if !defined(MSGBUF_SIZE) #define MSGBUF_SIZE 32768 Index: sys/conf/files =================================================================== RCS file: /dump/FreeBSD-CVS/src/sys/conf/files,v retrieving revision 1.789 diff -u -r1.789 files --- sys/conf/files 3 May 2003 10:16:55 -0000 1.789 +++ sys/conf/files 18 May 2003 02:01:05 -0000 @@ -1077,6 +1077,7 @@ kern/subr_mbuf.c standard kern/subr_mchain.c optional libmchain kern/subr_module.c standard +kern/subr_msgbuf.c standard kern/subr_param.c standard kern/subr_pcpu.c standard kern/subr_power.c standard Index: sys/kern/subr_log.c =================================================================== RCS file: /dump/FreeBSD-CVS/src/sys/kern/subr_log.c,v retrieving revision 1.55 diff -u -r1.55 subr_log.c --- sys/kern/subr_log.c 3 Mar 2003 12:15:51 -0000 1.55 +++ sys/kern/subr_log.c 18 May 2003 02:24:13 -0000 @@ -120,11 +120,12 @@ static int logread(dev_t dev, struct uio *uio, int flag) { + char buf[128]; struct msgbuf *mbp = msgbufp; int error = 0, l, s; s = splhigh(); - while (mbp->msg_bufr == mbp->msg_bufx) { + while (msgbuf_getcount(mbp) == 0) { if (flag & IO_NDELAY) { splx(s); return (EWOULDBLOCK); @@ -139,19 +140,13 @@ logsoftc.sc_state &= ~LOG_RDWAIT; while (uio->uio_resid > 0) { - l = mbp->msg_bufx - mbp->msg_bufr; - if (l < 0) - l = mbp->msg_size - mbp->msg_bufr; - l = imin(l, uio->uio_resid); + l = imin(sizeof(buf), uio->uio_resid); + l = msgbuf_getbytes(mbp, buf, l); if (l == 0) break; - error = uiomove((char *)msgbufp->msg_ptr + mbp->msg_bufr, - l, uio); + error = uiomove(buf, l, uio); if (error) break; - mbp->msg_bufr += l; - if (mbp->msg_bufr >= mbp->msg_size) - mbp->msg_bufr = 0; } return (error); } @@ -166,7 +161,7 @@ s = splhigh(); if (events & (POLLIN | POLLRDNORM)) { - if (msgbufp->msg_bufr != msgbufp->msg_bufx) + if (msgbuf_getcount(msgbufp) > 0) revents |= events & (POLLIN | POLLRDNORM); else selrecord(td, &logsoftc.sc_selp); @@ -202,18 +197,12 @@ static int logioctl(dev_t dev, u_long com, caddr_t data, int flag, struct thread *td) { - int l, s; switch (com) { /* return number of characters immediately available */ case FIONREAD: - s = splhigh(); - l = msgbufp->msg_bufx - msgbufp->msg_bufr; - splx(s); - if (l < 0) - l += msgbufp->msg_size; - *(int *)data = l; + *(int *)data = msgbuf_getcount(msgbufp); break; case FIONBIO: Index: sys/kern/subr_prf.c =================================================================== RCS file: /dump/FreeBSD-CVS/src/sys/kern/subr_prf.c,v retrieving revision 1.100 diff -u -r1.100 subr_prf.c --- sys/kern/subr_prf.c 17 Apr 2003 22:30:43 -0000 1.100 +++ sys/kern/subr_prf.c 18 May 2003 05:23:50 -0000 @@ -71,6 +71,8 @@ #define TOTTY 0x02 #define TOLOG 0x04 +#define CONSMSGBUF_SIZE 8192 /* size of console tty buffer */ + /* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */ #define MAXNBUF (sizeof(intmax_t) * NBBY + 1) @@ -88,11 +90,13 @@ extern int log_open; struct tty *constty; /* pointer to console "window" tty */ +static char consbuf[CONSMSGBUF_SIZE]; /* buffer area for consmsgbuf */ +static struct msgbuf consmsgbuf; /* message buffer for console tty */ +static struct callout conscallout; /* callout for printing console msgs */ -static void (*v_putc)(int) = cnputc; /* routine to putc on virtual console */ +static void consmsgbufstart(void *unused); +static void consttytimeout(void *arg); static void msglogchar(int c, int pri); -static void msgaddchar(int c, void *dummy); -static u_int msgbufcksum(char *cp, size_t size, u_int cksum); static void putchar(int ch, void *arg); static char *ksprintn(char *nbuf, uintmax_t num, int base, int *len); static void snprintf_func(int ch, void *arg); @@ -337,21 +341,28 @@ putchar(int c, void *arg) { struct putchar_arg *ap = (struct putchar_arg*) arg; - int flags = ap->flags; struct tty *tp = ap->tty; + int consdirect, flags = ap->flags; + + consdirect = ((flags & TOCONS) && constty == NULL) || !msgbufmapped; + /* Don't use the tty code after a panic or while in ddb. */ if (panicstr) - constty = NULL; - if ((flags & TOCONS) && tp == NULL && constty) { - tp = constty; - flags |= TOTTY; - } - if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 && - (flags & TOCONS) && tp == constty) - constty = NULL; + consdirect = 1; +#ifdef DDB + if (db_active) + consdirect = 1; +#endif + if (consdirect) { + if (c != '\0') + cnputc(c); + } else { + if ((flags & TOTTY) && tp != NULL) + tputchar(c, tp); + if ((flags & TOCONS) && constty != NULL) + msgbuf_addchar(&consmsgbuf, c); + } if ((flags & TOLOG)) msglogchar(c, ap->pri); - if ((flags & TOCONS) && constty == NULL && c != '\0') - (*v_putc)(c); } /* @@ -789,16 +800,16 @@ return; if (pri != -1 && pri != lastpri) { if (dangling) { - msgaddchar('\n', NULL); + msgbuf_addchar(msgbufp, '\n'); dangling = 0; } - msgaddchar('<', NULL); + msgbuf_addchar(msgbufp, '<'); for (p = ksprintn(nbuf, (uintmax_t)pri, 10, NULL); *p;) - msgaddchar(*p--, NULL); - msgaddchar('>', NULL); + msgbuf_addchar(msgbufp, *p--); + msgbuf_addchar(msgbufp, '>'); lastpri = pri; } - msgaddchar(c, NULL); + msgbuf_addchar(msgbufp, c); if (c == '\n') { dangling = 0; lastpri = -1; @@ -807,41 +818,6 @@ } } -/* - * Put char in log buffer - */ -static void -msgaddchar(int c, void *dummy) -{ - struct msgbuf *mbp; - - if (!msgbufmapped) - return; - mbp = msgbufp; - mbp->msg_cksum += (u_char)c - (u_char)mbp->msg_ptr[mbp->msg_bufx]; - mbp->msg_ptr[mbp->msg_bufx++] = c; - if (mbp->msg_bufx >= mbp->msg_size) - mbp->msg_bufx = 0; - /* If the buffer is full, keep the most recent data. */ - if (mbp->msg_bufr == mbp->msg_bufx) { - if (++mbp->msg_bufr >= mbp->msg_size) - mbp->msg_bufr = 0; - } -} - -static void -msgbufcopy(struct msgbuf *oldp) -{ - int pos; - - pos = oldp->msg_bufr; - while (pos != oldp->msg_bufx) { - msglogchar(oldp->msg_ptr[pos], -1); - if (++pos >= oldp->msg_size) - pos = 0; - } -} - void msgbufinit(void *ptr, int size) { @@ -850,39 +826,16 @@ size -= sizeof(*msgbufp); cp = (char *)ptr; - msgbufp = (struct msgbuf *) (cp + size); - if (msgbufp->msg_magic != MSG_MAGIC || msgbufp->msg_size != size || - msgbufp->msg_bufx >= size || msgbufp->msg_bufx < 0 || - msgbufp->msg_bufr >= size || msgbufp->msg_bufr < 0 || - msgbufcksum(cp, size, msgbufp->msg_cksum) != msgbufp->msg_cksum) { - bzero(cp, size); - bzero(msgbufp, sizeof(*msgbufp)); - msgbufp->msg_magic = MSG_MAGIC; - msgbufp->msg_size = size; - } - msgbufp->msg_ptr = cp; + msgbufp = (struct msgbuf *)(cp + size); + msgbuf_reinit(msgbufp, cp, size); if (msgbufmapped && oldp != msgbufp) - msgbufcopy(oldp); + msgbuf_copy(oldp, msgbufp); + if (!msgbufmapped) + msgbuf_init(&consmsgbuf, &consbuf, sizeof(consbuf)); msgbufmapped = 1; oldp = msgbufp; } -static u_int -msgbufcksum(char *cp, size_t size, u_int cksum) -{ - u_int sum; - int i; - - sum = 0; - for (i = 0; i < size; i++) - sum += (u_char)cp[i]; - if (sum != cksum) - printf("msgbuf cksum mismatch (read %x, calc %x)\n", cksum, - sum); - - return (sum); -} - SYSCTL_DECL(_security_bsd); static int unprivileged_read_msgbuf = 1; @@ -894,7 +847,8 @@ static int sysctl_kern_msgbuf(SYSCTL_HANDLER_ARGS) { - int error; + char buf[128]; + int error, len, seq; if (!unprivileged_read_msgbuf) { error = suser(req->td); @@ -902,25 +856,20 @@ return (error); } - /* - * Unwind the buffer, so that it's linear (possibly starting with - * some initial nulls). - */ - error = sysctl_handle_opaque(oidp, msgbufp->msg_ptr + msgbufp->msg_bufx, - msgbufp->msg_size - msgbufp->msg_bufx, req); - if (error) - return (error); - if (msgbufp->msg_bufx > 0) { - error = sysctl_handle_opaque(oidp, msgbufp->msg_ptr, - msgbufp->msg_bufx, req); + /* Read the whole buffer, one chunk at a time. */ + msgbuf_peekbytes(msgbufp, NULL, 0, &seq); + while ((len = msgbuf_peekbytes(msgbufp, buf, sizeof(buf), &seq)) > 0) { + error = sysctl_handle_opaque(oidp, buf, len, req); + if (error) + return (error); } - return (error); + return (0); } SYSCTL_PROC(_kern, OID_AUTO, msgbuf, CTLTYPE_STRING | CTLFLAG_RD, 0, 0, sysctl_kern_msgbuf, "A", "Contents of kernel message buffer"); -static int msgbuf_clear; +static int msgbuf_clearflag; static int sysctl_kern_msgbuf_clear(SYSCTL_HANDLER_ARGS) @@ -928,19 +877,46 @@ int error; error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req); if (!error && req->newptr) { - /* Clear the buffer and reset write pointer */ - bzero(msgbufp->msg_ptr, msgbufp->msg_size); - msgbufp->msg_bufr = msgbufp->msg_bufx = 0; - msgbufp->msg_cksum = 0; - msgbuf_clear = 0; + msgbuf_clear(msgbufp); + msgbuf_clearflag = 0; } return (error); } SYSCTL_PROC(_kern, OID_AUTO, msgbuf_clear, - CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE, &msgbuf_clear, 0, + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_SECURE, &msgbuf_clearflag, 0, sysctl_kern_msgbuf_clear, "I", "Clear kernel message buffer"); +/* Times per second to check for a pending console tty messages. */ +static int constty_wakeups_per_second = 5; +SYSCTL_INT(_kern, OID_AUTO, constty_wakeups_per_second, CTLFLAG_RW, + &constty_wakeups_per_second, 0, ""); + +static void +consttytimeout(void *arg) +{ + int c; + + while ((c = msgbuf_getchar(&consmsgbuf)) != -1) { + if (constty != NULL && tputchar(c, constty) < 0) + constty = NULL; + if (constty == NULL && c != '\0') + cnputc(c); + } + callout_reset(&conscallout, hz / constty_wakeups_per_second, + consttytimeout, NULL); +} + +static void +consmsgbufstart(void *unused) +{ + + callout_init(&conscallout, 0); + consttytimeout(NULL); +} + +SYSINIT(msgbuf, SI_SUB_SOFTINTR, SI_ORDER_ANY, consmsgbufstart, NULL) + #ifdef DDB DB_SHOW_COMMAND(msgbuf, db_show_msgbuf) @@ -952,11 +928,11 @@ return; } db_printf("msgbufp = %p\n", msgbufp); - db_printf("magic = %x, size = %d, r= %d, w = %d, ptr = %p, cksum= %d\n", - msgbufp->msg_magic, msgbufp->msg_size, msgbufp->msg_bufr, - msgbufp->msg_bufx, msgbufp->msg_ptr, msgbufp->msg_cksum); + db_printf("magic = %x, size = %d, r= %u, w = %u, ptr = %p, cksum= %u\n", + msgbufp->msg_magic, msgbufp->msg_size, msgbufp->msg_rseq, + msgbufp->msg_wseq, msgbufp->msg_ptr, msgbufp->msg_cksum); for (i = 0; i < msgbufp->msg_size; i++) { - j = (i + msgbufp->msg_bufr) % msgbufp->msg_size; + j = MSGBUF_SEQ_TO_POS(msgbufp, i + msgbufp->msg_rseq); db_printf("%c", msgbufp->msg_ptr[j]); } db_printf("\n"); Index: sys/kern/subr_msgbuf.c =================================================================== RCS file: sys/kern/subr_msgbuf.c diff -N sys/kern/subr_msgbuf.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/kern/subr_msgbuf.c 18 May 2003 04:29:33 -0000 @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2003 Ian Dowse. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include +#include +#include + +/* Read/write sequence numbers are modulo a multiple of the buffer size. */ +#define SEQMOD(size) ((size) * 16) + +static u_int msgbuf_cksum(struct msgbuf *mbp); + +/* + * Initialize a message buffer of the specified size at the specified + * location. This also zeros the buffer area. + */ +void +msgbuf_init(struct msgbuf *mbp, void *ptr, int size) +{ + + mbp->msg_ptr = ptr; + mbp->msg_size = size; + mbp->msg_seqmod = SEQMOD(size); + msgbuf_clear(mbp); + mbp->msg_magic = MSG_MAGIC; +} + +/* + * Reinitialize a message buffer, retaining its previous contents if + * the size and checksum are correct. If the old contents cannot be + * recovered, the message buffer is cleared. + */ +void +msgbuf_reinit(struct msgbuf *mbp, void *ptr, int size) +{ + u_int cksum; + + if (mbp->msg_magic != MSG_MAGIC || mbp->msg_size != size) { + msgbuf_init(mbp, ptr, size); + return; + } + mbp->msg_seqmod = SEQMOD(size); + mbp->msg_wseq = MSGBUF_SEQNORM(mbp, mbp->msg_wseq); + mbp->msg_rseq = MSGBUF_SEQNORM(mbp, mbp->msg_rseq); + mbp->msg_ptr = ptr; + cksum = msgbuf_cksum(mbp); + if (cksum != mbp->msg_cksum) { + printf("msgbuf cksum mismatch (read %x, calc %x)\n", + mbp->msg_cksum, cksum); + msgbuf_clear(mbp); + } +} + +/* + * Clear the message buffer. + */ +void +msgbuf_clear(struct msgbuf *mbp) +{ + + bzero(mbp->msg_ptr, mbp->msg_size); + mbp->msg_wseq = 0; + mbp->msg_rseq = 0; + mbp->msg_cksum = 0; +} + +/* + * Get a count of the number of unread characters in the message buffer. + */ +int +msgbuf_getcount(struct msgbuf *mbp) +{ + int len; + + len = MSGBUF_SEQSUB(mbp, mbp->msg_wseq, mbp->msg_rseq); + if (len < 0 || len > mbp->msg_size) + len = mbp->msg_size; + return (len); +} + +/* + * Append a character to a message buffer. This function can be + * considered fully reentrant so long as the number of concurrent + * callers is less than the number of characters in the buffer. + * However, the message buffer is only guaranteed to be consistent + * for reading when there are no callers in this function. + */ +void +msgbuf_addchar(struct msgbuf *mbp, int c) +{ + int new_seq, pos, seq; + + do { + seq = mbp->msg_wseq; + new_seq = MSGBUF_SEQNORM(mbp, seq + 1); + } while (atomic_cmpset_rel_int(&mbp->msg_wseq, seq, new_seq) == 0); + pos = MSGBUF_SEQ_TO_POS(mbp, seq); + atomic_add_int(&mbp->msg_cksum, (u_int)(u_char)c - + (u_int)(u_char)mbp->msg_ptr[pos]); + mbp->msg_ptr[pos] = c; +} + +/* + * Read and mark as read a character from a message buffer. + * Returns the character, or -1 if no characters are available. + */ +int +msgbuf_getchar(struct msgbuf *mbp) +{ + int c, len, wseq; + + wseq = mbp->msg_wseq; + len = MSGBUF_SEQSUB(mbp, wseq, mbp->msg_rseq); + if (len == 0) + return (-1); + if (len < 0 || len > mbp->msg_size) + mbp->msg_rseq = MSGBUF_SEQNORM(mbp, wseq - mbp->msg_size); + c = (u_char)mbp->msg_ptr[MSGBUF_SEQ_TO_POS(mbp, mbp->msg_rseq)]; + mbp->msg_rseq = MSGBUF_SEQNORM(mbp, mbp->msg_rseq + 1); + return (c); +} + +/* + * Read and mark as read a number of characters from a message buffer. + * Returns the number of characters that were placed in `buf'. + */ +int +msgbuf_getbytes(struct msgbuf *mbp, char *buf, int buflen) +{ + int len, pos, wseq; + + wseq = mbp->msg_wseq; + len = MSGBUF_SEQSUB(mbp, wseq, mbp->msg_rseq); + if (len == 0) + return (0); + if (len < 0 || len > mbp->msg_size) { + mbp->msg_rseq = MSGBUF_SEQNORM(mbp, wseq - mbp->msg_size); + len = mbp->msg_size; + } + pos = MSGBUF_SEQ_TO_POS(mbp, mbp->msg_rseq); + len = imin(len, mbp->msg_size - pos); + len = imin(len, buflen); + + bcopy(&mbp->msg_ptr[pos], buf, len); + mbp->msg_rseq = MSGBUF_SEQNORM(mbp, mbp->msg_rseq + len); + return (len); +} + +/* + * Peek at the full contents of a message buffer without marking any + * data as read. `seqp' should point to an integer that + * msgbuf_peekbytes() can use to retain state between calls so that + * the whole message buffer can be read in multiple short reads. + * To initialise this variable to the start of the message buffer, + * call msgbuf_peekbytes() with a NULL `buf' parameter. + * + * Returns the number of characters that were placed in `buf'. + */ +int +msgbuf_peekbytes(struct msgbuf *mbp, char *buf, int buflen, int *seqp) +{ + int len, pos, wseq; + + if (buf == NULL) { + /* Just initialise *seqp. */ + *seqp = MSGBUF_SEQNORM(mbp, mbp->msg_wseq - mbp->msg_size); + return (0); + } + + wseq = mbp->msg_wseq; + len = MSGBUF_SEQSUB(mbp, wseq, *seqp); + if (len == 0) + return (0); + if (len < 0 || len > mbp->msg_size) { + *seqp = MSGBUF_SEQNORM(mbp, wseq - mbp->msg_size); + len = mbp->msg_size; + } + pos = MSGBUF_SEQ_TO_POS(mbp, *seqp); + len = imin(len, mbp->msg_size - pos); + len = imin(len, buflen); + bcopy(&mbp->msg_ptr[MSGBUF_SEQ_TO_POS(mbp, *seqp)], buf, len); + *seqp = MSGBUF_SEQNORM(mbp, *seqp + len); + return (len); +} + +/* + * Compute the checksum for the complete message buffer contents. + */ +static u_int +msgbuf_cksum(struct msgbuf *mbp) +{ + u_int sum; + int i; + + sum = 0; + for (i = 0; i < mbp->msg_size; i++) + sum += (u_char)mbp->msg_ptr[i]; + return (sum); +} + +/* + * Copy from one message buffer to another. + */ +void +msgbuf_copy(struct msgbuf *src, struct msgbuf *dst) +{ + int c; + + while ((c = msgbuf_getchar(src)) >= 0) + msgbuf_addchar(dst, c); +} Index: sbin/dmesg/dmesg.c =================================================================== RCS file: /dump/FreeBSD-CVS/src/sbin/dmesg/dmesg.c,v retrieving revision 1.19 diff -u -r1.19 dmesg.c --- sbin/dmesg/dmesg.c 2 May 2003 07:08:52 -0000 1.19 +++ sbin/dmesg/dmesg.c 18 May 2003 04:38:42 -0000 @@ -137,9 +137,7 @@ errx(1, "kvm_read: %s", kvm_geterr(kd)); kvm_close(kd); buflen = cur.msg_size; - bufpos = cur.msg_bufx; - if (bufpos >= buflen) - bufpos = 0; + bufpos = MSGBUF_SEQ_TO_POS(&cur, cur.msg_wseq); } /*