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.1 (Berkeley) 06/10/93 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 logopen(dev, flags, mode, p) 37 dev_t dev; 38 int flags, mode; 39 struct proc *p; 40 { 41 register struct msgbuf *mbp = msgbufp; 42 43 if (log_open) 44 return (EBUSY); 45 log_open = 1; 46 logsoftc.sc_pgid = p->p_pid; /* signal process only */ 47 /* 48 * Potential race here with putchar() but since putchar should be 49 * called by autoconf, msg_magic should be initialized by the time 50 * we get here. 51 */ 52 if (mbp->msg_magic != MSG_MAGIC) { 53 register int i; 54 55 mbp->msg_magic = MSG_MAGIC; 56 mbp->msg_bufx = mbp->msg_bufr = 0; 57 for (i=0; i < MSG_BSIZE; i++) 58 mbp->msg_bufc[i] = 0; 59 } 60 return (0); 61 } 62 63 /*ARGSUSED*/ 64 logclose(dev, flag, mode, p) 65 dev_t dev; 66 int flag, mode; 67 struct proc *p; 68 { 69 70 log_open = 0; 71 logsoftc.sc_state = 0; 72 return (0); 73 } 74 75 /*ARGSUSED*/ 76 logread(dev, uio, flag) 77 dev_t dev; 78 struct uio *uio; 79 int flag; 80 { 81 register struct msgbuf *mbp = msgbufp; 82 register long l; 83 register int s; 84 int error = 0; 85 86 s = splhigh(); 87 while (mbp->msg_bufr == mbp->msg_bufx) { 88 if (flag & IO_NDELAY) { 89 splx(s); 90 return (EWOULDBLOCK); 91 } 92 logsoftc.sc_state |= LOG_RDWAIT; 93 if (error = tsleep((caddr_t)mbp, LOG_RDPRI | PCATCH, 94 "klog", 0)) { 95 splx(s); 96 return (error); 97 } 98 } 99 splx(s); 100 logsoftc.sc_state &= ~LOG_RDWAIT; 101 102 while (uio->uio_resid > 0) { 103 l = mbp->msg_bufx - mbp->msg_bufr; 104 if (l < 0) 105 l = MSG_BSIZE - mbp->msg_bufr; 106 l = min(l, uio->uio_resid); 107 if (l == 0) 108 break; 109 error = uiomove((caddr_t)&mbp->msg_bufc[mbp->msg_bufr], 110 (int)l, uio); 111 if (error) 112 break; 113 mbp->msg_bufr += l; 114 if (mbp->msg_bufr < 0 || mbp->msg_bufr >= MSG_BSIZE) 115 mbp->msg_bufr = 0; 116 } 117 return (error); 118 } 119 120 /*ARGSUSED*/ 121 logselect(dev, rw, p) 122 dev_t dev; 123 int rw; 124 struct proc *p; 125 { 126 int s = splhigh(); 127 128 switch (rw) { 129 130 case FREAD: 131 if (msgbufp->msg_bufr != msgbufp->msg_bufx) { 132 splx(s); 133 return (1); 134 } 135 selrecord(p, &logsoftc.sc_selp); 136 break; 137 } 138 splx(s); 139 return (0); 140 } 141 142 logwakeup() 143 { 144 struct proc *p; 145 146 if (!log_open) 147 return; 148 selwakeup(&logsoftc.sc_selp); 149 if (logsoftc.sc_state & LOG_ASYNC) { 150 if (logsoftc.sc_pgid < 0) 151 gsignal(-logsoftc.sc_pgid, SIGIO); 152 else if (p = pfind(logsoftc.sc_pgid)) 153 psignal(p, SIGIO); 154 } 155 if (logsoftc.sc_state & LOG_RDWAIT) { 156 wakeup((caddr_t)msgbufp); 157 logsoftc.sc_state &= ~LOG_RDWAIT; 158 } 159 } 160 161 /*ARGSUSED*/ 162 logioctl(dev, com, data, flag, p) 163 dev_t dev; 164 int com; 165 caddr_t data; 166 int flag; 167 struct proc *p; 168 { 169 long l; 170 int s; 171 172 switch (com) { 173 174 /* return number of characters immediately available */ 175 case FIONREAD: 176 s = splhigh(); 177 l = msgbufp->msg_bufx - msgbufp->msg_bufr; 178 splx(s); 179 if (l < 0) 180 l += MSG_BSIZE; 181 *(int *)data = l; 182 break; 183 184 case FIONBIO: 185 break; 186 187 case FIOASYNC: 188 if (*(int *)data) 189 logsoftc.sc_state |= LOG_ASYNC; 190 else 191 logsoftc.sc_state &= ~LOG_ASYNC; 192 break; 193 194 case TIOCSPGRP: 195 logsoftc.sc_pgid = *(int *)data; 196 break; 197 198 case TIOCGPGRP: 199 *(int *)data = logsoftc.sc_pgid; 200 break; 201 202 default: 203 return (-1); 204 } 205 return (0); 206 } 207