* 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,
* 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 */
* 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 *, ...);
/*
* 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);
struct putchar_args {
int flags;
struct tty *tty;
+ bool last_char_was_cr;
};
static void putchar(int c, void *arg);
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
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);
+ }
}
/*
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();
}
/*
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;
}
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);
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);
}
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)
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).
va_start(ap, format);
retval = vsnprintf(str, size, format, ap);
va_end(ap);
- return(retval);
+ return retval;
}
/*
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--;
}
}
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;
}
-