kernel - Add kqueue to log device (/dev/klog)
authorSamuel J. Greear <sjg@thesjg.com>
Tue, 15 Jun 2010 16:44:44 +0000 (16:44 +0000)
committerSamuel J. Greear <sjg@thesjg.com>
Wed, 30 Jun 2010 00:31:44 +0000 (00:31 +0000)
sys/kern/subr_log.c

index e6b4fa5..d5ab5b5 100644 (file)
@@ -51,6 +51,7 @@
 #include <sys/signalvar.h>
 #include <sys/kernel.h>
 #include <sys/poll.h>
+#include <sys/event.h>
 #include <sys/filedesc.h>
 #include <sys/sysctl.h>
 #include <sys/thread2.h>
@@ -63,17 +64,21 @@ static      d_close_t       logclose;
 static d_read_t        logread;
 static d_ioctl_t       logioctl;
 static d_poll_t        logpoll;
+static d_kqfilter_t    logkqfilter;
 
 static void logtimeout(void *arg);
+static void logfiltdetach(struct knote *kn);
+static int  logfiltread(struct knote *kn, long hint);
 
 #define CDEV_MAJOR 7
 static struct dev_ops log_ops = {
-       { "log", CDEV_MAJOR, 0 },
+       { "log", CDEV_MAJOR, D_KQFILTER },
        .d_open =       logopen,
        .d_close =      logclose,
        .d_read =       logread,
        .d_ioctl =      logioctl,
        .d_poll =       logpoll,
+       .d_kqfilter =   logkqfilter
 };
 
 static struct logsoftc {
@@ -178,6 +183,55 @@ logpoll(struct dev_poll_args *ap)
        return (0);
 }
 
+static struct filterops logread_filtops =
+       { 1, NULL, logfiltdetach, logfiltread };
+
+static int
+logkqfilter(struct dev_kqfilter_args *ap)
+{
+       struct knote *kn = ap->a_kn;
+       struct klist *klist = &logsoftc.sc_selp.si_note;
+
+       ap->a_result = 0;
+       switch (kn->kn_filter) {
+       case EVFILT_READ:
+               kn->kn_fop = &logread_filtops;
+               break;
+       default:
+               ap->a_result = 1;
+               return (0);
+       }
+
+       crit_enter();
+       SLIST_INSERT_HEAD(klist, kn, kn_selnext);
+       crit_exit();
+
+       return (0);
+}
+
+static void
+logfiltdetach(struct knote *kn)
+{
+       struct klist *klist = &logsoftc.sc_selp.si_note;
+
+       crit_enter();
+       SLIST_REMOVE(klist, kn, knote, kn_selnext);
+       crit_exit();
+}
+
+static int
+logfiltread(struct knote *kn, long hint)
+{
+       int ret = 0;
+
+       crit_enter();
+       if (msgbufp->msg_bufr != msgbufp->msg_bufx)
+               ret = 1;
+       crit_exit();
+
+       return (ret);
+}
+
 static void
 logtimeout(void *arg)
 {