|
|
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.