diff options
author | Ian Dowse <iedowse@FreeBSD.org> | 2003-06-22 02:54:33 +0000 |
---|---|---|
committer | Ian Dowse <iedowse@FreeBSD.org> | 2003-06-22 02:54:33 +0000 |
commit | d29bf12ff8af22103581957d676732a09eec7e19 (patch) | |
tree | 68d45a057c7fb88626bb480c259807ef2a5bf778 /sys/kern/tty_cons.c | |
parent | 7ca33ad1e88de79ac6dcbb6a30b8f199e72cf964 (diff) | |
download | src-d29bf12ff8af22103581957d676732a09eec7e19.tar.gz src-d29bf12ff8af22103581957d676732a09eec7e19.zip |
Use a new message buffer `consmsgbuf' to forward messages to a
TIOCCONS console (e.g. xconsole) via a timeout routine instead of
calling into the tty code directly from printf(). This fixes a
number of cases where calling printf() at the wrong time (such as
with locks held) would cause a panic if xconsole is running.
The TIOCCONS message buffer is 8k in size by default, but this can
be changed with the kern.consmsgbuf_size sysctl. By default, messages
are checked for 5 times per second. The timer runs and the buffer
memory remains allocated only at times when a TIOCCONS console is
active.
Discussed on: freebsd-arch
Notes
Notes:
svn path=/head/; revision=116663
Diffstat (limited to 'sys/kern/tty_cons.c')
-rw-r--r-- | sys/kern/tty_cons.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/sys/kern/tty_cons.c b/sys/kern/tty_cons.c index fe723e691bf9..53a5d3d32481 100644 --- a/sys/kern/tty_cons.c +++ b/sys/kern/tty_cons.c @@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$"); #include <sys/fcntl.h> #include <sys/kernel.h> #include <sys/malloc.h> +#include <sys/msgbuf.h> #include <sys/namei.h> #include <sys/proc.h> #include <sys/queue.h> @@ -117,11 +118,16 @@ int cons_unavail = 0; /* XXX: static int cn_mute; static int openflag; /* how /dev/console was opened */ static int cn_is_open; +static char *consbuf; /* buffer used by `consmsgbuf' */ +static struct callout conscallout; /* callout for outputting to constty */ +struct msgbuf consmsgbuf; /* message buffer for console tty */ static u_char console_pausing; /* pause after each line during probe */ static char *console_pausestr= "<pause; press any key to proceed to next line or '.' to end pause mode>"; +struct tty *constty; /* pointer to console "window" tty */ void cndebug(char *); +static void constty_timeout(void *arg); CONS_DRIVER(cons, NULL, NULL, NULL, NULL, NULL, NULL, NULL); SET_DECLARE(cons_set, struct consdev); @@ -589,6 +595,70 @@ cndbctl(int on) refcount++; } +static int consmsgbuf_size = 8192; +SYSCTL_INT(_kern, OID_AUTO, consmsgbuf_size, CTLFLAG_RW, &consmsgbuf_size, 0, + ""); + +/* + * Redirect console output to a tty. + */ +void +constty_set(struct tty *tp) +{ + int size; + + KASSERT(tp != NULL, ("constty_set: NULL tp")); + if (consbuf == NULL) { + size = consmsgbuf_size; + consbuf = malloc(size, M_TTYS, M_WAITOK); + msgbuf_init(&consmsgbuf, consbuf, size); + callout_init(&conscallout, 0); + } + constty = tp; + constty_timeout(NULL); +} + +/* + * Disable console redirection to a tty. + */ +void +constty_clear(void) +{ + int c; + + constty = NULL; + if (consbuf == NULL) + return; + callout_stop(&conscallout); + while ((c = msgbuf_getchar(&consmsgbuf)) != -1) + cnputc(c); + free(consbuf, M_TTYS); + consbuf = NULL; +} + +/* Times per second to check for pending console tty messages. */ +static int constty_wakeups_per_second = 5; +SYSCTL_INT(_kern, OID_AUTO, constty_wakeups_per_second, CTLFLAG_RW, + &constty_wakeups_per_second, 0, ""); + +static void +constty_timeout(void *arg) +{ + int c; + + while (constty != NULL && (c = msgbuf_getchar(&consmsgbuf)) != -1) { + if (tputchar(c, constty) < 0) + constty = NULL; + } + if (constty != NULL) { + callout_reset(&conscallout, hz / constty_wakeups_per_second, + constty_timeout, NULL); + } else { + /* Deallocate the constty buffer memory. */ + constty_clear(); + } +} + static void cn_drvinit(void *unused) { |