Index: conf/options =================================================================== RCS file: /usr/local/arch/ncvs/src/sys/conf/options,v retrieving revision 1.510.2.23 diff -u -r1.510.2.23 options --- conf/options 14 Sep 2007 22:44:37 -0000 1.510.2.23 +++ conf/options 19 Oct 2007 13:00:04 -0000 @@ -692,6 +692,9 @@ SC_RENDER_DEBUG opt_syscons.h SC_TWOBUTTON_MOUSE opt_syscons.h +# options for printf +PRINTF_BUFR_SIZE opt_printf.h + # kbd options KBD_DISABLE_KEYMAP_LOAD opt_kbd.h KBD_INSTALL_CDEV opt_kbd.h Index: ia64/ia64/genassym.c =================================================================== RCS file: /usr/local/arch/ncvs/src/sys/ia64/ia64/genassym.c,v retrieving revision 1.41.2.1 diff -u -r1.41.2.1 genassym.c --- ia64/ia64/genassym.c 28 Jan 2006 18:40:55 -0000 1.41.2.1 +++ ia64/ia64/genassym.c 19 Oct 2007 13:00:11 -0000 @@ -91,6 +91,7 @@ ASSYM(PAGE_SHIFT, PAGE_SHIFT); ASSYM(PAGE_SIZE, PAGE_SIZE); +ASSYM(PC_CONS_BUFR, offsetof(struct pcpu, pc_cons_bufr)); ASSYM(PC_CPUID, offsetof(struct pcpu, pc_cpuid)); ASSYM(PC_CURRENT_PMAP, offsetof(struct pcpu, pc_current_pmap)); ASSYM(PC_CURTHREAD, offsetof(struct pcpu, pc_curthread)); Index: kern/subr_prf.c =================================================================== RCS file: /usr/local/arch/ncvs/src/sys/kern/subr_prf.c,v retrieving revision 1.116.2.4 diff -u -r1.116.2.4 subr_prf.c --- kern/subr_prf.c 22 May 2006 23:51:14 -0000 1.116.2.4 +++ kern/subr_prf.c 19 Oct 2007 13:00:12 -0000 @@ -38,6 +38,7 @@ __FBSDID("$FreeBSD: src/sys/kern/subr_prf.c,v 1.116.2.4 2006/05/22 23:51:14 jkim Exp $"); #include "opt_ddb.h" +#include "opt_printf.h" #include #include @@ -78,6 +79,10 @@ int flags; int pri; struct tty *tty; + char *p_bufr; + size_t n_bufr; + char *p_next; + size_t remain; }; struct snprintf_arg { @@ -92,7 +97,6 @@ static char *ksprintn(char *nbuf, uintmax_t num, int base, int *len, int upper); static void snprintf_func(int ch, void *arg); -static int consintr = 1; /* Ok to handle console interrupts? */ static int msgbufmapped; /* Set when safe to use msgbuf */ int msgbuftrigger; @@ -234,6 +238,7 @@ pca.tty = NULL; pca.pri = level; pca.flags = log_open ? TOLOG : TOCONS; + pca.p_bufr = NULL; va_start(ap, fmt); kvprintf(fmt, putchar, &pca, 10, ap); @@ -284,43 +289,104 @@ printf(const char *fmt, ...) { va_list ap; - int savintr; struct putchar_arg pca; int retval; +#ifdef PRINTF_BUFR_SIZE + char bufr[PRINTF_BUFR_SIZE]; +#endif - savintr = consintr; /* disable interrupts */ - consintr = 0; va_start(ap, fmt); pca.tty = NULL; pca.flags = TOCONS | TOLOG; pca.pri = -1; +#ifdef PRINTF_BUFR_SIZE + pca.p_bufr = bufr; + pca.p_next = pca.p_bufr; + pca.n_bufr = sizeof(bufr); + pca.remain = sizeof(bufr); + *pca.p_next = '\0'; +#else + /* Don't buffer console output. */ + pca.p_bufr = NULL; +#endif + retval = kvprintf(fmt, putchar, &pca, 10, ap); va_end(ap); + + /* Write any buffered console output: */ + if (*pca.p_bufr != '\0') + cnputs(pca.p_bufr); + if (!panicstr) msgbuftrigger = 1; - consintr = savintr; /* reenable interrupts */ + return (retval); } int vprintf(const char *fmt, va_list ap) { - int savintr; struct putchar_arg pca; int retval; +#ifdef PRINTF_BUFR_SIZE + char bufr[PRINTF_BUFR_SIZE]; +#endif - savintr = consintr; /* disable interrupts */ - consintr = 0; pca.tty = NULL; pca.flags = TOCONS | TOLOG; pca.pri = -1; +#ifdef PRINTF_BUFR_SIZE + pca.p_bufr = bufr; + pca.p_next = pca.p_bufr; + pca.n_bufr = sizeof(bufr); + pca.remain = sizeof(bufr); + *pca.p_next = '\0'; +#else + /* Don't buffer console output. */ + pca.p_bufr = NULL; +#endif + retval = kvprintf(fmt, putchar, &pca, 10, ap); + + /* Write any buffered console output: */ + if (*pca.p_bufr != '\0') + cnputs(pca.p_bufr); + if (!panicstr) msgbuftrigger = 1; - consintr = savintr; /* reenable interrupts */ + return (retval); } +static void +putcons(int c, struct putchar_arg *ap) +{ + /* Check if no console output buffer was provided. */ + if (ap->p_bufr == NULL) + /* Output direct to the console. */ + cnputc(c); + else { + /* Buffer the character: */ + if (c == '\n') { + *ap->p_next++ = '\r'; + ap->remain--; + } + *ap->p_next++ = c; + ap->remain--; + + /* Always leave the buffer zero terminated. */ + *ap->p_next = '\0'; + + /* Check if the buffer needs to be flushed. */ + if (ap->remain < 3 || c == '\n') { + cnputs(ap->p_bufr); + ap->p_next = ap->p_bufr; + ap->remain = ap->n_bufr; + *ap->p_next = '\0'; + } + } +} + /* * Print a character on console or users terminal. If destination is * the console then the last bunch of characters are saved in msgbuf for @@ -331,17 +397,15 @@ { struct putchar_arg *ap = (struct putchar_arg*) arg; struct tty *tp = ap->tty; - int consdirect, flags = ap->flags; + int flags = ap->flags; - consdirect = ((flags & TOCONS) && constty == NULL); /* Don't use the tty code after a panic or while in ddb. */ - if (panicstr) - consdirect = 1; - if (kdb_active) - consdirect = 1; - if (consdirect) { + if (kdb_active) { if (c != '\0') cnputc(c); + } else if (panicstr || ((flags & TOCONS) && constty == NULL)) { + if (c != '\0') + putcons(c, ap); } else { if ((flags & TOTTY) && tp != NULL) tputchar(c, tp); @@ -349,7 +413,7 @@ if (constty != NULL) msgbuf_addchar(&consmsgbuf, c); if (always_console_output && c != '\0') - cnputc(c); + putcons(c, ap); } } if ((flags & TOLOG)) Index: kern/tty_cons.c =================================================================== RCS file: /usr/local/arch/ncvs/src/sys/kern/tty_cons.c,v retrieving revision 1.131 diff -u -r1.131 tty_cons.c --- kern/tty_cons.c 27 Feb 2005 21:52:41 -0000 1.131 +++ kern/tty_cons.c 19 Oct 2007 13:00:12 -0000 @@ -41,6 +41,8 @@ #include #include +#include +#include #include #include #include @@ -117,6 +119,8 @@ static char *console_pausestr= ""; struct tty *constty; /* pointer to console "window" tty */ +static struct mtx cnputs_mtx; /* Mutex for cnputs(). */ +static int use_cnputs_mtx = 0; /* != 0 if cnputs_mtx locking reqd. */ static void constty_timeout(void *arg); @@ -654,6 +658,24 @@ refcount++; } +void +cnputs(char *p) +{ + int c; + int unlock_reqd = 0; + + if (use_cnputs_mtx) { + mtx_lock_spin(&cnputs_mtx); + unlock_reqd = 1; + } + + while ((c = *p++) != '\0') + cnputc(c); + + if (unlock_reqd) + mtx_unlock_spin(&cnputs_mtx); +} + static int consmsgbuf_size = 8192; SYSCTL_INT(_kern, OID_AUTO, consmsgbuf_size, CTLFLAG_RW, &consmsgbuf_size, 0, ""); @@ -723,6 +745,9 @@ { make_dev(&cn_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "console"); + + mtx_init(&cnputs_mtx, "cnputs_mtx", NULL, MTX_SPIN | MTX_NOWITNESS); + use_cnputs_mtx = 1; } SYSINIT(cndev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, cn_drvinit, NULL) Index: sys/cons.h =================================================================== RCS file: /usr/local/arch/ncvs/src/sys/sys/cons.h,v retrieving revision 1.37 diff -u -r1.37 cons.h --- sys/cons.h 7 Jan 2005 02:29:23 -0000 1.37 +++ sys/cons.h 19 Oct 2007 13:00:15 -0000 @@ -100,6 +100,7 @@ int cngetc(void); void cndbctl(int); void cnputc(int); +void cnputs(char *); int cnunavailable(void); #endif /* _KERNEL */