1 /* 2 * Copyright (c) 1982, 1986, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)subr_log.c 8.3 (Berkeley) 02/14/95 8 */ 9 10 /* 11 * Error log buffer for kernel printf's. 12 */ 13 14 #include <sys/param.h> 15 #include <sys/systm.h> 16 #include <sys/proc.h> 17 #include <sys/vnode.h> 18 #include <sys/ioctl.h> 19 #include <sys/msgbuf.h> 20 #include <sys/file.h> 21 22 #define LOG_RDPRI (PZERO + 1) 23 24 #define LOG_ASYNC 0x04 25 #define LOG_RDWAIT 0x08 26 27 struct logsoftc { 28 int sc_state; /* see above for possibilities */ 29 struct selinfo sc_selp; /* process waiting on select call */ 30 int sc_pgid; /* process/group for async I/O */ 31 } logsoftc; 32 33 int log_open; /* also used in log() */ 34 35 /*ARGSUSED*/ 36 int 37 logopen(dev, flags, mode, p) 38 dev_t dev; 39 int flags, mode; 40 struct proc *p; 41 { 42 register struct msgbuf *mbp = msgbufp; 43 44 if (log_open) 45 return (EBUSY); 46 log_open = 1; 47 logsoftc.sc_pgid = p->p_pid; /* signal process only */ 48 /* 49 * Potential race here with putchar() but since putchar should be 50 * called by autoconf, msg_magic should be initialized by the time 51 * we get here. 52 */ 53 if (mbp->msg_magic != MSG_MAGIC) { 54 register int i; 55 56 mbp->msg_magic = MSG_MAGIC; 57 mbp->msg_bufx = mbp->msg_bufr = 0; 58 for (i=0; i < MSG_BSIZE; i++) 59 mbp->msg_bufc[i] = 0; 60 } 61 return (0); 62 } 63 64 /*ARGSUSED*/ 65 int 66 logclose(dev, flag, mode, p) 67 dev_t dev; 68 int flag, mode; 69 struct proc *p; 70 { 71 72 log_open = 0; 73 logsoftc.sc_state = 0; 74 return (0); 75 } 76 77 /*ARGSUSED*/ 78 int 79 logread(dev, uio, flag) 80 dev_t dev; 81 struct uio *uio; 82 int flag; 83 { 84 register struct msgbuf *mbp = msgbufp; 85 register long l; 86 register int s; 87 int error = 0; 88 89 s = splhigh(); 90 while (mbp->msg_bufr == mbp->msg_bufx) { 91 if (flag & IO_NDELAY) { 92 splx(s); 93 return (EWOULDBLOCK); 94 } 95 logsoftc.sc_state |= LOG_RDWAIT; 96 if (error = tsleep((caddr_t)mbp, LOG_RDPRI | PCATCH, 97 "klog", 0)) { 98 splx(s); 99 return (error); 100 } 101 } 102 splx(s); 103 logsoftc.sc_state &= ~LOG_RDWAIT; 104 105 while (uio->uio_resid > 0) { 106 l = mbp->msg_bufx - mbp->msg_bufr; 107 if (l < 0) 108 l = MSG_BSIZE - mbp->msg_bufr; 109 l = min(l, uio->uio_resid); 110 if (l == 0) 111 break; 112 error = uiomove((caddr_t)&mbp->msg_bufc[mbp->msg_bufr], 113 (int)l, uio); 114 if (error) 115 break; 116 mbp->msg_bufr += l; 117 if (mbp->msg_bufr < 0 || mbp->msg_bufr >= MSG_BSIZE) 118 mbp->msg_bufr = 0; 119 } 120 return (error); 121 } 122 123 /*ARGSUSED*/ 124 int 125 logselect(dev, rw, p) 126 dev_t dev; 127 int rw; 128 struct proc *p; 129 { 130 int s = splhigh(); 131 132 switch (rw) { 133 134 case FREAD: 135 if (msgbufp->msg_bufr != msgbufp->msg_bufx) { 136 splx(s); 137 return (1); 138 } 139 selrecord(p, &logsoftc.sc_selp); 140 break; 141 } 142 splx(s); 143 return (0); 144 } 145 146 void 147 logwakeup() 148 { 149 struct proc *p; 150 151 if (!log_open) 152 return; 153 selwakeup(&logsoftc.sc_selp); 154 if (logsoftc.sc_state & LOG_ASYNC) { 155 if (logsoftc.sc_pgid < 0) 156 gsignal(-logsoftc.sc_pgid, SIGIO); 157 else if (p = pfind(logsoftc.sc_pgid)) 158 psignal(p, SIGIO); 159 } 160 if (logsoftc.sc_state & LOG_RDWAIT) { 161 wakeup((caddr_t)msgbufp); 162 logsoftc.sc_state &= ~LOG_RDWAIT; 163 } 164 } 165 166 /*ARGSUSED*/ 167 int 168 logioctl(dev, com, data, flag, p) 169 dev_t dev; 170 u_long com; 171 caddr_t data; 172 int flag; 173 struct proc *p; 174 { 175 long l; 176 int s; 177 178 switch (com) { 179 180 /* return number of characters immediately available */ 181 case FIONREAD: 182 s = splhigh(); 183 l = msgbufp->msg_bufx - msgbufp->msg_bufr; 184 splx(s); 185 if (l < 0) 186 l += MSG_BSIZE; 187 *(int *)data = l; 188 break; 189 190 case FIONBIO: 191 break; 192 193 case FIOASYNC: 194 if (*(int *)data) 195 logsoftc.sc_state |= LOG_ASYNC; 196 else 197 logsoftc.sc_state &= ~LOG_ASYNC; 198 break; 199 200 case TIOCSPGRP: 201 logsoftc.sc_pgid = *(int *)data; 202 break; 203 204 case TIOCGPGRP: 205 *(int *)data = logsoftc.sc_pgid; 206 break; 207 208 default: 209 return (-1); 210 } 211 return (0); 212 } 213