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