int pri = 0;
int tailmode = 0;
int kno;
- unsigned int rindex;
size_t buflen, bufpos;
setlocale(LC_CTYPE, "");
if (memf == NULL && nlistf == NULL && tailmode == 0) {
/* Running kernel. Use sysctl. */
+ buflen = 0;
if (sysctlbyname("kern.msgbuf", NULL, &buflen, NULL, 0) == -1)
err(1, "sysctl kern.msgbuf");
- buflen += 4096; /* add some slop */
if ((bp = malloc(buflen)) == NULL)
errx(1, "malloc failed");
if (sysctlbyname("kern.msgbuf", bp, &buflen, NULL, 0) == -1)
bufpos = 0;
dumpbuf(bp, bufpos, buflen, &newl, &skip, &pri);
} else {
+ u_int rindex;
+ u_int xindex;
+ u_int ri;
+ u_int xi;
+ u_int n;
+
/* Read in kernel message buffer, do sanity checks. */
kd = kvm_open(nlistf, memf, NULL, O_RDONLY, "dmesg");
if (kd == NULL)
errx(1, "kvm_read: %s", kvm_geterr(kd));
if (KREAD((long)bufp, cur))
errx(1, "kvm_read: %s", kvm_geterr(kd));
- if (cur.msg_magic != MSG_MAGIC)
+ if (cur.msg_magic != MSG_MAGIC && cur.msg_magic != MSG_OMAGIC)
errx(1, "kernel message buffer has different magic "
"number");
/*
- * Start point. Use rindex == bufx as our end-of-buffer
- * indication but for the initial rindex from the kernel
- * this means the buffer has cycled and is 100% full.
+ * NOTE: current algorithm is compatible with both old and
+ * new msgbuf structures. The new structure doesn't
+ * modulo the indexes (so we do), and adds a separate
+ * log index which we don't access here.
*/
+
rindex = cur.msg_bufr;
- if (rindex == cur.msg_bufx) {
- if (++rindex >= cur.msg_size)
- rindex = 0;
- }
for (;;) {
- if (cur.msg_bufx >= rindex)
- buflen = cur.msg_bufx - rindex;
+ /*
+ * Calculate index for dump and do sanity clipping.
+ */
+ xindex = cur.msg_bufx;
+ n = xindex - rindex;
+ if (n > cur.msg_size - 1024) {
+ rindex = xindex - cur.msg_size + 2048;
+ n = xindex - rindex;
+ }
+ ri = rindex % cur.msg_size;
+ xi = xindex % cur.msg_size;
+
+ if (ri < xi)
+ buflen = xi - ri;
else
- buflen = cur.msg_size - rindex;
+ buflen = cur.msg_size - ri;
+ if (buflen > n)
+ buflen = n;
if (buflen > INCRBUFSIZE)
buflen = INCRBUFSIZE;
- if (kvm_read(kd, (long)cur.msg_ptr + rindex,
+
+ if (kvm_read(kd, (long)cur.msg_ptr + ri,
bp, buflen) != (ssize_t)buflen) {
errx(1, "kvm_read: %s", kvm_geterr(kd));
}
if (buflen)
dumpbuf(bp, 0, buflen, &newl, &skip, &pri);
+ ri = (ri + buflen) % cur.msg_size;
+ n = n - buflen;
rindex += buflen;
- if (rindex >= cur.msg_size)
- rindex = 0;
- if (rindex == cur.msg_bufx) {
+ if ((int)n <= 0) {
if (tailmode == 0)
break;
fflush(stdout);
*skip = 0;
*newl = 1;
} if (ch == '>') {
- if (LOG_FAC(*pri) == LOG_KERN || all_opt)
+ if (LOG_FAC(*pri) == LOG_KERN)
*newl = *skip = 0;
} else if (ch >= '0' && ch <= '9') {
*pri *= 10;
}
continue;
}
- if (*newl && ch == '<') {
+ if (*newl && ch == '<' && all_opt == 0) {
*pri = 0;
*skip = 1;
continue;
}
if (ch == '\0')
continue;
- *newl = ch == '\n';
+ *newl = (ch == '\n');
vis(buf, ch, 0, 0);
if (buf[1] == 0)
putchar(buf[0]);
logclose(struct dev_close_args *ap)
{
log_open = 0;
- callout_stop(&logsoftc.sc_callout);
+ callout_stop_sync(&logsoftc.sc_callout);
logsoftc.sc_state = 0;
funsetown(&logsoftc.sc_sigio);
return (0);
{
struct uio *uio = ap->a_uio;
struct msgbuf *mbp = msgbufp;
- long l;
int error = 0;
-
- crit_enter();
- while (mbp->msg_bufr == mbp->msg_bufx) {
+ u_int lindex;
+ u_int xindex;
+ u_int lindex_modulo;
+ u_int n;
+
+ /*
+ * Handle blocking
+ */
+ while (mbp->msg_bufl == mbp->msg_bufx) {
+ crit_enter();
if (ap->a_ioflag & IO_NDELAY) {
crit_exit();
return (EWOULDBLOCK);
}
- logsoftc.sc_state |= LOG_RDWAIT;
+ atomic_set_int(&logsoftc.sc_state, LOG_RDWAIT);
if ((error = tsleep((caddr_t)mbp, PCATCH, "klog", 0))) {
crit_exit();
return (error);
}
+ /* don't bother clearing LOG_RDWAIT */
+ crit_exit();
}
- crit_exit();
- logsoftc.sc_state &= ~LOG_RDWAIT;
-
- while (uio->uio_resid > 0) {
- l = (long)mbp->msg_bufx - (long)mbp->msg_bufr;
- if (l < 0)
- l = mbp->msg_size - mbp->msg_bufr;
- l = (long)szmin(l, uio->uio_resid);
- if (l == 0)
- break;
- error = uiomove((caddr_t)msgbufp->msg_ptr + mbp->msg_bufr,
- (size_t)l, uio);
+
+ /*
+ * Loop reading data
+ */
+ while (uio->uio_resid > 0 && mbp->msg_bufl != mbp->msg_bufx) {
+ lindex = mbp->msg_bufl;
+ xindex = mbp->msg_bufx;
+ cpu_ccfence();
+
+ /*
+ * Clean up if too much time has passed causing us to wrap
+ * the buffer. This will lose some data. If more than ~4GB
+ * then this will lose even more data.
+ */
+ n = xindex - lindex;
+ if (n > mbp->msg_size - 1024) {
+ lindex = xindex - mbp->msg_size + 2048;
+ n = xindex - lindex;
+ }
+
+ /*
+ * Calculates contiguous bytes we can read in one loop.
+ */
+ lindex_modulo = lindex % mbp->msg_size;
+ n = mbp->msg_size - lindex_modulo;
+ if (n > xindex - lindex)
+ n = xindex - lindex;
+ if ((size_t)n > uio->uio_resid)
+ n = (u_int)uio->uio_resid;
+
+ /*
+ * Copy (n) bytes of data.
+ */
+ error = uiomove((caddr_t)msgbufp->msg_ptr + lindex_modulo,
+ (size_t)n, uio);
if (error)
break;
- mbp->msg_bufr += l;
- if (mbp->msg_bufr >= mbp->msg_size)
- mbp->msg_bufr = 0;
+ mbp->msg_bufl = lindex + n;
}
return (error);
}
int ret = 0;
crit_enter();
- if (msgbufp->msg_bufr != msgbufp->msg_bufx)
+ if (msgbufp->msg_bufl != msgbufp->msg_bufx)
ret = 1;
crit_exit();
if ((logsoftc.sc_state & LOG_ASYNC) && logsoftc.sc_sigio != NULL)
pgsigio(logsoftc.sc_sigio, SIGIO, 0);
if (logsoftc.sc_state & LOG_RDWAIT) {
+ atomic_clear_int(&logsoftc.sc_state, LOG_RDWAIT);
wakeup((caddr_t)msgbufp);
- logsoftc.sc_state &= ~LOG_RDWAIT;
}
callout_reset(&logsoftc.sc_callout, hz / log_wakeups_per_second,
logtimeout, NULL);
static int
logioctl(struct dev_ioctl_args *ap)
{
- long l;
+ struct msgbuf *mbp = msgbufp;
+ u_int lindex;
+ u_int xindex;
+ u_int n;
switch (ap->a_cmd) {
case FIONREAD:
- /* return number of characters immediately available */
- crit_enter();
- l = msgbufp->msg_bufx - msgbufp->msg_bufr;
- crit_exit();
- if (l < 0)
- l += msgbufp->msg_size;
- *(int *)ap->a_data = l;
+ lindex = mbp->msg_bufl;
+ xindex = mbp->msg_bufx;
+ cpu_ccfence();
+
+ /*
+ * Clean up if too much time has passed causing us to wrap
+ * the buffer. This will lose some data. If more than ~4GB
+ * then this will lose even more data.
+ */
+ n = xindex - lindex;
+ if (n > mbp->msg_size - 1024) {
+ lindex = xindex - mbp->msg_size + 2048;
+ n = xindex - lindex;
+ }
+ *(int *)ap->a_data = n;
break;
case FIOASYNC:
if (*(int *)ap->a_data)
- logsoftc.sc_state |= LOG_ASYNC;
+ atomic_set_int(&logsoftc.sc_state, LOG_ASYNC);
else
- logsoftc.sc_state &= ~LOG_ASYNC;
+ atomic_clear_int(&logsoftc.sc_state, LOG_ASYNC);
break;
case FIOSETOWN:
static void
constty_daemon(void)
{
- int rindex = -1;
- int windex = -1;
+ u_int rindex;
+ u_int xindex;
+ u_int n;
struct msgbuf *mbp;
struct tty *tp;
constty_td, SHUTDOWN_PRI_FIRST);
constty_td->td_flags |= TDF_SYSTHREAD;
+ mbp = msgbufp;
+ rindex = mbp->msg_bufr; /* persistent loop variable */
+ xindex = mbp->msg_bufx - 1; /* anything different than bufx */
+ cpu_ccfence();
+
for (;;) {
kproc_suspend_loop();
crit_enter();
- mbp = msgbufp;
- if (mbp == NULL || msgbufmapped == 0 ||
- windex == mbp->msg_bufx) {
+ if (mbp != msgbufp)
+ mbp = msgbufp;
+ if (xindex == mbp->msg_bufx ||
+ mbp == NULL ||
+ msgbufmapped == 0) {
tsleep(constty_td, 0, "waiting", hz*60);
crit_exit();
continue;
}
- windex = mbp->msg_bufx;
crit_exit();
/*
* Get message buf FIFO indices. rindex is tracking.
*/
+ xindex = mbp->msg_bufx;
+ cpu_ccfence();
if ((tp = constty) == NULL) {
- rindex = mbp->msg_bufx;
+ rindex = xindex;
continue;
}
/*
- * Don't blow up if the message buffer is broken
+ * Check if the calculated bytes has rolled the whole
+ * message buffer.
*/
- if (windex < 0 || windex >= mbp->msg_size)
- continue;
- if (rindex < 0 || rindex >= mbp->msg_size)
- rindex = windex;
+ n = xindex - rindex;
+ if (n > mbp->msg_size - 1024) {
+ rindex = xindex - mbp->msg_size + 2048;
+ n = xindex - rindex;
+ }
/*
* And dump it. If constty gets stuck will give up.
*/
- while (rindex != windex) {
- if (tputchar((uint8_t)mbp->msg_ptr[rindex], tp) < 0) {
+ while (rindex != xindex) {
+ u_int ri = rindex % mbp->msg_size;
+ if (tputchar((uint8_t)mbp->msg_ptr[ri], tp) < 0) {
constty = NULL;
- rindex = mbp->msg_bufx;
+ rindex = xindex;
break;
}
- if (++rindex >= mbp->msg_size)
- rindex = 0;
if (tp->t_outq.c_cc >= tp->t_ohiwat) {
tsleep(constty_daemon, 0, "blocked", hz / 10);
if (tp->t_outq.c_cc >= tp->t_ohiwat) {
- rindex = windex;
+ rindex = xindex;
break;
}
}
+ ++rindex;
}
}
}
msgaddchar(int c, void *dummy)
{
struct msgbuf *mbp;
- int rindex;
- int windex;
+ u_int lindex;
+ u_int rindex;
+ u_int xindex;
+ u_int n;
if (!msgbufmapped)
return;
mbp = msgbufp;
- windex = mbp->msg_bufx;
- mbp->msg_ptr[windex] = c;
- if (++windex >= mbp->msg_size)
- windex = 0;
+ lindex = mbp->msg_bufl;
rindex = mbp->msg_bufr;
- if (windex == rindex) {
- rindex += 32;
- if (rindex >= mbp->msg_size)
- rindex -= mbp->msg_size;
+ xindex = mbp->msg_bufx++; /* Allow SMP race */
+ cpu_ccfence();
+
+ mbp->msg_ptr[xindex % mbp->msg_size] = c;
+ n = xindex - lindex;
+ if (n > mbp->msg_size - 1024) {
+ lindex = xindex - mbp->msg_size + 2048;
+ cpu_ccfence();
+ mbp->msg_bufl = lindex;
+ }
+ n = xindex - rindex;
+ if (n > mbp->msg_size - 1024) {
+ rindex = xindex - mbp->msg_size + 2048;
+ cpu_ccfence();
mbp->msg_bufr = rindex;
}
- mbp->msg_bufx = windex;
}
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;
+ u_int rindex;
+ u_int xindex;
+ u_int n;
+
+ rindex = oldp->msg_bufr;
+ xindex = oldp->msg_bufx;
+ cpu_ccfence();
+
+ n = xindex - rindex;
+ if (n > oldp->msg_size - 1024)
+ rindex = xindex - oldp->msg_size + 2048;
+ while (rindex != xindex) {
+ msglogchar(oldp->msg_ptr[rindex % oldp->msg_size], -1);
+ ++rindex;
}
}
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_bufr >= size) {
+ if (msgbufp->msg_magic != MSG_MAGIC || msgbufp->msg_size != size) {
bzero(cp, size);
bzero(msgbufp, sizeof(*msgbufp));
msgbufp->msg_magic = MSG_MAGIC;
msgbufp->msg_ptr = cp;
if (msgbufmapped && oldp != msgbufp)
msgbufcopy(oldp);
+ cpu_mfence();
msgbufmapped = 1;
oldp = msgbufp;
}
static int
sysctl_kern_msgbuf(SYSCTL_HANDLER_ARGS)
{
+ struct msgbuf *mbp;
struct ucred *cred;
int error;
+ u_int rindex_modulo;
+ u_int xindex_modulo;
+ u_int rindex;
+ u_int xindex;
+ u_int n;
/*
* Only wheel or root can access the message log.
/*
* Unwind the buffer, so that it's linear (possibly starting with
* some initial nulls).
+ *
+ * We don't push the entire buffer like we did before because
+ * bufr (and bufl) now advance in chunks when the fifo is full,
+ * rather than one character.
*/
- error = sysctl_handle_opaque(oidp, msgbufp->msg_ptr + msgbufp->msg_bufx,
- msgbufp->msg_size - msgbufp->msg_bufx, req);
+ mbp = msgbufp;
+ rindex = mbp->msg_bufr;
+ xindex = mbp->msg_bufx;
+ n = xindex - rindex;
+ if (n > mbp->msg_size - 1024) {
+ rindex = xindex - mbp->msg_size + 2048;
+ n = xindex - rindex;
+ }
+ rindex_modulo = rindex % mbp->msg_size;
+ xindex_modulo = xindex % mbp->msg_size;
+
+ if (rindex_modulo < xindex_modulo) {
+ error = sysctl_handle_opaque(oidp,
+ mbp->msg_ptr + rindex_modulo,
+ xindex_modulo - rindex_modulo,
+ req);
+ } else if (n <= mbp->msg_size - rindex_modulo) {
+ error = sysctl_handle_opaque(oidp,
+ mbp->msg_ptr + rindex_modulo,
+ n - rindex_modulo,
+ req);
+ } else {
+ error = sysctl_handle_opaque(oidp,
+ mbp->msg_ptr + rindex_modulo,
+ mbp->msg_size - rindex_modulo,
+ req);
+ n -= mbp->msg_size - rindex_modulo;
+ if (error == 0)
+ error = sysctl_handle_opaque(oidp, mbp->msg_ptr,
+ n, req);
+ }
if (error)
return (error);
- if (msgbufp->msg_bufx > 0) {
- error = sysctl_handle_opaque(oidp, msgbufp->msg_ptr,
- msgbufp->msg_bufx, req);
- }
return (error);
}
error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
if (!error && req->newptr) {
/* Clear the buffer and reset write pointer */
+ msgbufp->msg_bufr = msgbufp->msg_bufx;
+ msgbufp->msg_bufl = msgbufp->msg_bufx;
bzero(msgbufp->msg_ptr, msgbufp->msg_size);
- msgbufp->msg_bufr = msgbufp->msg_bufx = 0;
msgbuf_clear = 0;
}
return (error);
DB_SHOW_COMMAND(msgbuf, db_show_msgbuf)
{
- int i, j;
+ u_int rindex;
+ u_int i;
+ u_int j;
if (!msgbufmapped) {
db_printf("msgbuf not mapped yet\n");
}
db_printf("msgbufp = %p\n", msgbufp);
db_printf("magic = %x, size = %d, r= %d, w = %d, ptr = %p\n",
- msgbufp->msg_magic, msgbufp->msg_size, msgbufp->msg_bufr,
- msgbufp->msg_bufx, msgbufp->msg_ptr);
+ msgbufp->msg_magic, msgbufp->msg_size,
+ msgbufp->msg_bufr % msgbufp->msg_size,
+ msgbufp->msg_bufx % msgbufp->msg_size,
+ msgbufp->msg_ptr);
+
+ rindex = msgbufp->msg_bufr;
for (i = 0; i < msgbufp->msg_size; i++) {
- j = (i + msgbufp->msg_bufr) % msgbufp->msg_size;
+ j = (i + rindex) % msgbufp->msg_size;
db_printf("%c", msgbufp->msg_ptr[j]);
}
db_printf("\n");
SYSCTL_ULONG(_hw, OID_AUTO, availpages, CTLFLAG_RD, &Maxmem, 0, "");
-#if 0
-
-static int
-sysctl_machdep_msgbuf(SYSCTL_HANDLER_ARGS)
-{
- int 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_bufr,
- msgbufp->msg_size-msgbufp->msg_bufr,req);
- if(error) return(error);
- if(msgbufp->msg_bufr>0) {
- error=sysctl_handle_opaque(oidp,msgbufp->msg_ptr,
- msgbufp->msg_bufr,req);
- }
- return(error);
-}
-
-SYSCTL_PROC(_machdep, OID_AUTO, msgbuf, CTLTYPE_STRING|CTLFLAG_RD,
- 0, 0, sysctl_machdep_msgbuf, "A","Contents of kernel message buffer");
-
-static int msgbuf_clear;
-
-static int
-sysctl_machdep_msgbuf_clear(SYSCTL_HANDLER_ARGS)
-{
- 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;
- msgbuf_clear=0;
- }
- return (error);
-}
-
-SYSCTL_PROC(_machdep, OID_AUTO, msgbuf_clear, CTLTYPE_INT|CTLFLAG_RW,
- &msgbuf_clear, 0, sysctl_machdep_msgbuf_clear, "I",
- "Clear kernel message buffer");
-
-#endif
-
/*
* Send an interrupt to process.
*
SYSCTL_ULONG(_hw, OID_AUTO, availpages, CTLFLAG_RD, &Maxmem, 0, "");
-#if 0
-
-static int
-sysctl_machdep_msgbuf(SYSCTL_HANDLER_ARGS)
-{
- int 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_bufr,
- msgbufp->msg_size-msgbufp->msg_bufr,req);
- if(error) return(error);
- if(msgbufp->msg_bufr>0) {
- error=sysctl_handle_opaque(oidp,msgbufp->msg_ptr,
- msgbufp->msg_bufr,req);
- }
- return(error);
-}
-
-SYSCTL_PROC(_machdep, OID_AUTO, msgbuf, CTLTYPE_STRING|CTLFLAG_RD,
- 0, 0, sysctl_machdep_msgbuf, "A","Contents of kernel message buffer");
-
-static int msgbuf_clear;
-
-static int
-sysctl_machdep_msgbuf_clear(SYSCTL_HANDLER_ARGS)
-{
- 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;
- msgbuf_clear=0;
- }
- return (error);
-}
-
-SYSCTL_PROC(_machdep, OID_AUTO, msgbuf_clear, CTLTYPE_INT|CTLFLAG_RW,
- &msgbuf_clear, 0, sysctl_machdep_msgbuf_clear, "I",
- "Clear kernel message buffer");
-
-#endif
-
/*
* Send an interrupt to process.
*
#include <sys/types.h>
#endif
+/*
+ * NOTE! The indices are not masked against msg_size. All accessors
+ * must mask the indices against msg_size to get actual buffer
+ * indexes. For relative block sizes, simple subtraction can be
+ * used using unsigned integers.
+ */
struct msgbuf {
-#define MSG_MAGIC 0x063062
+#define MSG_MAGIC 0x063064
+#define MSG_OMAGIC 0x063062
unsigned int msg_magic;
unsigned int msg_size; /* size of buffer area */
- unsigned int msg_bufx; /* write pointer */
- unsigned int msg_bufr; /* read pointer */
+ unsigned int msg_bufx; /* write index - kernel */
+ unsigned int msg_bufr; /* base index - kernel */
char * msg_ptr; /* pointer to buffer */
+ unsigned int msg_bufl; /* read index - log device */
+ unsigned int msg_unused01;
};
#ifdef _KERNEL