diff options
author | iedowse <iedowse@FreeBSD.org> | 2003-06-22 02:18:31 +0000 |
---|---|---|
committer | iedowse <iedowse@FreeBSD.org> | 2003-06-22 02:18:31 +0000 |
commit | 6bb0e5cb462431a2a86e4263d027ba8ad04eddc4 (patch) | |
tree | 9a1905dfa8c0a75f641cb540d2ad545b73865369 /sys/kern/subr_log.c | |
parent | e6efd8ec4391d9b20c677c9b0a816b41e4036b17 (diff) | |
download | FreeBSD-src-6bb0e5cb462431a2a86e4263d027ba8ad04eddc4.zip FreeBSD-src-6bb0e5cb462431a2a86e4263d027ba8ad04eddc4.tar.gz |
Replace the code for reading and writing the kernel message buffer
with a new implementation that has a mostly reentrant "addchar"
routine, supports multiple message buffers in the kernel, and hides
the implementation details from callers.
The new code uses a kind of sequence number to represend the current
read and write positions in the buffer. This approach (suggested
mainly by bde) permits the read and write pointers to be maintained
separately, which reduces the number of atomic operations that are
required. The "mostly reentrant" above refers to the way that while
it is now always safe to have any number of concurrent writers,
readers could see the message buffer after a writer has advanced
the pointers but before it has witten the new character.
Discussed on: freebsd-arch
Diffstat (limited to 'sys/kern/subr_log.c')
-rw-r--r-- | sys/kern/subr_log.c | 25 |
1 files changed, 7 insertions, 18 deletions
diff --git a/sys/kern/subr_log.c b/sys/kern/subr_log.c index d721e2e..031d081 100644 --- a/sys/kern/subr_log.c +++ b/sys/kern/subr_log.c @@ -126,11 +126,12 @@ logclose(dev_t dev, int flag, int mode, struct thread *td) 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); @@ -145,19 +146,13 @@ logread(dev_t dev, struct uio *uio, int flag) 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); } @@ -172,7 +167,7 @@ logpoll(dev_t dev, int events, struct thread *td) 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); @@ -212,18 +207,12 @@ logtimeout(void *arg) 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: |