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