X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/e5568f75972dfc723778653c11cb6b4dc825716a..15129b1c8dbb3650c63b70adb1cad9af601c6c17:/bsd/kern/subr_prf.c diff --git a/bsd/kern/subr_prf.c b/bsd/kern/subr_prf.c index 8bcf0e3ce..5bb098bbb 100644 --- a/bsd/kern/subr_prf.c +++ b/bsd/kern/subr_prf.c @@ -1,23 +1,29 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. * - * @APPLE_LICENSE_HEADER_END@ + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ /*- @@ -77,14 +83,13 @@ #include #include -#include #include #include #include -#include +#include #include #include -#include +#include #include #include #include @@ -96,6 +101,13 @@ #include #include +/* for vaddlog(): the following are implemented in osfmk/kern/printf.c */ +extern void bsd_log_lock(void); +extern void bsd_log_unlock(void); + +/* Keep this around only because it's exported */ +void _printf(int, struct tty *, const char *, ...); + struct snprintf_arg { char *str; size_t remain; @@ -109,34 +121,24 @@ struct snprintf_arg { */ extern const char *panicstr; -extern cnputc(); /* standard console putc */ -int (*v_putc)() = cnputc; /* routine to putc on virtual console */ +extern void cnputc(char); /* standard console putc */ +void (*v_putc)(char) = cnputc; /* routine to putc on virtual console */ extern struct tty cons; /* standard console tty */ extern struct tty *constty; /* pointer to console "window" tty */ extern int __doprnt(const char *fmt, - va_list *argp, - void (*putc)(int, void *arg), + va_list argp, + void (*)(int, void *), void *arg, int radix); /* * Record cpu that panic'd and lock around panic data */ +static void printn(uint32_t n, int b, int flags, struct tty *ttyp, int zf, int fld_size); -static void puts(const char *s, int flags, struct tty *ttyp); -static void printn(u_long n, int b, int flags, struct tty *ttyp, int zf, int fld_size); - -/* MP printf stuff */ -decl_simple_lock_data(,printf_lock) -#if NCPUS > 1 -boolean_t new_printf_cpu_number; /* do we need to output who we are */ -#endif - -extern void logwakeup(); -extern void halt_cpu(); -extern boot(); - +extern void logwakeup(void); +extern void halt_cpu(void); static void snprintf_func(int ch, void *arg); @@ -156,64 +158,90 @@ static void putchar(int c, void *arg); void uprintf(const char *fmt, ...) { - register struct proc *p = current_proc(); + struct proc *p = current_proc(); struct putchar_args pca; va_list ap; + struct session *sessp; - pca.flags = TOTTY; - pca.tty = (struct tty *)p->p_session->s_ttyp; + sessp = proc_session(p); - if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) { + if (p->p_flag & P_CONTROLT && sessp != SESSION_NULL && sessp->s_ttyvp) { + pca.flags = TOTTY; + pca.tty = SESSION_TP(sessp); + if (pca.tty != NULL) + tty_lock(pca.tty); va_start(ap, fmt); - __doprnt(fmt, &ap, putchar, &pca, 10); + __doprnt(fmt, ap, putchar, &pca, 10); va_end(ap); + if (pca.tty != NULL) + tty_unlock(pca.tty); } + if (sessp != SESSION_NULL) + session_rele(sessp); } tpr_t -tprintf_open(p) - register struct proc *p; +tprintf_open(struct proc *p) { - if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) { - SESSHOLD(p->p_session); - return ((tpr_t) p->p_session); + struct session * sessp; + + sessp = proc_session(p); + + if (p->p_flag & P_CONTROLT && sessp->s_ttyvp) { + return ((tpr_t)sessp); } + if (sessp != SESSION_NULL) + session_rele(sessp); + return ((tpr_t) NULL); } void -tprintf_close(sess) - tpr_t sess; +tprintf_close(tpr_t sessp) { - if (sess) - SESSRELE((struct session *) sess); + if (sessp) + session_rele((struct session *) sessp); } /* * tprintf prints on the controlling terminal associated * with the given session. + * + * NOTE: No one else should call this function!!! */ void tprintf(tpr_t tpr, const char *fmt, ...) { - register struct session *sess = (struct session *)tpr; - struct tty *tp = NULL; + struct session *sess = (struct session *)tpr; + struct tty *tp = TTY_NULL; int flags = TOLOG; va_list ap; struct putchar_args pca; logpri(LOG_INFO); - if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) { - flags |= TOTTY; - tp = sess->s_ttyp; + + if (sess && (tp = SESSION_TP(sess)) != TTY_NULL) { + /* ttycheckoutq(), tputchar() require a locked tp */ + tty_lock(tp); + if(ttycheckoutq(tp, 0)) { + flags |= TOTTY; + /* going to the tty; leave locked */ + } else { + /* not going to the tty... */ + tty_unlock(tp); + tp = TTY_NULL; + } } pca.flags = flags; pca.tty = tp; va_start(ap, fmt); - __doprnt(fmt, &ap, putchar, &pca, 10); + __doprnt(fmt, ap, putchar, &pca, 10); va_end(ap); + if (tp != NULL) + tty_unlock(tp); /* lock/unlock is guarded by tp, above */ + logwakeup(); } @@ -221,6 +249,10 @@ tprintf(tpr_t tpr, const char *fmt, ...) * Ttyprintf displays a message on a tty; it should be used only by * the tty driver, or anything that knows the underlying tty will not * be revoke(2)'d away. Other callers should use tprintf. + * + * Locks: It is assumed that the tty_lock() is held over the call + * to this function. Ensuring this is the responsibility + * of the caller. */ void ttyprintf(struct tty *tp, const char *fmt, ...) @@ -233,118 +265,104 @@ ttyprintf(struct tty *tp, const char *fmt, ...) pca.tty = tp; va_start(ap, fmt); - __doprnt(fmt, &ap, putchar, &pca, 10); + __doprnt(fmt, ap, putchar, &pca, 10); va_end(ap); } } + extern int log_open; void -logpri(level) - int level; +logpri(int level) { struct putchar_args pca; pca.flags = TOLOG; pca.tty = NULL; putchar('<', &pca); - printn((u_long)level, 10, TOLOG, (struct tty *)0, 0, 0); + printn((uint32_t)level, 10, TOLOG, (struct tty *)0, 0, 0); putchar('>', &pca); } -void -addlog(const char *fmt, ...) +static void +_logtime(const char *fmt, ...) { - register s = splhigh(); va_list ap; + va_start(ap, fmt); + vaddlog(fmt, ap); + va_end(ap); +} + +void +logtime(time_t secs) +{ + _logtime(" 0 [Time %ld] [Message ", secs); +} + +int +vaddlog(const char *fmt, va_list ap) +{ struct putchar_args pca; - pca.flags = TOLOG; + pca.flags = TOLOGLOCKED; pca.tty = NULL; - va_start(ap, fmt); - __doprnt(fmt, &ap, putchar, &pca, 10); - - splx(s); if (!log_open) { - pca.flags = TOCONS; - __doprnt(fmt, &ap, putchar, &pca, 10); + pca.flags |= TOCONS; } - va_end(ap); - logwakeup(); -} -void _printf(int flags, struct tty *ttyp, const char *format, ...) -{ - va_list ap; - struct putchar_args pca; - pca.flags = flags; - pca.tty = ttyp; + bsd_log_lock(); + __doprnt(fmt, ap, putchar, &pca, 10); + bsd_log_unlock(); - va_start(ap, format); - __doprnt(format, &ap, putchar, &pca, 10); - va_end(ap); + logwakeup(); + return 0; } -int prf(const char *fmt, va_list ap, int flags, struct tty *ttyp) +void +_printf(int flags, struct tty *ttyp, const char *format, ...) { + va_list ap; struct putchar_args pca; pca.flags = flags; pca.tty = ttyp; -#if NCPUS > 1 - int cpun = cpu_number(); - - if(ttyp == 0) { - simple_lock(&printf_lock); - } else - TTY_LOCK(ttyp); - - if (cpun != master_cpu) - new_printf_cpu_number = TRUE; + if (ttyp != NULL) { + tty_lock(ttyp); + + va_start(ap, format); + __doprnt(format, ap, putchar, &pca, 10); + va_end(ap); - if (new_printf_cpu_number) { - putchar('{', flags, ttyp); - printn((u_long)cpun, 10, flags, ttyp, 0, 0); - putchar('}', flags, ttyp); + tty_unlock(ttyp); } -#endif /* NCPUS > 1 */ - - __doprnt(fmt, &ap, putchar, &pca, 10); - -#if NCPUS > 1 - if(ttyp == 0) { - simple_unlock(&printf_lock); - } else - TTY_UNLOCK(ttyp); -#endif - - return 0; } -static void puts(const char *s, int flags, struct tty *ttyp) +int +prf(const char *fmt, va_list ap, int flags, struct tty *ttyp) { - register char c; struct putchar_args pca; pca.flags = flags; pca.tty = ttyp; - while ((c = *s++)) - putchar(c, &pca); + __doprnt(fmt, ap, putchar, &pca, 10); + + return 0; } /* * Printn prints a number n in base b. * We don't use recursion to avoid deep kernel stacks. */ -static void printn(u_long n, int b, int flags, struct tty *ttyp, int zf, int fld_size) +static void +printn(uint32_t n, int b, int flags, struct tty *ttyp, int zf, int fld_size) { char prbuf[11]; - register char *cp; + char *cp; struct putchar_args pca; pca.flags = flags; @@ -385,13 +403,15 @@ void tablefull(const char *tab) * Print a character on console or users terminal. * If destination is console then the last MSGBUFS characters * are saved in msgbuf for inspection later. + * + * Locks: If TOTTY is set, we assume that the tty lock is held + * over the call to this function. */ /*ARGSUSED*/ void putchar(int c, void *arg) { struct putchar_args *pca = arg; - register struct msgbuf *mbp; char **sp = (char**) pca->tty; if (panicstr) @@ -405,6 +425,8 @@ putchar(int c, void *arg) constty = 0; if ((pca->flags & TOLOG) && c != '\0' && c != '\r' && c != 0177) log_putc(c); + if ((pca->flags & TOLOGLOCKED) && c != '\0' && c != '\r' && c != 0177) + log_putc_locked(c); if ((pca->flags & TOCONS) && constty == 0 && c != '\0') (*v_putc)(c); if (pca->flags & TOSTR) { @@ -413,10 +435,23 @@ putchar(int c, void *arg) } } +int +vprintf(const char *fmt, va_list ap) +{ + struct putchar_args pca; + + pca.flags = TOLOG | TOCONS; + pca.tty = NULL; + __doprnt(fmt, ap, putchar, &pca, 10); + return 0; +} /* * Scaled down version of vsprintf(3). + * + * Deprecation Warning: + * vsprintf() is being deprecated. Please use vsnprintf() instead. */ int vsprintf(char *buf, const char *cfmt, va_list ap) @@ -427,7 +462,7 @@ vsprintf(char *buf, const char *cfmt, va_list ap) info.str = buf; info.remain = 999999; - retval = __doprnt(cfmt, &ap, snprintf_func, &info, 10); + retval = __doprnt(cfmt, ap, snprintf_func, &info, 10); if (info.remain >= 1) { *info.str++ = '\0'; } @@ -460,7 +495,7 @@ vsnprintf(char *str, size_t size, const char *format, va_list ap) info.str = str; info.remain = size; - retval = __doprnt(format, &ap, snprintf_func, &info, 10); + retval = __doprnt(format, ap, snprintf_func, &info, 10); if (info.remain >= 1) *info.str++ = '\0'; return retval; @@ -480,7 +515,7 @@ snprintf_func(int ch, void *arg) int kvprintf(char const *fmt, void (*func)(int, void*), void *arg, int radix, va_list ap) { - __doprnt(fmt, &ap, func, arg, radix); + __doprnt(fmt, ap, func, arg, radix); return 0; }