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