|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
23: /*
24: * Copyright (c) 1982, 1986, 1993
25: * The Regents of the University of California. All rights reserved.
26: *
27: * Redistribution and use in source and binary forms, with or without
28: * modification, are permitted provided that the following conditions
29: * are met:
30: * 1. Redistributions of source code must retain the above copyright
31: * notice, this list of conditions and the following disclaimer.
32: * 2. Redistributions in binary form must reproduce the above copyright
33: * notice, this list of conditions and the following disclaimer in the
34: * documentation and/or other materials provided with the distribution.
35: * 3. All advertising materials mentioning features or use of this software
36: * must display the following acknowledgement:
37: * This product includes software developed by the University of
38: * California, Berkeley and its contributors.
39: * 4. Neither the name of the University nor the names of its contributors
40: * may be used to endorse or promote products derived from this software
41: * without specific prior written permission.
42: *
43: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
44: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
47: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53: * SUCH DAMAGE.
54: *
55: * @(#)subr_log.c 8.3 (Berkeley) 2/14/95
56: */
57:
58: /*
59: * Error log buffer for kernel printf's.
60: */
61:
62: #include <sys/param.h>
63: #include <sys/systm.h>
64: #include <sys/proc.h>
65: #include <sys/vnode.h>
66: #include <sys/ioctl.h>
67: #include <sys/msgbuf.h>
68: #include <sys/file.h>
69: #include <sys/errno.h>
70: #include <sys/select.h>
71: #include <kern/thread.h>
72: #if 0 /* [ */
73: #include <kern/sched_prim.h>
74: #include <kern/parallel.h>
75: #endif /* 0 ] */
76:
77: #define LOG_RDPRI (PZERO + 1)
78:
79: #define LOG_NBIO 0x02
80: #define LOG_ASYNC 0x04
81: #define LOG_RDWAIT 0x08
82:
83: struct logsoftc {
84: int sc_state; /* see above for possibilities */
85: struct selinfo sc_selp; /* thread waiting for select */
86: int sc_pgid; /* process/group for async I/O */
87: } logsoftc;
88:
89: int log_open; /* also used in log() */
90: struct msgbuf temp_msgbuf;
91: struct msgbuf *msgbufp;
92:
93: /*
94: * Serialize log access. Note that the log can be written at interrupt level,
95: * so any log manipulations that can be done from, or affect, another processor
96: * at interrupt level must be guarded with a spin lock.
97: */
98: decl_simple_lock_data(,log_lock); /* stop races dead in their tracks */
99: #define LOG_LOCK() simple_lock(&log_lock)
100: #define LOG_UNLOCK() simple_unlock(&log_lock)
101: #define LOG_LOCK_INIT() simple_lock_init(&log_lock)
102:
103: /*ARGSUSED*/
104: logopen(dev, flags, mode, p)
105: dev_t dev;
106: int flags, mode;
107: struct proc *p;
108: {
109: unix_master(); /* for pg_id, sigh */
110: LOG_LOCK();
111: if (log_open) {
112: LOG_UNLOCK();
113: unix_release();
114: return (EBUSY);
115: }
116: log_open = 1;
117: logsoftc.sc_pgid = p->p_pid; /* signal process only */
118: /*
119: * Potential race here with putchar() but since putchar should be
120: * called by autoconf, msg_magic should be initialized by the time
121: * we get here.
122: */
123: if (msgbufp->msg_magic != MSG_MAGIC) {
124: register int i;
125:
126: msgbufp->msg_magic = MSG_MAGIC;
127: msgbufp->msg_bufx = msgbufp->msg_bufr = 0;
128: for (i=0; i < MSG_BSIZE; i++)
129: msgbufp->msg_bufc[i] = 0;
130: }
131: LOG_UNLOCK();
132: unix_release();
133: return (0);
134: }
135:
136: /*ARGSUSED*/
137: int
138: logclose(dev, flag)
139: dev_t dev;
140: {
141: int oldpri;
142: LOG_LOCK();
143: log_open = 0;
144: selwakeup(&logsoftc.sc_selp);
145: oldpri = splhigh();
146: selthreadclear(&logsoftc.sc_selp);
147: splx(oldpri);
148: LOG_UNLOCK();
149: return (0);
150: }
151:
152: /*ARGSUSED*/
153: int
154: logread(dev, uio, flag)
155: dev_t dev;
156: struct uio *uio;
157: int flag;
158: {
159: register long l;
160: register int s;
161: int error = 0;
162:
163: s = splhigh();
164: while (msgbufp->msg_bufr == msgbufp->msg_bufx) {
165: if (flag & IO_NDELAY) {
166: splx(s);
167: return (EWOULDBLOCK);
168: }
169: if (logsoftc.sc_state & LOG_NBIO) {
170: splx(s);
171: return (EWOULDBLOCK);
172: }
173: logsoftc.sc_state |= LOG_RDWAIT;
174: if (error = tsleep((caddr_t)msgbufp, LOG_RDPRI | PCATCH,
175: "klog", 0)) {
176: splx(s);
177: return (error);
178: }
179: }
180: splx(s);
181: logsoftc.sc_state &= ~LOG_RDWAIT;
182:
183: while (uio->uio_resid > 0) {
184: l = msgbufp->msg_bufx - msgbufp->msg_bufr;
185: if (l < 0)
186: l = MSG_BSIZE - msgbufp->msg_bufr;
187: l = min(l, uio->uio_resid);
188: if (l == 0)
189: break;
190: error = uiomove((caddr_t)&msgbufp->msg_bufc[msgbufp->msg_bufr],
191: (int)l, uio);
192: if (error)
193: break;
194: msgbufp->msg_bufr += l;
195: if (msgbufp->msg_bufr < 0 || msgbufp->msg_bufr >= MSG_BSIZE)
196: msgbufp->msg_bufr = 0;
197: }
198: return (error);
199: }
200:
201: /*ARGSUSED*/
202: int
203: logselect(dev, rw, p)
204: dev_t dev;
205: int rw;
206: struct proc *p;
207: {
208: int s = splhigh();
209:
210: switch (rw) {
211:
212: case FREAD:
213: if (msgbufp->msg_bufr != msgbufp->msg_bufx) {
214: splx(s);
215: return (1);
216: }
217: selrecord(p, &logsoftc.sc_selp);
218: break;
219: }
220: splx(s);
221: return (0);
222: }
223:
224: void
225: logwakeup()
226: {
227: struct proc *p;
228: int pgid;
229: boolean_t funnel_state;
230:
231: if (!log_open)
232: return;
233: funnel_state = thread_set_funneled(TRUE);
234: selwakeup(&logsoftc.sc_selp);
235: if (logsoftc.sc_state & LOG_ASYNC) {
236: unix_master();
237: LOG_LOCK();
238: pgid = logsoftc.sc_pgid;
239: LOG_UNLOCK();
240: if (pgid < 0)
241: gsignal(-pgid, SIGIO);
242: else if (p = pfind(pgid))
243: psignal(p, SIGIO);
244: unix_release();
245: }
246: if (logsoftc.sc_state & LOG_RDWAIT) {
247: wakeup((caddr_t)msgbufp);
248: logsoftc.sc_state &= ~LOG_RDWAIT;
249: }
250: (void) thread_set_funneled(funnel_state);
251: }
252:
253: /*ARGSUSED*/
254: int
255: logioctl(com, data, flag)
256: caddr_t data;
257: {
258: long l;
259: int s;
260:
261: switch (com) {
262:
263: /* return number of characters immediately available */
264: case FIONREAD:
265: s = splhigh();
266: l = msgbufp->msg_bufx - msgbufp->msg_bufr;
267: splx(s);
268: if (l < 0)
269: l += MSG_BSIZE;
270: *(off_t *)data = l;
271: break;
272:
273: case FIONBIO:
274: if (*(int *)data)
275: logsoftc.sc_state |= LOG_NBIO;
276: else
277: logsoftc.sc_state &= ~LOG_NBIO;
278: break;
279:
280: case FIOASYNC:
281: if (*(int *)data)
282: logsoftc.sc_state |= LOG_ASYNC;
283: else
284: logsoftc.sc_state &= ~LOG_ASYNC;
285: break;
286:
287: case TIOCSPGRP:
288: LOG_LOCK();
289: logsoftc.sc_pgid = *(int *)data;
290: LOG_UNLOCK();
291: break;
292:
293: case TIOCGPGRP:
294: LOG_LOCK();
295: *(int *)data = logsoftc.sc_pgid;
296: LOG_UNLOCK();
297: break;
298:
299: default:
300: return (-1);
301: }
302: return (0);
303: }
304:
305: void
306: log_init()
307: {
308: msgbufp = &temp_msgbuf;
309: LOG_LOCK_INIT();
310: }
311:
312: void
313: log_putc(char c)
314: {
315: register struct msgbuf *mbp;
316:
317: if (msgbufp == NULL)
318: msgbufp =&temp_msgbuf;
319:
320: mbp = msgbufp;
321: if (mbp-> msg_magic != MSG_MAGIC) {
322: register int i;
323:
324: mbp->msg_magic = MSG_MAGIC;
325: mbp->msg_bufx = mbp->msg_bufr = 0;
326: for (i=0; i < MSG_BSIZE; i++)
327: mbp->msg_bufc[i] = 0;
328: }
329: mbp->msg_bufc[mbp->msg_bufx++] = c;
330: if (mbp->msg_bufx < 0 || mbp->msg_bufx >= MSG_BSIZE)
331: mbp->msg_bufx = 0;
332: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.