diff options
author | Konstantin Belousov <kib@FreeBSD.org> | 2012-02-01 14:34:52 +0000 |
---|---|---|
committer | Konstantin Belousov <kib@FreeBSD.org> | 2012-02-01 14:34:52 +0000 |
commit | 6af519cf187b8ca1968d35e84dc4cec6107f2e26 (patch) | |
tree | f09fa09c934afb788a380e77fb43f728c59e5cd3 /sys/kern/subr_log.c | |
parent | c72ef339bfc9f4d534c0210114c28ed075fcaa52 (diff) | |
download | src-6af519cf187b8ca1968d35e84dc4cec6107f2e26.tar.gz src-6af519cf187b8ca1968d35e84dc4cec6107f2e26.zip |
Add kqueue support to /dev/klog.
Submitted by: Mateusz Guzik <mjguzik gmail com>
PR: kern/156423
MFC after: 1 weeks
Notes
Notes:
svn path=/head/; revision=230866
Diffstat (limited to 'sys/kern/subr_log.c')
-rw-r--r-- | sys/kern/subr_log.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/sys/kern/subr_log.c b/sys/kern/subr_log.c index dfd0f94594ab..8981358a2ab0 100644 --- a/sys/kern/subr_log.c +++ b/sys/kern/subr_log.c @@ -59,6 +59,7 @@ 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); @@ -69,9 +70,20 @@ static struct cdevsw log_cdevsw = { .d_read = logread, .d_ioctl = logioctl, .d_poll = logpoll, + .d_kqfilter = logkqfilter, .d_name = "log", }; +static int logkqread(struct knote *note, long hint); +static void logkqdetach(struct knote *note); + +static struct filterops log_read_filterops = { + .f_isfd = 1, + .f_attach = NULL, + .f_detach = logkqdetach, + .f_event = logkqread, +}; + static struct logsoftc { int sc_state; /* see above for possibilities */ struct selinfo sc_selp; /* process waiting on select call */ @@ -181,6 +193,40 @@ logpoll(struct cdev *dev, int events, struct thread *td) return (revents); } +static int +logkqfilter(struct cdev *dev, struct knote *kn) +{ + + if (kn->kn_filter != EVFILT_READ) + return (EINVAL); + + kn->kn_fop = &log_read_filterops; + kn->kn_hook = NULL; + + mtx_lock(&msgbuf_lock); + knlist_add(&logsoftc.sc_selp.si_note, kn, 1); + mtx_unlock(&msgbuf_lock); + return (0); +} + +static int +logkqread(struct knote *kn, long hint) +{ + + mtx_assert(&msgbuf_lock, MA_OWNED); + kn->kn_data = msgbuf_getcount(msgbufp); + return (kn->kn_data != 0); +} + +static void +logkqdetach(struct knote *kn) +{ + + mtx_lock(&msgbuf_lock); + knlist_remove(&logsoftc.sc_selp.si_note, kn, 1); + mtx_unlock(&msgbuf_lock); +} + static void logtimeout(void *arg) { @@ -198,6 +244,7 @@ logtimeout(void *arg) } msgbuftrigger = 0; selwakeuppri(&logsoftc.sc_selp, LOG_RDPRI); + KNOTE_LOCKED(&logsoftc.sc_selp.si_note, 0); if ((logsoftc.sc_state & LOG_ASYNC) && logsoftc.sc_sigio != NULL) pgsigio(&logsoftc.sc_sigio, SIGIO, 0); cv_broadcastpri(&log_wakeup, LOG_RDPRI); @@ -256,6 +303,7 @@ log_drvinit(void *unused) cv_init(&log_wakeup, "klog"); callout_init_mtx(&logsoftc.sc_callout, &msgbuf_lock, 0); + knlist_init_mtx(&logsoftc.sc_selp.si_note, &msgbuf_lock); make_dev_credf(MAKEDEV_ETERNAL, &log_cdevsw, 0, NULL, UID_ROOT, GID_WHEEL, 0600, "klog"); } |