123379Smckusick /* 223379Smckusick * Copyright (c) 1982 Regents of the University of California. 323379Smckusick * All rights reserved. The Berkeley software License Agreement 423379Smckusick * specifies the terms and conditions for redistribution. 523379Smckusick * 6*24524Sbloom * @(#)subr_log.c 6.6 (Berkeley) 09/04/85 723379Smckusick */ 816723Sralph 916723Sralph /* 1016723Sralph * Error log buffer for kernel printf's. 1116723Sralph */ 1216723Sralph 1317093Sbloom #include "param.h" 1417093Sbloom #include "dir.h" 1517093Sbloom #include "user.h" 1617093Sbloom #include "proc.h" 1717093Sbloom #include "ioctl.h" 1817093Sbloom #include "msgbuf.h" 1917093Sbloom #include "file.h" 2017093Sbloom #include "errno.h" 2116723Sralph 2216723Sralph #define LOG_RDPRI (PZERO + 1) 2316723Sralph 2416723Sralph #define LOG_NBIO 0x02 2516723Sralph #define LOG_ASYNC 0x04 2616723Sralph #define LOG_RDWAIT 0x08 2716723Sralph 2816723Sralph struct logsoftc { 2916723Sralph int sc_state; /* see above for possibilities */ 3016723Sralph struct proc *sc_selp; /* process waiting on select call */ 3116723Sralph int sc_pgrp; /* process group for async I/O */ 3216723Sralph } logsoftc; 3316723Sralph 3418365Skarels int log_open; /* also used in log() */ 3518365Skarels 3616725Sralph #ifdef LOGDEBUG 3716725Sralph /*VARARGS1*/ 3816725Sralph xprintf(fmt, x1) 3916725Sralph char *fmt; 4016725Sralph unsigned x1; 4116725Sralph { 4216725Sralph 4316725Sralph prf(fmt, &x1, 1, (struct tty *)0); 4416725Sralph } 4516725Sralph #endif 4616725Sralph 47*24524Sbloom /*ARGSUSED*/ 4816723Sralph logopen(dev) 4916723Sralph dev_t dev; 5016723Sralph { 5116723Sralph 5216723Sralph #ifdef LOGDEBUG 5316725Sralph xprintf("logopen: dev=0x%x\n", dev); 5416723Sralph #endif 5518365Skarels if (log_open) 5616725Sralph return (EBUSY); 5718365Skarels log_open = 1; 5816723Sralph logsoftc.sc_selp = 0; 5916723Sralph logsoftc.sc_pgrp = u.u_procp->p_pgrp; 6016723Sralph /* 6116723Sralph * Potential race here with putchar() but since putchar should be 6216723Sralph * called by autoconf, msg_magic should be initialized by the time 6316723Sralph * we get here. 6416723Sralph */ 6516723Sralph if (msgbuf.msg_magic != MSG_MAGIC) { 6616723Sralph register int i; 6716723Sralph 6816723Sralph msgbuf.msg_magic = MSG_MAGIC; 6916723Sralph msgbuf.msg_bufx = msgbuf.msg_bufr = 0; 7016723Sralph for (i=0; i < MSG_BSIZE; i++) 7116723Sralph msgbuf.msg_bufc[i] = 0; 7216723Sralph } 7316725Sralph #ifdef LOGDEBUG 7416725Sralph xprintf("logopen: bufx=%d, bufr=%d\n", msgbuf.msg_bufx, msgbuf.msg_bufr); 7516725Sralph #endif 7616725Sralph return (0); 7716723Sralph } 7816723Sralph 79*24524Sbloom /*ARGSUSED*/ 8016723Sralph logclose(dev, flag) 8116723Sralph dev_t dev; 8216723Sralph { 8318365Skarels log_open = 0; 8416723Sralph logsoftc.sc_state = 0; 8516723Sralph logsoftc.sc_selp = 0; 8616723Sralph logsoftc.sc_pgrp = 0; 8716723Sralph #ifdef LOGDEBUG 8816725Sralph xprintf("logclose: dev=0x%x\n", dev); 8916723Sralph #endif 9016723Sralph } 9116723Sralph 92*24524Sbloom /*ARGSUSED*/ 9316723Sralph logread(dev, uio) 9416723Sralph dev_t dev; 9516723Sralph struct uio *uio; 9616723Sralph { 9716723Sralph register long l; 9816723Sralph register u_int c; 9916723Sralph register int s; 10016723Sralph int error = 0; 10116723Sralph 10216723Sralph #ifdef LOGDEBUG 10316725Sralph xprintf("logread: dev=0x%x\n", dev); 10416723Sralph #endif 10516723Sralph 10616723Sralph s = splhigh(); 10716723Sralph while (msgbuf.msg_bufr == msgbuf.msg_bufx) { 10816723Sralph if (logsoftc.sc_state & LOG_NBIO) { 10916723Sralph splx(s); 11016725Sralph return (EWOULDBLOCK); 11116723Sralph } 11216723Sralph logsoftc.sc_state |= LOG_RDWAIT; 11316723Sralph sleep((caddr_t)&msgbuf, LOG_RDPRI); 11416723Sralph } 11516723Sralph splx(s); 11616723Sralph logsoftc.sc_state &= ~LOG_RDWAIT; 11716723Sralph 11816723Sralph while (uio->uio_resid > 0) { 11916723Sralph l = msgbuf.msg_bufx - msgbuf.msg_bufr; 12016723Sralph if (l < 0) 12116723Sralph l = MSG_BSIZE - msgbuf.msg_bufr; 12216723Sralph c = min((u_int) l, (u_int)uio->uio_resid); 12316725Sralph #ifdef LOGDEBUG 12416725Sralph xprintf("logread: bufx=%d, bufr=%d, l=%d, c=%d\n", 12516725Sralph msgbuf.msg_bufx, msgbuf.msg_bufr, l, c); 12616725Sralph #endif 12716725Sralph if (c <= 0) 12816725Sralph break; 12916723Sralph error = uiomove((caddr_t)&msgbuf.msg_bufc[msgbuf.msg_bufr], 13016723Sralph (int)c, UIO_READ, uio); 13116723Sralph if (error) 13216723Sralph break; 13316723Sralph msgbuf.msg_bufr += c; 13416723Sralph if (msgbuf.msg_bufr < 0 || msgbuf.msg_bufr >= MSG_BSIZE) 13516723Sralph msgbuf.msg_bufr = 0; 13616723Sralph } 13716725Sralph return (error); 13816723Sralph } 13916723Sralph 140*24524Sbloom /*ARGSUSED*/ 14116723Sralph logselect(dev, rw) 14216723Sralph dev_t dev; 14316723Sralph int rw; 14416723Sralph { 14516723Sralph int s = splhigh(); 14616723Sralph 14716723Sralph switch (rw) { 14816723Sralph 14916723Sralph case FREAD: 15016723Sralph if (msgbuf.msg_bufr != msgbuf.msg_bufx) 15116723Sralph goto win; 15216723Sralph #ifdef LOGDEBUG 15316723Sralph if (logsoftc.sc_selp) 15416725Sralph xprintf("logselect: collision\n"); 15516723Sralph #endif 15616723Sralph logsoftc.sc_selp = u.u_procp; 15716723Sralph break; 15816723Sralph 15916723Sralph case FWRITE: 16016723Sralph #ifdef LOGDEBUG 16116725Sralph xprintf("logselect: FWRITE\n"); 16216723Sralph #endif 16316723Sralph break; 16416723Sralph } 16516723Sralph splx(s); 16616725Sralph return (0); 16716723Sralph win: 16816723Sralph splx(s); 16916725Sralph return (1); 17016723Sralph } 17116723Sralph 17216723Sralph logwakeup() 17316723Sralph { 17416723Sralph 17518365Skarels if (!log_open) 17618365Skarels return; 17716723Sralph if (logsoftc.sc_selp) { 17816723Sralph selwakeup(logsoftc.sc_selp, 0); 17916723Sralph logsoftc.sc_selp = 0; 18016723Sralph } 18116723Sralph if (logsoftc.sc_state & LOG_ASYNC) 18216723Sralph gsignal(logsoftc.sc_pgrp, SIGIO); 18316723Sralph if (logsoftc.sc_state & LOG_RDWAIT) { 18416723Sralph wakeup((caddr_t)&msgbuf); 18516723Sralph logsoftc.sc_state &= ~LOG_RDWAIT; 18616723Sralph } 18716723Sralph } 18816723Sralph 18916723Sralph /*ARGSUSED*/ 19016723Sralph logioctl(com, data, flag) 19116723Sralph caddr_t data; 19216723Sralph { 19316723Sralph long l; 19416723Sralph int s; 19516723Sralph 19616723Sralph switch (com) { 19716723Sralph 19816723Sralph /* return number of characters immediately available */ 19916723Sralph case FIONREAD: 20016723Sralph s = splhigh(); 20116723Sralph l = msgbuf.msg_bufx - msgbuf.msg_bufr; 20216723Sralph splx(s); 20316723Sralph if (l < 0) 20416723Sralph l += MSG_BSIZE; 20516723Sralph *(off_t *)data = l; 20616723Sralph break; 20716723Sralph 20816723Sralph case FIONBIO: 20916723Sralph if (*(int *)data) 21016723Sralph logsoftc.sc_state |= LOG_NBIO; 21116723Sralph else 21216723Sralph logsoftc.sc_state &= ~LOG_NBIO; 21316723Sralph break; 21416723Sralph 21516723Sralph case FIOASYNC: 21616723Sralph if (*(int *)data) 21716723Sralph logsoftc.sc_state |= LOG_ASYNC; 21816723Sralph else 21916723Sralph logsoftc.sc_state &= ~LOG_ASYNC; 22016723Sralph break; 22116723Sralph 22216723Sralph case TIOCSPGRP: 22316723Sralph logsoftc.sc_pgrp = *(int *)data; 22416723Sralph break; 22516723Sralph 22616723Sralph case TIOCGPGRP: 22716723Sralph *(int *)data = logsoftc.sc_pgrp; 22816723Sralph break; 22916723Sralph 23016723Sralph default: 23116725Sralph return (-1); 23216723Sralph } 23316725Sralph return (0); 23416723Sralph } 235