The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/kernel/printk.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  *  linux/kernel/printk.c
    3  *
    4  *  Copyright (C) 1991, 1992  Linus Torvalds
    5  *
    6  * Modified to make sys_syslog() more flexible: added commands to
    7  * return the last 4k of kernel messages, regardless of whether
    8  * they've been read or not.  Added option to suppress kernel printk's
    9  * to the console.  Added hook for sending the console messages
   10  * elsewhere, in preparation for a serial line console (someday).
   11  * Ted Ts'o, 2/11/93.
   12  * Modified for sysctl support, 1/8/97, Chris Horn.
   13  * Fixed SMP synchronization, 08/08/99, Manfred Spraul 
   14  *     manfreds@colorfullife.com
   15  * Rewrote bits to get rid of console_lock
   16  *      01Mar01 Andrew Morton <andrewm@uow.edu.au>
   17  */
   18 
   19 #include <linux/kernel.h>
   20 #include <linux/mm.h>
   21 #include <linux/tty.h>
   22 #include <linux/tty_driver.h>
   23 #include <linux/smp_lock.h>
   24 #include <linux/console.h>
   25 #include <linux/init.h>
   26 #include <linux/module.h>
   27 #include <linux/interrupt.h>                    /* For in_interrupt() */
   28 #include <linux/config.h>
   29 
   30 #include <asm/uaccess.h>
   31 
   32 #if defined(CONFIG_MULTIQUAD) || defined(CONFIG_IA64)
   33 #define LOG_BUF_LEN     (65536)
   34 #elif defined(CONFIG_ARCH_S390)
   35 #define LOG_BUF_LEN     (131072)
   36 #elif defined(CONFIG_SMP)
   37 #define LOG_BUF_LEN     (32768)
   38 #else   
   39 #define LOG_BUF_LEN     (16384)                 /* This must be a power of two */
   40 #endif
   41 
   42 #define LOG_BUF_MASK    (LOG_BUF_LEN-1)
   43 
   44 #ifndef arch_consoles_callable
   45 #define arch_consoles_callable() (1)
   46 #endif
   47 
   48 /* printk's without a loglevel use this.. */
   49 #define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */
   50 
   51 /* We show everything that is MORE important than this.. */
   52 #define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */
   53 #define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */
   54 
   55 DECLARE_WAIT_QUEUE_HEAD(log_wait);
   56 
   57 int console_printk[4] = {
   58         DEFAULT_CONSOLE_LOGLEVEL,       /* console_loglevel */
   59         DEFAULT_MESSAGE_LOGLEVEL,       /* default_message_loglevel */
   60         MINIMUM_CONSOLE_LOGLEVEL,       /* minimum_console_loglevel */
   61         DEFAULT_CONSOLE_LOGLEVEL,       /* default_console_loglevel */
   62 };
   63 
   64 int oops_in_progress;
   65 
   66 /*
   67  * console_sem protects the console_drivers list, and also
   68  * provides serialisation for access to the entire console
   69  * driver system.
   70  */
   71 static DECLARE_MUTEX(console_sem);
   72 struct console *console_drivers;
   73 
   74 /*
   75  * logbuf_lock protects log_buf, log_start, log_end, con_start and logged_chars
   76  * It is also used in interesting ways to provide interlocking in
   77  * release_console_sem().
   78  */
   79 static spinlock_t logbuf_lock = SPIN_LOCK_UNLOCKED;
   80 
   81 static char log_buf[LOG_BUF_LEN];
   82 #define LOG_BUF(idx) (log_buf[(idx) & LOG_BUF_MASK])
   83 
   84 /*
   85  * The indices into log_buf are not constrained to LOG_BUF_LEN - they
   86  * must be masked before subscripting
   87  */
   88 static unsigned long log_start;                 /* Index into log_buf: next char to be read by syslog() */
   89 static unsigned long con_start;                 /* Index into log_buf: next char to be sent to consoles */
   90 static unsigned long log_end;                   /* Index into log_buf: most-recently-written-char + 1 */
   91 static unsigned long logged_chars;              /* Number of chars produced since last read+clear operation */
   92 
   93 struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];
   94 static int preferred_console = -1;
   95 
   96 /* Flag: console code may call schedule() */
   97 static int console_may_schedule;
   98 
   99 /*
  100  *      Setup a list of consoles. Called from init/main.c
  101  */
  102 static int __init console_setup(char *str)
  103 {
  104         struct console_cmdline *c;
  105         char name[sizeof(c->name)];
  106         char *s, *options;
  107         int i, idx;
  108 
  109         /*
  110          *      Decode str into name, index, options.
  111          */
  112         if (str[0] >= '' && str[0] <= '9') {
  113                 strcpy(name, "ttyS");
  114                 strncpy(name + 4, str, sizeof(name) - 5);
  115         } else
  116                 strncpy(name, str, sizeof(name) - 1);
  117         name[sizeof(name) - 1] = 0;
  118         if ((options = strchr(str, ',')) != NULL)
  119                 *(options++) = 0;
  120 #ifdef __sparc__
  121         if (!strcmp(str, "ttya"))
  122                 strcpy(name, "ttyS0");
  123         if (!strcmp(str, "ttyb"))
  124                 strcpy(name, "ttyS1");
  125 #endif
  126         for(s = name; *s; s++)
  127                 if (*s >= '' && *s <= '9')
  128                         break;
  129         idx = simple_strtoul(s, NULL, 10);
  130         *s = 0;
  131 
  132         /*
  133          *      See if this tty is not yet registered, and
  134          *      if we have a slot free.
  135          */
  136         for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
  137                 if (strcmp(console_cmdline[i].name, name) == 0 &&
  138                           console_cmdline[i].index == idx) {
  139                                 preferred_console = i;
  140                                 return 1;
  141                 }
  142         if (i == MAX_CMDLINECONSOLES)
  143                 return 1;
  144         preferred_console = i;
  145         c = &console_cmdline[i];
  146         memcpy(c->name, name, sizeof(c->name));
  147         c->options = options;
  148         c->index = idx;
  149         return 1;
  150 }
  151 
  152 __setup("console=", console_setup);
  153 
  154 /*
  155  * Commands to do_syslog:
  156  *
  157  *      0 -- Close the log.  Currently a NOP.
  158  *      1 -- Open the log. Currently a NOP.
  159  *      2 -- Read from the log.
  160  *      3 -- Read all messages remaining in the ring buffer.
  161  *      4 -- Read and clear all messages remaining in the ring buffer
  162  *      5 -- Clear ring buffer.
  163  *      6 -- Disable printk's to console
  164  *      7 -- Enable printk's to console
  165  *      8 -- Set level of messages printed to console
  166  *      9 -- Return number of unread characters in the log buffer
  167  */
  168 int do_syslog(int type, char * buf, int len)
  169 {
  170         unsigned long i, j, limit, count;
  171         int do_clear = 0;
  172         char c;
  173         int error = 0;
  174 
  175         switch (type) {
  176         case 0:         /* Close log */
  177                 break;
  178         case 1:         /* Open log */
  179                 break;
  180         case 2:         /* Read from log */
  181                 error = -EINVAL;
  182                 if (!buf || len < 0)
  183                         goto out;
  184                 error = 0;
  185                 if (!len)
  186                         goto out;
  187                 error = verify_area(VERIFY_WRITE,buf,len);
  188                 if (error)
  189                         goto out;
  190                 error = wait_event_interruptible(log_wait, (log_start - log_end));
  191                 if (error)
  192                         goto out;
  193                 i = 0;
  194                 spin_lock_irq(&logbuf_lock);
  195                 while ((log_start != log_end) && i < len) {
  196                         c = LOG_BUF(log_start);
  197                         log_start++;
  198                         spin_unlock_irq(&logbuf_lock);
  199                         __put_user(c,buf);
  200                         buf++;
  201                         i++;
  202                         spin_lock_irq(&logbuf_lock);
  203                 }
  204                 spin_unlock_irq(&logbuf_lock);
  205                 error = i;
  206                 break;
  207         case 4:         /* Read/clear last kernel messages */
  208                 do_clear = 1; 
  209                 /* FALL THRU */
  210         case 3:         /* Read last kernel messages */
  211                 error = -EINVAL;
  212                 if (!buf || len < 0)
  213                         goto out;
  214                 error = 0;
  215                 if (!len)
  216                         goto out;
  217                 error = verify_area(VERIFY_WRITE,buf,len);
  218                 if (error)
  219                         goto out;
  220                 count = len;
  221                 if (count > LOG_BUF_LEN)
  222                         count = LOG_BUF_LEN;
  223                 spin_lock_irq(&logbuf_lock);
  224                 if (count > logged_chars)
  225                         count = logged_chars;
  226                 if (do_clear)
  227                         logged_chars = 0;
  228                 limit = log_end;
  229                 /*
  230                  * __put_user() could sleep, and while we sleep
  231                  * printk() could overwrite the messages 
  232                  * we try to copy to user space. Therefore
  233                  * the messages are copied in reverse. <manfreds>
  234                  */
  235                 for(i=0;i < count;i++) {
  236                         j = limit-1-i;
  237                         if (j+LOG_BUF_LEN < log_end)
  238                                 break;
  239                         c = LOG_BUF(j);
  240                         spin_unlock_irq(&logbuf_lock);
  241                         __put_user(c,&buf[count-1-i]);
  242                         spin_lock_irq(&logbuf_lock);
  243                 }
  244                 spin_unlock_irq(&logbuf_lock);
  245                 error = i;
  246                 if(i != count) {
  247                         int offset = count-error;
  248                         /* buffer overflow during copy, correct user buffer. */
  249                         for(i=0;i<error;i++) {
  250                                 __get_user(c,&buf[i+offset]);
  251                                 __put_user(c,&buf[i]);
  252                         }
  253                 }
  254 
  255                 break;
  256         case 5:         /* Clear ring buffer */
  257                 spin_lock_irq(&logbuf_lock);
  258                 logged_chars = 0;
  259                 spin_unlock_irq(&logbuf_lock);
  260                 break;
  261         case 6:         /* Disable logging to console */
  262                 spin_lock_irq(&logbuf_lock);
  263                 console_loglevel = minimum_console_loglevel;
  264                 spin_unlock_irq(&logbuf_lock);
  265                 break;
  266         case 7:         /* Enable logging to console */
  267                 spin_lock_irq(&logbuf_lock);
  268                 console_loglevel = default_console_loglevel;
  269                 spin_unlock_irq(&logbuf_lock);
  270                 break;
  271         case 8:         /* Set level of messages printed to console */
  272                 error = -EINVAL;
  273                 if (len < 1 || len > 8)
  274                         goto out;
  275                 if (len < minimum_console_loglevel)
  276                         len = minimum_console_loglevel;
  277                 spin_lock_irq(&logbuf_lock);
  278                 console_loglevel = len;
  279                 spin_unlock_irq(&logbuf_lock);
  280                 error = 0;
  281                 break;
  282         case 9:         /* Number of chars in the log buffer */
  283                 spin_lock_irq(&logbuf_lock);
  284                 error = log_end - log_start;
  285                 spin_unlock_irq(&logbuf_lock);
  286                 break;
  287         default:
  288                 error = -EINVAL;
  289                 break;
  290         }
  291 out:
  292         return error;
  293 }
  294 
  295 asmlinkage long sys_syslog(int type, char * buf, int len)
  296 {
  297         if ((type != 3) && !capable(CAP_SYS_ADMIN))
  298                 return -EPERM;
  299         return do_syslog(type, buf, len);
  300 }
  301 
  302 /*
  303  * Call the console drivers on a range of log_buf
  304  */
  305 static void __call_console_drivers(unsigned long start, unsigned long end)
  306 {
  307         struct console *con;
  308 
  309         for (con = console_drivers; con; con = con->next) {
  310                 if ((con->flags & CON_ENABLED) && con->write)
  311                         con->write(con, &LOG_BUF(start), end - start);
  312         }
  313 }
  314 
  315 /*
  316  * Write out chars from start to end - 1 inclusive
  317  */
  318 static void _call_console_drivers(unsigned long start, unsigned long end, int msg_log_level)
  319 {
  320         if (msg_log_level < console_loglevel && console_drivers && start != end) {
  321                 if ((start & LOG_BUF_MASK) > (end & LOG_BUF_MASK)) {
  322                         /* wrapped write */
  323                         __call_console_drivers(start & LOG_BUF_MASK, LOG_BUF_LEN);
  324                         __call_console_drivers(0, end & LOG_BUF_MASK);
  325                 } else {
  326                         __call_console_drivers(start, end);
  327                 }
  328         }
  329 }
  330 
  331 /*
  332  * Call the console drivers, asking them to write out
  333  * log_buf[start] to log_buf[end - 1].
  334  * The console_sem must be held.
  335  */
  336 static void call_console_drivers(unsigned long start, unsigned long end)
  337 {
  338         unsigned long cur_index, start_print;
  339         static int msg_level = -1;
  340 
  341         if (((long)(start - end)) > 0)
  342                 BUG();
  343 
  344         cur_index = start;
  345         start_print = start;
  346         while (cur_index != end) {
  347                 if (    msg_level < 0 &&
  348                         ((end - cur_index) > 2) &&
  349                         LOG_BUF(cur_index + 0) == '<' &&
  350                         LOG_BUF(cur_index + 1) >= '' &&
  351                         LOG_BUF(cur_index + 1) <= '7' &&
  352                         LOG_BUF(cur_index + 2) == '>')
  353                 {
  354                         msg_level = LOG_BUF(cur_index + 1) - '';
  355                         cur_index += 3;
  356                         start_print = cur_index;
  357                 }
  358                 while (cur_index != end) {
  359                         char c = LOG_BUF(cur_index);
  360                         cur_index++;
  361 
  362                         if (c == '\n') {
  363                                 if (msg_level < 0) {
  364                                         /*
  365                                          * printk() has already given us loglevel tags in
  366                                          * the buffer.  This code is here in case the
  367                                          * log buffer has wrapped right round and scribbled
  368                                          * on those tags
  369                                          */
  370                                         msg_level = default_message_loglevel;
  371                                 }
  372                                 _call_console_drivers(start_print, cur_index, msg_level);
  373                                 msg_level = -1;
  374                                 start_print = cur_index;
  375                                 break;
  376                         }
  377                 }
  378         }
  379         _call_console_drivers(start_print, end, msg_level);
  380 }
  381 
  382 static void emit_log_char(char c)
  383 {
  384         LOG_BUF(log_end) = c;
  385         log_end++;
  386         if (log_end - log_start > LOG_BUF_LEN)
  387                 log_start = log_end - LOG_BUF_LEN;
  388         if (log_end - con_start > LOG_BUF_LEN)
  389                 con_start = log_end - LOG_BUF_LEN;
  390         if (logged_chars < LOG_BUF_LEN)
  391                 logged_chars++;
  392 }
  393 
  394 /*
  395  * This is printk.  It can be called from any context.  We want it to work.
  396  * 
  397  * We try to grab the console_sem.  If we succeed, it's easy - we log the output and
  398  * call the console drivers.  If we fail to get the semaphore we place the output
  399  * into the log buffer and return.  The current holder of the console_sem will
  400  * notice the new output in release_console_sem() and will send it to the
  401  * consoles before releasing the semaphore.
  402  *
  403  * One effect of this deferred printing is that code which calls printk() and
  404  * then changes console_loglevel may break. This is because console_loglevel
  405  * is inspected when the actual printing occurs.
  406  */
  407 asmlinkage int printk(const char *fmt, ...)
  408 {
  409         va_list args;
  410         unsigned long flags;
  411         int printed_len;
  412         char *p;
  413         static char printk_buf[1024];
  414         static int log_level_unknown = 1;
  415 
  416         if (oops_in_progress) {
  417                 /* If a crash is occurring, make sure we can't deadlock */
  418                 spin_lock_init(&logbuf_lock);
  419                 /* And make sure that we print immediately */
  420                 init_MUTEX(&console_sem);
  421         }
  422 
  423         /* This stops the holder of console_sem just where we want him */
  424         spin_lock_irqsave(&logbuf_lock, flags);
  425 
  426         /* Emit the output into the temporary buffer */
  427         va_start(args, fmt);
  428         printed_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);
  429         va_end(args);
  430 
  431         /*
  432          * Copy the output into log_buf.  If the caller didn't provide
  433          * appropriate log level tags, we insert them here
  434          */
  435         for (p = printk_buf; *p; p++) {
  436                 if (log_level_unknown) {
  437                         if (p[0] != '<' || p[1] < '' || p[1] > '7' || p[2] != '>') {
  438                                 emit_log_char('<');
  439                                 emit_log_char(default_message_loglevel + '');
  440                                 emit_log_char('>');
  441                         }
  442                         log_level_unknown = 0;
  443                 }
  444                 emit_log_char(*p);
  445                 if (*p == '\n')
  446                         log_level_unknown = 1;
  447         }
  448 
  449         if (!arch_consoles_callable()) {
  450                 /*
  451                  * On some architectures, the consoles are not usable
  452                  * on secondary CPUs early in the boot process.
  453                  */
  454                 spin_unlock_irqrestore(&logbuf_lock, flags);
  455                 goto out;
  456         }
  457         if (!down_trylock(&console_sem)) {
  458                 /*
  459                  * We own the drivers.  We can drop the spinlock and let
  460                  * release_console_sem() print the text
  461                  */
  462                 spin_unlock_irqrestore(&logbuf_lock, flags);
  463                 console_may_schedule = 0;
  464                 release_console_sem();
  465         } else {
  466                 /*
  467                  * Someone else owns the drivers.  We drop the spinlock, which
  468                  * allows the semaphore holder to proceed and to call the
  469                  * console drivers with the output which we just produced.
  470                  */
  471                 spin_unlock_irqrestore(&logbuf_lock, flags);
  472         }
  473 out:
  474         return printed_len;
  475 }
  476 EXPORT_SYMBOL(printk);
  477 
  478 /**
  479  * acquire_console_sem - lock the console system for exclusive use.
  480  *
  481  * Acquires a semaphore which guarantees that the caller has
  482  * exclusive access to the console system and the console_drivers list.
  483  *
  484  * Can sleep, returns nothing.
  485  */
  486 void acquire_console_sem(void)
  487 {
  488         if (in_interrupt())
  489                 BUG();
  490         down(&console_sem);
  491         console_may_schedule = 1;
  492 }
  493 EXPORT_SYMBOL(acquire_console_sem);
  494 
  495 /**
  496  * release_console_sem - unlock the console system
  497  *
  498  * Releases the semaphore which the caller holds on the console system
  499  * and the console driver list.
  500  *
  501  * While the semaphore was held, console output may have been buffered
  502  * by printk().  If this is the case, release_console_sem() emits
  503  * the output prior to releasing the semaphore.
  504  *
  505  * If there is output waiting for klogd, we wake it up.
  506  *
  507  * release_console_sem() may be called from any context.
  508  */
  509 void release_console_sem(void)
  510 {
  511         unsigned long flags;
  512         unsigned long _con_start, _log_end;
  513         unsigned long must_wake_klogd = 0;
  514 
  515         for ( ; ; ) {
  516                 spin_lock_irqsave(&logbuf_lock, flags);
  517                 must_wake_klogd |= log_start - log_end;
  518                 if (con_start == log_end)
  519                         break;                  /* Nothing to print */
  520                 _con_start = con_start;
  521                 _log_end = log_end;
  522                 con_start = log_end;            /* Flush */
  523                 spin_unlock_irqrestore(&logbuf_lock, flags);
  524                 call_console_drivers(_con_start, _log_end);
  525         }
  526         console_may_schedule = 0;
  527         up(&console_sem);
  528         spin_unlock_irqrestore(&logbuf_lock, flags);
  529         if (must_wake_klogd && !oops_in_progress)
  530                 wake_up_interruptible(&log_wait);
  531 }
  532 
  533 /** console_conditional_schedule - yield the CPU if required
  534  *
  535  * If the console code is currently allowed to sleep, and
  536  * if this CPU should yield the CPU to another task, do
  537  * so here.
  538  *
  539  * Must be called within acquire_console_sem().
  540  */
  541 void console_conditional_schedule(void)
  542 {
  543         if (console_may_schedule && current->need_resched) {
  544                 set_current_state(TASK_RUNNING);
  545                 schedule();
  546         }
  547 }
  548 
  549 void console_print(const char *s)
  550 {
  551         printk(KERN_EMERG "%s", s);
  552 }
  553 EXPORT_SYMBOL(console_print);
  554 
  555 void console_unblank(void)
  556 {
  557         struct console *c;
  558 
  559         /*
  560          * Try to get the console semaphore. If someone else owns it
  561          * we have to return without unblanking because console_unblank
  562          * may be called in interrupt context.
  563          */
  564         if (down_trylock(&console_sem) != 0)
  565                 return;
  566         console_may_schedule = 0;
  567         for (c = console_drivers; c != NULL; c = c->next)
  568                 if ((c->flags & CON_ENABLED) && c->unblank)
  569                         c->unblank();
  570         release_console_sem();
  571 }
  572 EXPORT_SYMBOL(console_unblank);
  573 
  574 /*
  575  * The console driver calls this routine during kernel initialization
  576  * to register the console printing procedure with printk() and to
  577  * print any messages that were printed by the kernel before the
  578  * console driver was initialized.
  579  */
  580 void register_console(struct console * console)
  581 {
  582         int     i;
  583         unsigned long flags;
  584 
  585         /*
  586          *      See if we want to use this console driver. If we
  587          *      didn't select a console we take the first one
  588          *      that registers here.
  589          */
  590         if (preferred_console < 0) {
  591                 if (console->index < 0)
  592                         console->index = 0;
  593                 if (console->setup == NULL ||
  594                     console->setup(console, NULL) == 0) {
  595                         console->flags |= CON_ENABLED | CON_CONSDEV;
  596                         preferred_console = 0;
  597                 }
  598         }
  599 
  600         /*
  601          *      See if this console matches one we selected on
  602          *      the command line.
  603          */
  604         for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++) {
  605                 if (strcmp(console_cmdline[i].name, console->name) != 0)
  606                         continue;
  607                 if (console->index >= 0 &&
  608                     console->index != console_cmdline[i].index)
  609                         continue;
  610                 if (console->index < 0)
  611                         console->index = console_cmdline[i].index;
  612                 if (console->setup &&
  613                     console->setup(console, console_cmdline[i].options) != 0)
  614                         break;
  615                 console->flags |= CON_ENABLED;
  616                 console->index = console_cmdline[i].index;
  617                 if (i == preferred_console)
  618                         console->flags |= CON_CONSDEV;
  619                 break;
  620         }
  621 
  622         if (!(console->flags & CON_ENABLED))
  623                 return;
  624 
  625         /*
  626          *      Put this console in the list - keep the
  627          *      preferred driver at the head of the list.
  628          */
  629         acquire_console_sem();
  630         if ((console->flags & CON_CONSDEV) || console_drivers == NULL) {
  631                 console->next = console_drivers;
  632                 console_drivers = console;
  633         } else {
  634                 console->next = console_drivers->next;
  635                 console_drivers->next = console;
  636         }
  637         if (console->flags & CON_PRINTBUFFER) {
  638                 /*
  639                  * release_console_sem() will print out the buffered messages for us.
  640                  */
  641                 spin_lock_irqsave(&logbuf_lock, flags);
  642                 con_start = log_start;
  643                 spin_unlock_irqrestore(&logbuf_lock, flags);
  644         }
  645         release_console_sem();
  646 }
  647 EXPORT_SYMBOL(register_console);
  648 
  649 int unregister_console(struct console * console)
  650 {
  651         struct console *a,*b;
  652         int res = 1;
  653 
  654         acquire_console_sem();
  655         if (console_drivers == console) {
  656                 console_drivers=console->next;
  657                 res = 0;
  658         } else {
  659                 for (a=console_drivers->next, b=console_drivers ;
  660                      a; b=a, a=b->next) {
  661                         if (a == console) {
  662                                 b->next = a->next;
  663                                 res = 0;
  664                                 break;
  665                         }  
  666                 }
  667         }
  668         
  669         /* If last console is removed, we re-enable picking the first
  670          * one that gets registered. Without that, pmac early boot console
  671          * would prevent fbcon from taking over.
  672          */
  673         if (console_drivers == NULL)
  674                 preferred_console = -1;
  675                 
  676 
  677         release_console_sem();
  678         return res;
  679 }
  680 EXPORT_SYMBOL(unregister_console);
  681         
  682 /**
  683  * tty_write_message - write a message to a certain tty, not just the console.
  684  *
  685  * This is used for messages that need to be redirected to a specific tty.
  686  * We don't put it into the syslog queue right now maybe in the future if
  687  * really needed.
  688  */
  689 void tty_write_message(struct tty_struct *tty, char *msg)
  690 {
  691         if (tty && tty->driver.write)
  692                 tty->driver.write(tty, 0, msg, strlen(msg));
  693         return;
  694 }

Cache object: 0333da38f6121c8ae89c8b8a3f1ebaa4


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.