svn commit: r222537 - in head/sys: kern sys

mdf at FreeBSD.org mdf at FreeBSD.org
Tue May 31 21:00:21 UTC 2011


On Tue, May 31, 2011 at 10:29 AM, Kenneth D. Merry <ken at freebsd.org> wrote:
> Author: ken
> Date: Tue May 31 17:29:58 2011
> New Revision: 222537
> URL: http://svn.freebsd.org/changeset/base/222537
>
> Log:
>  Fix apparent garbage in the message buffer.
>
>  While we have had a fix in place (options PRINTF_BUFR_SIZE=128) to fix
>  scrambled console output, the message buffer and syslog were still getting
>  log messages one character at a time.  While all of the characters still
>  made it into the log (courtesy of atomic operations), they were often
>  interleaved when there were multiple threads writing to the buffer at the
>  same time.

This seems to panic my box with "lock "msgbuf" 0xfffffe0127ffffe0
already initialized".

Unfortunately, though I booted with a fresh CURRENT this morning
successfully, both /boot/kernel and /boot/kernel.old give this panic.
To add insult to injury, when the kernel drops into the debugger, my
keyboard input no longer works so I can't get a stack, etc.

So:

1) Is there anything else I can do to help debug this?
2) how can I resurrect this box without a reinstall?

I will try to repro on a virtual machine so I have a snapshot to come back to.

Thanks,
matthew

>  This fixes message buffer accesses to use buffering logic as well, so that
>  strings that are less than PRINTF_BUFR_SIZE will be put into the message
>  buffer atomically.  So now dmesg output should look the same as console
>  output.
>
>  subr_msgbuf.c:                Convert most message buffer calls to use a new spin
>                        lock instead of atomic variables in some places.
>
>                        Add a new routine, msgbuf_addstr(), that adds a
>                        NUL-terminated string to a message buffer.  This
>                        takes a priority argument, which allows us to
>                        eliminate some races (at least in the the string
>                        at a time case) that are present in the
>                        implementation of msglogchar().  (dangling and
>                        lastpri are static variables, and are subject to
>                        races when multiple callers are present.)
>
>                        msgbuf_addstr() also allows the caller to request
>                        that carriage returns be stripped out of the
>                        string.  This matches the behavior of msglogchar(),
>                        but in testing so far it doesn't appear that any
>                        newlines are being stripped out.  So the carriage
>                        return removal functionality may be a candidate
>                        for removal later on if further analysis shows
>                        that it isn't necessary.
>
>  subr_prf.c:           Add a new msglogstr() routine that calls
>                        msgbuf_logstr().
>
>                        Rename putcons() to putbuf().  This now handles
>                        buffered output to the message log as well as
>                        the console.  Also, remove the logic in putcons()
>                        (now putbuf()) that added a carriage return before
>                        a newline.  The console path was the only path that
>                        needed it, and cnputc() (called by cnputs())
>                        already adds a carriage return.  So this
>                        duplication resulted in kernel-generated console
>                        output lines ending in '\r''\r''\n'.
>
>                        Refactor putchar() to handle the new buffering
>                        scheme.
>
>                        Add buffering to log().
>
>                        Change log_console() to use msglogstr() instead of
>                        msglogchar().  Don't add extra newlines by default
>                        in log_console().  Hide that behavior behind a
>                        tunable/sysctl (kern.log_console_add_linefeed) for
>                        those who would like the old behavior.  The old
>                        behavior led to the insertion of extra newlines
>                        for log output for programs that print out a
>                        string, and then a trailing newline on a separate
>                        write.  (This is visible with dmesg -a.)
>
>  msgbuf.h:             Add a prototype for msgbuf_addstr().
>
>                        Add three new fields to struct msgbuf, msg_needsnl,
>                        msg_lastpri and msg_lock.  The first two are needed
>                        for log message functionality previously handled
>                        by msglogchar().  (Which is still active if
>                        buffering isn't enabled.)
>
>                        Include sys/lock.h and sys/mutex.h for the new
>                        mutex.
>
>  Reviewed by:  gibbs
>
> Modified:
>  head/sys/kern/subr_msgbuf.c
>  head/sys/kern/subr_prf.c
>  head/sys/sys/msgbuf.h
>
> Modified: head/sys/kern/subr_msgbuf.c
> ==============================================================================
> --- head/sys/kern/subr_msgbuf.c Tue May 31 17:24:18 2011        (r222536)
> +++ head/sys/kern/subr_msgbuf.c Tue May 31 17:29:58 2011        (r222537)
> @@ -31,8 +31,16 @@
>
>  #include <sys/param.h>
>  #include <sys/systm.h>
> +#include <sys/lock.h>
> +#include <sys/mutex.h>
>  #include <sys/msgbuf.h>
>
> +/*
> + * Maximum number conversion buffer length: uintmax_t in base 2, plus <>
> + * around the priority, and a terminating NUL.
> + */
> +#define        MAXPRIBUF       (sizeof(intmax_t) * NBBY + 3)
> +
>  /* Read/write sequence numbers are modulo a multiple of the buffer size. */
>  #define SEQMOD(size) ((size) * 16)
>
> @@ -51,6 +59,9 @@ msgbuf_init(struct msgbuf *mbp, void *pt
>        mbp->msg_seqmod = SEQMOD(size);
>        msgbuf_clear(mbp);
>        mbp->msg_magic = MSG_MAGIC;
> +       mbp->msg_lastpri = -1;
> +       mbp->msg_needsnl = 0;
> +       mtx_init(&mbp->msg_lock, "msgbuf", NULL, MTX_SPIN);
>  }
>
>  /*
> @@ -80,6 +91,11 @@ msgbuf_reinit(struct msgbuf *mbp, void *
>                }
>                msgbuf_clear(mbp);
>        }
> +
> +       mbp->msg_lastpri = -1;
> +       /* Assume that the old message buffer didn't end in a newline. */
> +       mbp->msg_needsnl = 1;
> +       mtx_init(&mbp->msg_lock, "msgbuf", NULL, MTX_SPIN);
>  }
>
>  /*
> @@ -110,25 +126,140 @@ msgbuf_getcount(struct msgbuf *mbp)
>  }
>
>  /*
> - * 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.
> + * Add a character into the message buffer, and update the checksum and
> + * sequence number.
> + *
> + * The caller should hold the message buffer spinlock.
> + */
> +static inline void
> +msgbuf_do_addchar(struct msgbuf *mbp, u_int *seq, int c)
> +{
> +       u_int pos;
> +
> +       /* Make sure we properly wrap the sequence number. */
> +       pos = MSGBUF_SEQ_TO_POS(mbp, *seq);
> +
> +       mbp->msg_cksum += (u_int)c -
> +           (u_int)(u_char)mbp->msg_ptr[pos];
> +
> +       mbp->msg_ptr[pos] = c;
> +
> +       *seq = MSGBUF_SEQNORM(mbp, *seq + 1);
> +}
> +
> +/*
> + * Append a character to a message buffer.
>  */
>  void
>  msgbuf_addchar(struct msgbuf *mbp, int c)
>  {
> -       u_int new_seq, pos, seq;
> +       mtx_lock_spin(&mbp->msg_lock);
> +
> +       msgbuf_do_addchar(mbp, &mbp->msg_wseq, c);
> +
> +       mtx_unlock_spin(&mbp->msg_lock);
> +}
> +
> +/*
> + * Append a NUL-terminated string with a priority to a message buffer.
> + * Filter carriage returns if the caller requests it.
> + *
> + * XXX The carriage return filtering behavior is present in the
> + * msglogchar() API, however testing has shown that we don't seem to send
> + * carriage returns down this path.  So do we still need it?
> + */
> +void
> +msgbuf_addstr(struct msgbuf *mbp, int pri, char *str, int filter_cr)
> +{
> +       u_int seq;
> +       size_t len, prefix_len;
> +       char prefix[MAXPRIBUF];
> +       int nl, i;
> +
> +       len = strlen(str);
> +       prefix_len = 0;
> +       nl = 0;
> +
> +       /* If we have a zero-length string, no need to do anything. */
> +       if (len == 0)
> +               return;
> +
> +       mtx_lock_spin(&mbp->msg_lock);
> +
> +       /*
> +        * If this is true, we may need to insert a new priority sequence,
> +        * so prepare the prefix.
> +        */
> +       if (pri != -1)
> +               prefix_len = sprintf(prefix, "<%d>", pri);
> +
> +       /*
> +        * Starting write sequence number.
> +        */
> +       seq = mbp->msg_wseq;
> +
> +       /*
> +        * Whenever there is a change in priority, we have to insert a
> +        * newline, and a priority prefix if the priority is not -1.  Here
> +        * we detect whether there was a priority change, and whether we
> +        * did not end with a newline.  If that is the case, we need to
> +        * insert a newline before this string.
> +        */
> +       if (mbp->msg_lastpri != pri && mbp->msg_needsnl != 0) {
> +
> +               msgbuf_do_addchar(mbp, &seq, '\n');
> +               mbp->msg_needsnl = 0;
> +       }
> +
> +       for (i = 0; i < len; i++) {
> +               /*
> +                * If we just had a newline, and the priority is not -1
> +                * (and therefore prefix_len != 0), then we need a priority
> +                * prefix for this line.
> +                */
> +               if (mbp->msg_needsnl == 0 && prefix_len != 0) {
> +                       int j;
> +
> +                       for (j = 0; j < prefix_len; j++)
> +                               msgbuf_do_addchar(mbp, &seq, prefix[j]);
> +               }
> +
> +               /*
> +                * Don't copy carriage returns if the caller requested
> +                * filtering.
> +                *
> +                * XXX This matches the behavior of msglogchar(), but is it
> +                * necessary?  Testing has shown that we don't seem to get
> +                * carriage returns here.
> +                */
> +               if ((filter_cr != 0) && (str[i] == '\r'))
> +                       continue;
> +
> +               /*
> +                * Clear this flag if we see a newline.  This affects whether
> +                * we need to insert a new prefix or insert a newline later.
> +                */
> +               if (str[i] == '\n')
> +                       mbp->msg_needsnl = 0;
> +               else
> +                       mbp->msg_needsnl = 1;
> +
> +               msgbuf_do_addchar(mbp, &seq, str[i]);
> +       }
> +       /*
> +        * Update the write sequence number for the actual number of
> +        * characters we put in the message buffer.  (Depends on whether
> +        * carriage returns are filtered.)
> +        */
> +       mbp->msg_wseq = seq;
> +
> +       /*
> +        * Set the last priority.
> +        */
> +       mbp->msg_lastpri = pri;
> +
> +       mtx_unlock_spin(&mbp->msg_lock);
>
> -       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;
>  }
>
>  /*
> @@ -141,14 +272,21 @@ msgbuf_getchar(struct msgbuf *mbp)
>        u_int len, wseq;
>        int c;
>
> +       mtx_lock_spin(&mbp->msg_lock);
> +
>        wseq = mbp->msg_wseq;
>        len = MSGBUF_SEQSUB(mbp, wseq, mbp->msg_rseq);
> -       if (len == 0)
> +       if (len == 0) {
> +               mtx_unlock_spin(&mbp->msg_lock);
>                return (-1);
> +       }
>        if (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);
> +
> +       mtx_unlock_spin(&mbp->msg_lock);
> +
>        return (c);
>  }
>
> @@ -161,10 +299,14 @@ msgbuf_getbytes(struct msgbuf *mbp, char
>  {
>        u_int len, pos, wseq;
>
> +       mtx_lock_spin(&mbp->msg_lock);
> +
>        wseq = mbp->msg_wseq;
>        len = MSGBUF_SEQSUB(mbp, wseq, mbp->msg_rseq);
> -       if (len == 0)
> +       if (len == 0) {
> +               mtx_unlock_spin(&mbp->msg_lock);
>                return (0);
> +       }
>        if (len > mbp->msg_size) {
>                mbp->msg_rseq = MSGBUF_SEQNORM(mbp, wseq - mbp->msg_size);
>                len = mbp->msg_size;
> @@ -175,6 +317,9 @@ msgbuf_getbytes(struct msgbuf *mbp, char
>
>        bcopy(&mbp->msg_ptr[pos], buf, len);
>        mbp->msg_rseq = MSGBUF_SEQNORM(mbp, mbp->msg_rseq + len);
> +
> +       mtx_unlock_spin(&mbp->msg_lock);
> +
>        return (len);
>  }
>
> @@ -193,16 +338,21 @@ msgbuf_peekbytes(struct msgbuf *mbp, cha
>  {
>        u_int len, pos, wseq;
>
> +       mtx_lock_spin(&mbp->msg_lock);
> +
>        if (buf == NULL) {
>                /* Just initialise *seqp. */
>                *seqp = MSGBUF_SEQNORM(mbp, mbp->msg_wseq - mbp->msg_size);
> +               mtx_unlock_spin(&mbp->msg_lock);
>                return (0);
>        }
>
>        wseq = mbp->msg_wseq;
>        len = MSGBUF_SEQSUB(mbp, wseq, *seqp);
> -       if (len == 0)
> +       if (len == 0) {
> +               mtx_unlock_spin(&mbp->msg_lock);
>                return (0);
> +       }
>        if (len > mbp->msg_size) {
>                *seqp = MSGBUF_SEQNORM(mbp, wseq - mbp->msg_size);
>                len = mbp->msg_size;
> @@ -212,6 +362,9 @@ msgbuf_peekbytes(struct msgbuf *mbp, cha
>        len = min(len, (u_int)buflen);
>        bcopy(&mbp->msg_ptr[MSGBUF_SEQ_TO_POS(mbp, *seqp)], buf, len);
>        *seqp = MSGBUF_SEQNORM(mbp, *seqp + len);
> +
> +       mtx_unlock_spin(&mbp->msg_lock);
> +
>        return (len);
>  }
>
>
> Modified: head/sys/kern/subr_prf.c
> ==============================================================================
> --- head/sys/kern/subr_prf.c    Tue May 31 17:24:18 2011        (r222536)
> +++ head/sys/kern/subr_prf.c    Tue May 31 17:29:58 2011        (r222537)
> @@ -94,6 +94,7 @@ struct snprintf_arg {
>  extern int log_open;
>
>  static void  msglogchar(int c, int pri);
> +static void  msglogstr(char *str, int pri, int filter_cr);
>  static void  putchar(int ch, void *arg);
>  static char *ksprintn(char *nbuf, uintmax_t num, int base, int *len, int upper);
>  static void  snprintf_func(int ch, void *arg);
> @@ -106,6 +107,14 @@ TUNABLE_INT("kern.log_console_output", &
>  SYSCTL_INT(_kern, OID_AUTO, log_console_output, CTLFLAG_RW,
>     &log_console_output, 0, "Duplicate console output to the syslog.");
>
> +/*
> + * See the comment in log_console() below for more explanation of this.
> + */
> +static int log_console_add_linefeed = 0;
> +TUNABLE_INT("kern.log_console_add_linefeed", &log_console_add_linefeed);
> +SYSCTL_INT(_kern, OID_AUTO, log_console_add_linefeed, CTLFLAG_RW,
> +    &log_console_add_linefeed, 0, "log_console() adds extra newlines.");
> +
>  static int     always_console_output = 0;
>  TUNABLE_INT("kern.always_console_output", &always_console_output);
>  SYSCTL_INT(_kern, OID_AUTO, always_console_output, CTLFLAG_RW,
> @@ -240,16 +249,37 @@ log(int level, const char *fmt, ...)
>  {
>        va_list ap;
>        struct putchar_arg pca;
> +#ifdef PRINTF_BUFR_SIZE
> +       char bufr[PRINTF_BUFR_SIZE];
> +#endif
>
>        pca.tty = NULL;
>        pca.pri = level;
>        pca.flags = log_open ? TOLOG : TOCONS;
> +#ifdef PRINTF_BUFR_SIZE
> +       pca.p_bufr = bufr;
> +       pca.p_next = pca.p_bufr;
> +       pca.n_bufr = sizeof(bufr);
> +       pca.remain = sizeof(bufr);
> +       *pca.p_next = '\0';
> +#else
>        pca.p_bufr = NULL;
> +#endif
>
>        va_start(ap, fmt);
>        kvprintf(fmt, putchar, &pca, 10, ap);
>        va_end(ap);
>
> +#ifdef PRINTF_BUFR_SIZE
> +       /* Write any buffered console/log output: */
> +       if (*pca.p_bufr != '\0') {
> +               if (pca.flags & TOLOG)
> +                       msglogstr(pca.p_bufr, level, /*filter_cr*/1);
> +
> +               if (pca.flags & TOCONS)
> +                       cnputs(pca.p_bufr);
> +       }
> +#endif
>        msgbuftrigger = 1;
>  }
>
> @@ -258,7 +288,7 @@ log(int level, const char *fmt, ...)
>  void
>  log_console(struct uio *uio)
>  {
> -       int c, i, error, nl;
> +       int c, error, nl;
>        char *consbuffer;
>        int pri;
>
> @@ -271,20 +301,48 @@ log_console(struct uio *uio)
>
>        nl = 0;
>        while (uio->uio_resid > 0) {
> -               c = imin(uio->uio_resid, CONSCHUNK);
> +               c = imin(uio->uio_resid, CONSCHUNK - 1);
>                error = uiomove(consbuffer, c, uio);
>                if (error != 0)
>                        break;
> -               for (i = 0; i < c; i++) {
> -                       msglogchar(consbuffer[i], pri);
> -                       if (consbuffer[i] == '\n')
> -                               nl = 1;
> -                       else
> -                               nl = 0;
> -               }
> +               /* Make sure we're NUL-terminated */
> +               consbuffer[c] = '\0';
> +               if (consbuffer[c - 1] == '\n')
> +                       nl = 1;
> +               else
> +                       nl = 0;
> +               msglogstr(consbuffer, pri, /*filter_cr*/ 1);
> +       }
> +       /*
> +        * The previous behavior in log_console() is preserved when
> +        * log_console_add_linefeed is non-zero.  For that behavior, if an
> +        * individual console write came in that was not terminated with a
> +        * line feed, it would add a line feed.
> +        *
> +        * This results in different data in the message buffer than
> +        * appears on the system console (which doesn't add extra line feed
> +        * characters).
> +        *
> +        * A number of programs and rc scripts write a line feed, or a period
> +        * and a line feed when they have completed their operation.  On
> +        * the console, this looks seamless, but when displayed with
> +        * 'dmesg -a', you wind up with output that looks like this:
> +        *
> +        * Updating motd:
> +        * .
> +        *
> +        * On the console, it looks like this:
> +        * Updating motd:.
> +        *
> +        * We could add logic to detect that situation, or just not insert
> +        * the extra newlines.  Set the kern.log_console_add_linefeed
> +        * sysctl/tunable variable to get the old behavior.
> +        */
> +       if (!nl && log_console_add_linefeed) {
> +               consbuffer[0] = '\n';
> +               consbuffer[1] = '\0';
> +               msglogstr(consbuffer, pri, /*filter_cr*/ 1);
>        }
> -       if (!nl)
> -               msglogchar('\n', pri);
>        msgbuftrigger = 1;
>        free(uio, M_IOV);
>        free(consbuffer, M_TEMP);
> @@ -330,9 +388,11 @@ vprintf(const char *fmt, va_list ap)
>        retval = kvprintf(fmt, putchar, &pca, 10, ap);
>
>  #ifdef PRINTF_BUFR_SIZE
> -       /* Write any buffered console output: */
> -       if (*pca.p_bufr != '\0')
> +       /* Write any buffered console/log output: */
> +       if (*pca.p_bufr != '\0') {
>                cnputs(pca.p_bufr);
> +               msglogstr(pca.p_bufr, pca.pri, /*filter_cr*/ 1);
> +       }
>  #endif
>
>        if (!panicstr)
> @@ -342,18 +402,18 @@ vprintf(const char *fmt, va_list ap)
>  }
>
>  static void
> -putcons(int c, struct putchar_arg *ap)
> +putbuf(int c, struct putchar_arg *ap)
>  {
>        /* Check if no console output buffer was provided. */
> -       if (ap->p_bufr == NULL)
> +       if (ap->p_bufr == NULL) {
>                /* Output direct to the console. */
> -               cnputc(c);
> -       else {
> +               if (ap->flags & TOCONS)
> +                       cnputc(c);
> +
> +               if (ap->flags & TOLOG)
> +                       msglogchar(c, ap->pri);
> +       } else {
>                /* Buffer the character: */
> -               if (c == '\n') {
> -                       *ap->p_next++ = '\r';
> -                       ap->remain--;
> -               }
>                *ap->p_next++ = c;
>                ap->remain--;
>
> @@ -361,12 +421,35 @@ putcons(int c, struct putchar_arg *ap)
>                *ap->p_next = '\0';
>
>                /* Check if the buffer needs to be flushed. */
> -               if (ap->remain < 3 || c == '\n') {
> -                       cnputs(ap->p_bufr);
> +               if (ap->remain == 2 || c == '\n') {
> +
> +                       if (ap->flags & TOLOG)
> +                               msglogstr(ap->p_bufr, ap->pri, /*filter_cr*/1);
> +
> +                       if (ap->flags & TOCONS) {
> +                               if ((panicstr == NULL) && (constty != NULL))
> +                                       msgbuf_addstr(&consmsgbuf, -1,
> +                                           ap->p_bufr, /*filter_cr*/ 0);
> +
> +                               if ((constty == NULL) ||(always_console_output))
> +                                       cnputs(ap->p_bufr);
> +                       }
> +
>                        ap->p_next = ap->p_bufr;
>                        ap->remain = ap->n_bufr;
>                        *ap->p_next = '\0';
>                }
> +
> +               /*
> +                * Since we fill the buffer up one character at a time,
> +                * this should not happen.  We should always catch it when
> +                * ap->remain == 2 (if not sooner due to a newline), flush
> +                * the buffer and move on.  One way this could happen is
> +                * if someone sets PRINTF_BUFR_SIZE to 1 or something
> +                * similarly silly.
> +                */
> +               KASSERT(ap->remain > 2, ("Bad buffer logic, remain = %zd",
> +                   ap->remain));
>        }
>  }
>
> @@ -381,26 +464,25 @@ putchar(int c, void *arg)
>        struct putchar_arg *ap = (struct putchar_arg*) arg;
>        struct tty *tp = ap->tty;
>        int flags = ap->flags;
> +       int putbuf_done = 0;
>
>        /* Don't use the tty code after a panic or while in ddb. */
>        if (kdb_active) {
>                if (c != '\0')
>                        cnputc(c);
> -       } else if (panicstr || ((flags & TOCONS) && constty == NULL)) {
> -               if (c != '\0')
> -                       putcons(c, ap);
>        } else {
> -               if ((flags & TOTTY) && tp != NULL)
> +               if ((panicstr == NULL) && (flags & TOTTY) && (tp != NULL))
>                        tty_putchar(tp, c);
> +
>                if (flags & TOCONS) {
> -                       if (constty != NULL)
> -                               msgbuf_addchar(&consmsgbuf, c);
> -                       if (always_console_output && c != '\0')
> -                               putcons(c, ap);
> +                       putbuf(c, ap);
> +                       putbuf_done = 1;
>                }
>        }
> -       if ((flags & TOLOG))
> -               msglogchar(c, ap->pri);
> +       if ((flags & TOLOG) && (putbuf_done == 0)) {
> +               if (c != '\0')
> +                       putbuf(c, ap);
> +       }
>  }
>
>  /*
> @@ -890,6 +972,15 @@ msglogchar(int c, int pri)
>        }
>  }
>
> +static void
> +msglogstr(char *str, int pri, int filter_cr)
> +{
> +       if (!msgbufmapped)
> +               return;
> +
> +       msgbuf_addstr(msgbufp, pri, str, filter_cr);
> +}
> +
>  void
>  msgbufinit(void *ptr, int size)
>  {
>
> Modified: head/sys/sys/msgbuf.h
> ==============================================================================
> --- head/sys/sys/msgbuf.h       Tue May 31 17:24:18 2011        (r222536)
> +++ head/sys/sys/msgbuf.h       Tue May 31 17:29:58 2011        (r222537)
> @@ -33,15 +33,21 @@
>  #ifndef _SYS_MSGBUF_H_
>  #define        _SYS_MSGBUF_H_
>
> +#include <sys/lock.h>
> +#include <sys/mutex.h>
> +
>  struct msgbuf {
> -       char    *msg_ptr;               /* pointer to buffer */
> +       char       *msg_ptr;            /* pointer to buffer */
>  #define        MSG_MAGIC       0x063062
> -       u_int   msg_magic;
> -       u_int   msg_size;               /* size of buffer area */
> -       u_int   msg_wseq;               /* write sequence number */
> -       u_int   msg_rseq;               /* read sequence number */
> -       u_int   msg_cksum;              /* checksum of contents */
> -       u_int   msg_seqmod;             /* range for sequence numbers */
> +       u_int      msg_magic;
> +       u_int      msg_size;            /* size of buffer area */
> +       u_int      msg_wseq;            /* write sequence number */
> +       u_int      msg_rseq;            /* read sequence number */
> +       u_int      msg_cksum;           /* checksum of contents */
> +       u_int      msg_seqmod;          /* range for sequence numbers */
> +       int        msg_lastpri;         /* saved priority value */
> +       int        msg_needsnl;         /* set when newline needed */
> +       struct mtx msg_lock;            /* mutex to protect the buffer */
>  };
>
>  /* Normalise a sequence number or a difference between sequence numbers. */
> @@ -59,6 +65,7 @@ extern struct mtx msgbuf_lock;
>
>  void   msgbufinit(void *ptr, int size);
>  void   msgbuf_addchar(struct msgbuf *mbp, int c);
> +void   msgbuf_addstr(struct msgbuf *mbp, int pri, char *str, int filter_cr);
>  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);
> _______________________________________________
> svn-src-head at freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/svn-src-head
> To unsubscribe, send any mail to "svn-src-head-unsubscribe at freebsd.org"
>


More information about the svn-src-all mailing list