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/kern/subr_log.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  * Copyright (c) 1982, 1986, 1993
    3  *      The Regents of the University of California.  All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. Neither the name of the University nor the names of its contributors
   14  *    may be used to endorse or promote products derived from this software
   15  *    without specific prior written permission.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  *
   29  *      @(#)subr_log.c  8.1 (Berkeley) 6/10/93
   30  * $FreeBSD: src/sys/kern/subr_log.c,v 1.39.2.2 2001/06/02 08:11:25 phk Exp $
   31  */
   32 
   33 /*
   34  * Error log buffer for kernel printf's.
   35  */
   36 
   37 #include <sys/param.h>
   38 #include <sys/systm.h>
   39 #include <sys/conf.h>
   40 #include <sys/device.h>
   41 #include <sys/proc.h>
   42 #include <sys/vnode.h>
   43 #include <sys/filio.h>
   44 #include <sys/ttycom.h>
   45 #include <sys/msgbuf.h>
   46 #include <sys/signalvar.h>
   47 #include <sys/kernel.h>
   48 #include <sys/event.h>
   49 #include <sys/filedesc.h>
   50 #include <sys/sysctl.h>
   51 #include <sys/thread2.h>
   52 
   53 #define LOG_ASYNC       0x04
   54 #define LOG_RDWAIT      0x08
   55 
   56 static  d_open_t        logopen;
   57 static  d_close_t       logclose;
   58 static  d_read_t        logread;
   59 static  d_ioctl_t       logioctl;
   60 static  d_kqfilter_t    logkqfilter;
   61 
   62 static  void logtimeout(void *arg);
   63 static  void logfiltdetach(struct knote *kn);
   64 static  int  logfiltread(struct knote *kn, long hint);
   65 
   66 #define CDEV_MAJOR 7
   67 static struct dev_ops log_ops = {
   68         { "log", 0, 0 },
   69         .d_open =       logopen,
   70         .d_close =      logclose,
   71         .d_read =       logread,
   72         .d_ioctl =      logioctl,
   73         .d_kqfilter =   logkqfilter
   74 };
   75 
   76 static struct logsoftc {
   77         int     sc_state;               /* see above for possibilities */
   78         struct  kqinfo  sc_kqp;         /* processes waiting on I/O */
   79         struct  sigio *sc_sigio;        /* information for async I/O */
   80         struct  callout sc_callout;     /* callout to wakeup syslog  */
   81 } logsoftc;
   82 
   83 int     log_open;                       /* also used in log() */
   84 
   85 /* Times per second to check for a pending syslog wakeup. */
   86 static int      log_wakeups_per_second = 5;
   87 SYSCTL_INT(_kern, OID_AUTO, log_wakeups_per_second, CTLFLAG_RW,
   88     &log_wakeups_per_second, 0, "");
   89 
   90 /*ARGSUSED*/
   91 static  int
   92 logopen(struct dev_open_args *ap)
   93 {
   94         struct proc *p = curproc;
   95 
   96         KKASSERT(p != NULL);
   97         if (log_open)
   98                 return (EBUSY);
   99         log_open = 1;
  100         callout_init_mp(&logsoftc.sc_callout);
  101         fsetown(p->p_pid, &logsoftc.sc_sigio);  /* signal process only */
  102         callout_reset(&logsoftc.sc_callout, hz / log_wakeups_per_second,
  103                       logtimeout, NULL);
  104         return (0);
  105 }
  106 
  107 /*ARGSUSED*/
  108 static  int
  109 logclose(struct dev_close_args *ap)
  110 {
  111         log_open = 0;
  112         callout_stop(&logsoftc.sc_callout);
  113         logsoftc.sc_state = 0;
  114         funsetown(&logsoftc.sc_sigio);
  115         return (0);
  116 }
  117 
  118 /*ARGSUSED*/
  119 static  int
  120 logread(struct dev_read_args *ap)
  121 {
  122         struct uio *uio = ap->a_uio;
  123         struct msgbuf *mbp = msgbufp;
  124         long l;
  125         int error = 0;
  126 
  127         crit_enter();
  128         while (mbp->msg_bufr == mbp->msg_bufx) {
  129                 if (ap->a_ioflag & IO_NDELAY) {
  130                         crit_exit();
  131                         return (EWOULDBLOCK);
  132                 }
  133                 logsoftc.sc_state |= LOG_RDWAIT;
  134                 if ((error = tsleep((caddr_t)mbp, PCATCH, "klog", 0))) {
  135                         crit_exit();
  136                         return (error);
  137                 }
  138         }
  139         crit_exit();
  140         logsoftc.sc_state &= ~LOG_RDWAIT;
  141 
  142         while (uio->uio_resid > 0) {
  143                 l = (long)mbp->msg_bufx - (long)mbp->msg_bufr;
  144                 if (l < 0)
  145                         l = mbp->msg_size - mbp->msg_bufr;
  146                 l = (long)szmin(l, uio->uio_resid);
  147                 if (l == 0)
  148                         break;
  149                 error = uiomove((caddr_t)msgbufp->msg_ptr + mbp->msg_bufr,
  150                                 (size_t)l, uio);
  151                 if (error)
  152                         break;
  153                 mbp->msg_bufr += l;
  154                 if (mbp->msg_bufr >= mbp->msg_size)
  155                         mbp->msg_bufr = 0;
  156         }
  157         return (error);
  158 }
  159 
  160 static struct filterops logread_filtops =
  161         { FILTEROP_ISFD, NULL, logfiltdetach, logfiltread };
  162 
  163 static int
  164 logkqfilter(struct dev_kqfilter_args *ap)
  165 {
  166         struct knote *kn = ap->a_kn;
  167         struct klist *klist = &logsoftc.sc_kqp.ki_note;
  168 
  169         ap->a_result = 0;
  170         switch (kn->kn_filter) {
  171         case EVFILT_READ:
  172                 kn->kn_fop = &logread_filtops;
  173                 break;
  174         default:
  175                 ap->a_result = EOPNOTSUPP;
  176                 return (0);
  177         }
  178 
  179         knote_insert(klist, kn);
  180 
  181         return (0);
  182 }
  183 
  184 static void
  185 logfiltdetach(struct knote *kn)
  186 {
  187         struct klist *klist = &logsoftc.sc_kqp.ki_note;
  188 
  189         knote_remove(klist, kn);
  190 }
  191 
  192 static int
  193 logfiltread(struct knote *kn, long hint)
  194 {
  195         int ret = 0;
  196 
  197         crit_enter();
  198         if (msgbufp->msg_bufr != msgbufp->msg_bufx)
  199                 ret = 1;
  200         crit_exit();
  201 
  202         return (ret);
  203 }
  204 
  205 static void
  206 logtimeout(void *arg)
  207 {
  208         if (!log_open)
  209                 return;
  210         if (msgbuftrigger == 0) {
  211                 callout_reset(&logsoftc.sc_callout,
  212                               hz / log_wakeups_per_second, logtimeout, NULL);
  213                 return;
  214         }
  215         msgbuftrigger = 0;
  216         KNOTE(&logsoftc.sc_kqp.ki_note, 0);
  217         if ((logsoftc.sc_state & LOG_ASYNC) && logsoftc.sc_sigio != NULL)
  218                 pgsigio(logsoftc.sc_sigio, SIGIO, 0);
  219         if (logsoftc.sc_state & LOG_RDWAIT) {
  220                 wakeup((caddr_t)msgbufp);
  221                 logsoftc.sc_state &= ~LOG_RDWAIT;
  222         }
  223         callout_reset(&logsoftc.sc_callout, hz / log_wakeups_per_second,
  224                       logtimeout, NULL);
  225 }
  226 
  227 /*ARGSUSED*/
  228 static  int
  229 logioctl(struct dev_ioctl_args *ap)
  230 {
  231         long l;
  232 
  233         switch (ap->a_cmd) {
  234         case FIONREAD:
  235                 /* return number of characters immediately available */
  236                 crit_enter();
  237                 l = msgbufp->msg_bufx - msgbufp->msg_bufr;
  238                 crit_exit();
  239                 if (l < 0)
  240                         l += msgbufp->msg_size;
  241                 *(int *)ap->a_data = l;
  242                 break;
  243 
  244         case FIOASYNC:
  245                 if (*(int *)ap->a_data)
  246                         logsoftc.sc_state |= LOG_ASYNC;
  247                 else
  248                         logsoftc.sc_state &= ~LOG_ASYNC;
  249                 break;
  250 
  251         case FIOSETOWN:
  252                 return (fsetown(*(int *)ap->a_data, &logsoftc.sc_sigio));
  253 
  254         case FIOGETOWN:
  255                 *(int *)ap->a_data = fgetown(&logsoftc.sc_sigio);
  256                 break;
  257 
  258         /* This is deprecated, FIOSETOWN should be used instead. */
  259         case TIOCSPGRP:
  260                 return (fsetown(-(*(int *)ap->a_data), &logsoftc.sc_sigio));
  261 
  262         /* This is deprecated, FIOGETOWN should be used instead */
  263         case TIOCGPGRP:
  264                 *(int *)ap->a_data = -fgetown(&logsoftc.sc_sigio);
  265                 break;
  266 
  267         default:
  268                 return (ENOTTY);
  269         }
  270         return (0);
  271 }
  272 
  273 static void
  274 log_drvinit(void *unused)
  275 {
  276         make_dev(&log_ops, 0, UID_ROOT, GID_WHEEL, 0600, "klog");
  277 }
  278 
  279 SYSINIT(logdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,log_drvinit,NULL)

Cache object: 7cd2678d46a5c97d6198fd18180fc3ba


[ 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.