]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/subr_prf.c
xnu-7195.50.7.100.1.tar.gz
[apple/xnu.git] / bsd / kern / subr_prf.c
index 5bb098bbbd2e62daf354349227adc90c641c608f..d5d5c7de7875f4be0087c817ee8e902b07f319ab 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- * 
+ *
  * 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
  * 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.
- * 
+ *
  * 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,
@@ -22,7 +22,7 @@
  * 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_OSREFERENCE_LICENSE_HEADER_END@
  */
 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
@@ -74,8 +74,8 @@
  *     in bsd/dev/XXX/cons.c
  *
  * 26-MAR-1997 Umesh Vaishampayan (umeshv@NeXT.com
- *     Fixed tharshing format in many functions. Cleanup.
- * 
+ *      Fixed tharshing format in many functions. Cleanup.
+ *
  * 17-Jun-1995 Mac Gillon (mgillon) at NeXT
  *     Purged old history
  *     New version based on 4.4 and NS3.3
 #include <sys/lock.h>
 #include <sys/subr_prf.h>
 
-#include <kern/cpu_number.h>   /* for cpu_number() */
-#include <machine/spl.h>
+#include <kern/cpu_number.h>    /* for cpu_number() */
 #include <libkern/libkern.h>
+#include <os/log_private.h>
 
 /* for vaddlog(): the following are implemented in osfmk/kern/printf.c  */
-extern void bsd_log_lock(void);
+extern bool bsd_log_lock(bool);
 extern void bsd_log_unlock(void);
 
+uint32_t vaddlog_msgcount = 0;
+uint32_t vaddlog_msgcount_dropped = 0;
+
 /* Keep this around only because it's exported */
 void _printf(int, struct tty *, const char *, ...);
 
@@ -116,29 +119,28 @@ struct snprintf_arg {
 
 /*
  * In case console is off,
- * panicstr contains argument to last
+ * debugger_panic_str contains argument to last
  * call to panic.
  */
-extern const char      *panicstr;
+extern const char       *debugger_panic_str;
 
-extern void cnputc(char);              /* standard console putc */
-void   (*v_putc)(char) = cnputc;       /* routine to putc on virtual console */
+extern  void cnputc(char);              /* standard console putc */
 
-extern struct tty cons;                /* standard console tty */
-extern struct  tty *constty;           /* pointer to console "window" tty */
+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       (*)(int, void *),
-                                        void       *arg,
-                                        int        radix);
+    va_list    argp,
+    void       (*)(int, void *),
+    void       *arg,
+    int        radix,
+    int        is_log);
 
 /*
  *     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);
 
-extern void logwakeup(void);
-extern void halt_cpu(void);
+extern  void logwakeup(struct msgbuf *);
+extern  void halt_cpu(void);
 
 static void
 snprintf_func(int ch, void *arg);
@@ -146,6 +148,7 @@ snprintf_func(int ch, void *arg);
 struct putchar_args {
        int flags;
        struct tty *tty;
+       bool last_char_was_cr;
 };
 static void putchar(int c, void *arg);
 
@@ -162,22 +165,25 @@ uprintf(const char *fmt, ...)
        struct putchar_args pca;
        va_list ap;
        struct session *sessp;
-       
+
        sessp = proc_session(p);
 
        if (p->p_flag & P_CONTROLT && sessp != SESSION_NULL && sessp->s_ttyvp) {
                pca.flags = TOTTY;
                pca.tty   = SESSION_TP(sessp);
-               if (pca.tty != NULL)
+               if (pca.tty != NULL) {
                        tty_lock(pca.tty);
+               }
                va_start(ap, fmt);
-               __doprnt(fmt, ap, putchar, &pca, 10);
+               __doprnt(fmt, ap, putchar, &pca, 10, FALSE);
                va_end(ap);
-               if (pca.tty != NULL)
-               tty_unlock(pca.tty);
+               if (pca.tty != NULL) {
+                       tty_unlock(pca.tty);
+               }
        }
-       if (sessp != SESSION_NULL)
+       if (sessp != SESSION_NULL) {
                session_rele(sessp);
+       }
 }
 
 tpr_t
@@ -188,19 +194,21 @@ tprintf_open(struct proc *p)
        sessp = proc_session(p);
 
        if (p->p_flag & P_CONTROLT && sessp->s_ttyvp) {
-               return ((tpr_t)sessp);
+               return (tpr_t)sessp;
        }
-       if (sessp != SESSION_NULL)
+       if (sessp != SESSION_NULL) {
                session_rele(sessp);
+       }
 
-       return ((tpr_t) NULL);
+       return (tpr_t) NULL;
 }
 
 void
 tprintf_close(tpr_t sessp)
 {
-       if (sessp)
+       if (sessp) {
                session_rele((struct session *) sessp);
+       }
 }
 
 /*
@@ -213,36 +221,27 @@ void
 tprintf(tpr_t tpr, const char *fmt, ...)
 {
        struct session *sess = (struct session *)tpr;
-       struct tty *tp = TTY_NULL;
-       int flags = TOLOG;
+       struct tty *tp;
        va_list ap;
        struct putchar_args pca;
 
-       logpri(LOG_INFO);
-
        if (sess && (tp = SESSION_TP(sess)) != TTY_NULL) {
                /* ttycheckoutq(), tputchar() require a locked tp */
                tty_lock(tp);
-               if(ttycheckoutq(tp, 0)) {
-                       flags |= TOTTY;
+               if (ttycheckoutq(tp, 0)) {
+                       pca.flags = TOTTY;
                        /* going to the tty; leave locked */
-               } else {
-                       /* not going to the tty... */
-                       tty_unlock(tp);
-                       tp = TTY_NULL;
+                       pca.tty = tp;
+                       va_start(ap, fmt);
+                       __doprnt(fmt, ap, putchar, &pca, 10, FALSE);
+                       va_end(ap);
                }
+               tty_unlock(tp);
        }
-       
-       pca.flags = flags;
-       pca.tty   = tp;
+
        va_start(ap, fmt);
-       __doprnt(fmt, ap, putchar, &pca, 10);
+       os_log_with_args(OS_LOG_DEFAULT, OS_LOG_TYPE_DEFAULT, fmt, ap, __builtin_return_address(0));
        va_end(ap);
-
-       if (tp != NULL)
-               tty_unlock(tp); /* lock/unlock is guarded by tp, above */
-
-       logwakeup();
 }
 
 /*
@@ -263,61 +262,51 @@ ttyprintf(struct tty *tp, const char *fmt, ...)
                struct putchar_args pca;
                pca.flags = TOTTY;
                pca.tty   = tp;
-               
+
                va_start(ap, fmt);
-               __doprnt(fmt, ap, putchar, &pca, 10);
+               __doprnt(fmt, ap, putchar, &pca, 10, TRUE);
                va_end(ap);
        }
 }
 
-
-extern int log_open;
-
-
 void
-logpri(int level)
+logtime(time_t secs)
 {
-       struct putchar_args pca;
-       pca.flags = TOLOG;
-       pca.tty   = NULL;
-       
-       putchar('<', &pca);
-       printn((uint32_t)level, 10, TOLOG, (struct tty *)0, 0, 0);
-       putchar('>', &pca);
+       printf("Time 0x%lx Message ", secs);
 }
 
 static void
-_logtime(const char *fmt, ...)
+putchar_asl(int c, void *arg)
 {
-       va_list ap;
-       va_start(ap, fmt);
-       vaddlog(fmt, ap);
-       va_end(ap);
-}
+       struct putchar_args *pca = arg;
 
-void
-logtime(time_t secs)
-{
-       _logtime("         0 [Time %ld] [Message ", secs);
+       if ((pca->flags & TOLOGLOCKED) && c != '\0' && c != '\r' && c != 0177) {
+               log_putc_locked(aslbufp, (char)c);
+       }
+       putchar(c, arg);
 }
 
+/*
+ * Vestigial support for kern_asl_msg() via /dev/klog
+ */
 int
 vaddlog(const char *fmt, va_list ap)
 {
-       struct putchar_args pca;
-
-       pca.flags = TOLOGLOCKED;
-       pca.tty   = NULL;
-
-       if (!log_open) {
-               pca.flags |= TOCONS;
+       if (!bsd_log_lock(oslog_is_safe())) {
+               os_atomic_inc(&vaddlog_msgcount_dropped, relaxed);
+               return 1;
        }
 
-       bsd_log_lock();
-       __doprnt(fmt, ap, putchar, &pca, 10);
+       struct putchar_args pca = {
+               .flags = TOLOGLOCKED,
+               .tty = NULL,
+       };
+
+       __doprnt(fmt, ap, putchar_asl, &pca, 10, TRUE);
        bsd_log_unlock();
-       
-       logwakeup();
+       logwakeup(NULL);
+
+       os_atomic_inc(&vaddlog_msgcount, relaxed);
        return 0;
 }
 
@@ -332,9 +321,9 @@ _printf(int flags, struct tty *ttyp, const char *format, ...)
 
        if (ttyp != NULL) {
                tty_lock(ttyp);
-       
+
                va_start(ap, format);
-               __doprnt(format, ap, putchar, &pca, 10);
+               __doprnt(format, ap, putchar, &pca, 10, TRUE);
                va_end(ap);
 
                tty_unlock(ttyp);
@@ -349,52 +338,16 @@ prf(const char *fmt, va_list ap, int flags, struct tty *ttyp)
        pca.flags = flags;
        pca.tty   = ttyp;
 
-       __doprnt(fmt, ap, putchar, &pca, 10);
+       __doprnt(fmt, ap, putchar, &pca, 10, TRUE);
 
        return 0;
 }
 
-/*
- * Printn prints a number n in base b.
- * We don't use recursion to avoid deep kernel stacks.
- */
-static void
-printn(uint32_t n, int b, int flags, struct tty *ttyp, int zf, int fld_size)
-{
-       char prbuf[11];
-       char *cp;
-       struct putchar_args pca;
-
-       pca.flags = flags;
-       pca.tty   = ttyp;
-
-       if (b == 10 && (int)n < 0) {
-               putchar('-', &pca);
-               n = (unsigned)(-(int)n);
-       }
-       cp = prbuf;
-       do {
-               *cp++ = "0123456789abcdef"[n%b];
-               n /= b;
-       } while (n);
-       if (fld_size) {
-               for (fld_size -= cp - prbuf; fld_size > 0; fld_size--)
-                       if (zf)
-                               putchar('0', &pca);
-                       else
-                               putchar(' ', &pca);
-       }
-       do
-               putchar(*--cp, &pca);
-       while (cp > prbuf);
-}
-
-
-
 /*
  * Warn that a system table is full.
  */
-void tablefull(const char *tab)
+void
+tablefull(const char *tab)
 {
        log(LOG_ERR, "%s: table is full\n", tab);
 }
@@ -414,44 +367,68 @@ putchar(int c, void *arg)
        struct putchar_args *pca = arg;
        char **sp = (char**) pca->tty;
 
-       if (panicstr)
+       if (debugger_panic_str) {
                constty = 0;
+       }
        if ((pca->flags & TOCONS) && pca->tty == NULL && constty) {
                pca->tty = constty;
                pca->flags |= TOTTY;
        }
        if ((pca->flags & TOTTY) && pca->tty && tputchar(c, pca->tty) < 0 &&
-           (pca->flags & TOCONS) && pca->tty == constty)
+           (pca->flags & TOCONS) && pca->tty == constty) {
                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 & TOLOG) && c != '\0' && c != '\r' && c != 0177) {
+               log_putc((char)c);
+       }
+       if ((pca->flags & TOLOGLOCKED) && c != '\0' && c != '\r' && c != 0177) {
+               log_putc_locked(msgbufp, (char)c);
+       }
+       if ((pca->flags & TOCONS) && constty == 0 && c != '\0') {
+               cnputc((char)c);
+       }
        if (pca->flags & TOSTR) {
-               **sp = c;
+               **sp = (char)c;
                (*sp)++;
        }
+
+       pca->last_char_was_cr = ('\n' == c);
 }
 
-int
-vprintf(const char *fmt, va_list ap)
+bool
+printf_log_locked(bool addcr, const char *fmt, ...)
+{
+       bool retval;
+       va_list args;
+
+       va_start(args, fmt);
+       retval = vprintf_log_locked(fmt, args, addcr);
+       va_end(args);
+
+       return retval;
+}
+
+bool
+vprintf_log_locked(const char *fmt, va_list ap, bool addcr)
 {
        struct putchar_args pca;
 
-       pca.flags = TOLOG | TOCONS;
+       pca.flags = TOLOGLOCKED;
        pca.tty   = NULL;
-       __doprnt(fmt, ap, putchar, &pca, 10);
-       return 0;
+       pca.last_char_was_cr = false;
+       __doprnt(fmt, ap, putchar, &pca, 10, TRUE);
+       if (addcr) {
+               putchar('\n', &pca);
+       }
+       return pca.last_char_was_cr;
 }
 
-
+#if CONFIG_VSPRINTF
 /*
  * Scaled down version of vsprintf(3).
  *
  * Deprecation Warning:
- *     vsprintf() is being deprecated. Please use vsnprintf() instead. 
+ *     vsprintf() is being deprecated. Please use vsnprintf() instead.
  */
 int
 vsprintf(char *buf, const char *cfmt, va_list ap)
@@ -462,12 +439,13 @@ 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, FALSE);
        if (info.remain >= 1) {
                *info.str++ = '\0';
        }
        return 0;
 }
+#endif  /* CONFIG_VSPRINTF */
 
 /*
  * Scaled down version of snprintf(3).
@@ -481,7 +459,7 @@ snprintf(char *str, size_t size, const char *format, ...)
        va_start(ap, format);
        retval = vsnprintf(str, size, format, ap);
        va_end(ap);
-       return(retval);
+       return retval;
 }
 
 /*
@@ -495,19 +473,44 @@ 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);
-       if (info.remain >= 1)
+       retval = __doprnt(format, ap, snprintf_func, &info, 10, FALSE);
+       if (info.remain >= 1) {
                *info.str++ = '\0';
+       }
        return retval;
 }
 
+int
+vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
+{
+       ssize_t ssize = size;
+       int i;
+
+       i = vsnprintf(buf, size, fmt, args);
+
+       return (i >= ssize) ? (int)(ssize - 1) : i;
+}
+
+int
+scnprintf(char *buf, size_t size, const char *fmt, ...)
+{
+       va_list args;
+       int i;
+
+       va_start(args, fmt);
+       i = vscnprintf(buf, size, fmt, args);
+       va_end(args);
+
+       return i;
+}
+
 static void
 snprintf_func(int ch, void *arg)
 {
        struct snprintf_arg *const info = arg;
 
        if (info->remain >= 2) {
-               *info->str++ = ch;
+               *info->str++ = (char)ch;
                info->remain--;
        }
 }
@@ -515,7 +518,6 @@ 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, TRUE);
        return 0;
 }
-