Commit ebe6a33a authored by Léo Grange's avatar Léo Grange

printk use TTY instead of VFS files, and is able to force flushing

parent b42d2a68
......@@ -98,6 +98,8 @@ void kdebug_oops(const char *errstr) {
kdebug_print_vmspace(proc);
printk_force_flush();
// print each kernel context information
kdebug_print_trace();
......@@ -113,5 +115,7 @@ void kdebug_oops(const char *errstr) {
cont = cont->previous;
}
printk_force_flush();
while(1);
}
......@@ -96,12 +96,15 @@ static int vt_tty_putchar(struct tty *tty, char c);
static int vt_tty_write(struct tty *tty, const char *data, size_t len);
static int vt_tty_force_flush(struct tty *tty);
static const struct tty_ops _vt_tty_ops = {
.ioctl_setwinsize = &vt_ioctl_setwinsize,
.ioctl_getwinsize = &vt_ioctl_getwinsize,
.is_ready = &vt_tty_is_ready,
.tty_write = &vt_tty_write,
.putchar = &vt_tty_putchar
.putchar = &vt_tty_putchar,
.force_flush = &vt_tty_force_flush
};
......@@ -172,6 +175,13 @@ static void vt_delay_flush() {
}
// direct flush without waiting delayed flushing
static int vt_tty_force_flush(struct tty *tty) {
_tdisp->flush(& ((struct vt_instance*)tty->private)->disp);
return 0;
}
/**
* Move the cursor from its current position to (newx, newy), after checking
* screen boundaries.
......
......@@ -18,9 +18,6 @@
static uint32 _console_node = (CONSOLE_TTY_MAJOR << 16) | CONSOLE_TTY_MINOR_BASE;
// static file used for the console
static struct file _console_file;
int parse_console(const char *val) {
//printk(LOG_DEBUG, "ARG: console='%s'\n", val);
if(val != NULL) {
......@@ -58,19 +55,16 @@ void console_make_active() {
if(console_dev != NULL) {
struct tty *tty;
_console_file.flags = 0;
_console_file.inode = NULL;
// FIXME use only the tty interface, not the file one!
tty = console_dev->get_tty(minor(_console_node));
if(console_dev->open(minor(_console_node), &_console_file) == 0) {
if(tty != NULL && !tty_is_ready(tty)) {
if(tty != NULL) {
if(!tty_is_ready(tty)) {
// wait until the TTY is ready
printk(LOG_INFO, "[console tty not ready...]\n");
while(!tty_is_ready(tty));
printk(LOG_INFO, "[ready!]\n");
}
// set printk(LOG_DEBUG, ) callback func
set_kernel_print_file(&_console_file);
// set printk() TTY
printk_set_console_tty(tty);
printk(LOG_INFO, "Now using console device for printk()!\n");
}
else {
......
......@@ -61,6 +61,9 @@ struct tty_ops {
// ioctl support
int (*ioctl_setwinsize)(struct tty *tty, const struct winsize *size);
int (*ioctl_getwinsize)(struct tty *tty, struct winsize *size);
// last chance to flush output from a TTY (e.g. after a oops)
int (*force_flush)(struct tty *tty);
};
......@@ -164,4 +167,16 @@ int tty_ioctl(struct tty *tty, int cmd, void *data);
*/
int tty_input_char(struct tty *tty, char c);
/**
* Try to flush the output buffer of the given TTY (to be visible from user).
* Should be as simple as possible, because it may be called from unstable
* states, as a last chance to show something to the user.
*/
extern inline int tty_force_flush(struct tty *tty) {
if(tty->ops->force_flush != NULL)
return tty->ops->force_flush(tty);
return -EIO;
}
#endif //_SYS_TTY_H
#include "log.h"
#include "types.h"
#include "strconv.h"
#include <fs/vfs_file.h>
#include <sys/cmdline.h>
#include <sys/tty.h>
// normally provide by GCC, with only builtins calls...
// FIXME replace by in-kernel definition with __builtin_va_*
......@@ -12,14 +12,12 @@
static print_callback_t current_kernel_print = NULL;
// used by print_to_file()
static struct file *current_log_file = NULL;
// console TTY used (NULL if using early printk)
static struct tty *_current_console_tty = NULL;
// dynamic level, default is to display every non debug message
static int printk_dynamic_level = LOG_INFO;
static void print_to_file(const char *str);
void printk_internal(int level, const char *str, ...)
{
if(level >= printk_dynamic_level && current_kernel_print != NULL) {
......@@ -107,24 +105,30 @@ void set_kernel_print(print_callback_t func)
}
void set_kernel_print_file(struct file *logfile) {
current_log_file = logfile;
if(current_log_file != NULL) {
current_kernel_print = &print_to_file;
static void printk_write_tty(const char *str) {
size_t len = 0;
// no strlen() for now, basic implementation
while(str[len]!='\0')
len++;
tty_write(_current_console_tty, str, len);
}
void printk_set_console_tty(struct tty *tty) {
_current_console_tty = tty;
if(_current_console_tty != NULL) {
current_kernel_print = &printk_write_tty;
}
else {
current_kernel_print = NULL;
}
}
void print_to_file(const char *str) {
size_t len = 0;
// no strlen() for now, basic implementation
while(str[len]!='\0')
len++;
vfs_write(current_log_file, str, len);
void printk_force_flush() {
if(_current_console_tty != NULL)
tty_force_flush(_current_console_tty);
}
......
......@@ -6,7 +6,7 @@
// callack used to print a part of a printk() message
typedef void(*print_callback_t)(const char*);
struct file;
struct tty;
/**
* Message level are using the same names than the POSIX syslog() priorities.
......@@ -67,9 +67,16 @@ void set_kernel_print(print_callback_t func);
/**
* Set printk callback function to vfs_write(logfile, msg, strlen(msg)).
* Set printk callback function to tty_write(logfile, msg, strlen(msg)).
* This function override the callback defined by set_kernel_print().
*/
void set_kernel_print_file(struct file *logfile);
void printk_set_console_tty(struct tty *tty);
/**
* Should force the previous printk() content to be displayed to the
* underlying console if possible.
*/
void printk_force_flush();
#endif //_UTILS_LOG_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment