From a73855e8566a08edda210afca4ae5b3048ab5bc1 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Mon, 15 Jan 2007 01:26:56 +0000 Subject: [PATCH] Add O_ASYNC (SIGIO) support to kqueue(). Also add F_SETOWN support. --- sys/kern/kern_event.c | 37 ++++++++++++++++++++++++++++++++++--- sys/sys/event.h | 6 ++++-- sys/sys/eventvar.h | 7 ++++++- 3 files changed, 44 insertions(+), 6 deletions(-) diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index 225ba3442f..4b6db54b64 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -24,7 +24,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/kern/kern_event.c,v 1.2.2.10 2004/04/04 07:03:14 cperciva Exp $ - * $DragonFly: src/sys/kern/kern_event.c,v 1.31 2006/12/23 00:35:04 swildner Exp $ + * $DragonFly: src/sys/kern/kern_event.c,v 1.32 2007/01/15 01:26:55 dillon Exp $ */ #include @@ -49,6 +49,8 @@ #include #include #include +#include +#include #include #include @@ -751,7 +753,29 @@ kqueue_write(struct file *fp, struct uio *uio, struct ucred *cred, int flags) static int kqueue_ioctl(struct file *fp, u_long com, caddr_t data, struct ucred *cred) { - return (ENOTTY); + struct kqueue *kq; + int error; + + get_mplock(); + kq = (struct kqueue *)fp->f_data; + + switch(com) { + case FIOASYNC: + if (*(int *)data) + kq->kq_state |= KQ_ASYNC; + else + kq->kq_state &= ~KQ_ASYNC; + error = 0; + break; + case FIOSETOWN: + error = fsetown(*(int *)data, &kq->kq_sigio); + break; + default: + error = ENOTTY; + break; + } + rel_mplock(); + return (error); } /* @@ -844,6 +868,7 @@ kqueue_close(struct file *fp) } } fp->f_data = NULL; + funsetown(kq->kq_sigio); rel_mplock(); kfree(kq, M_KQUEUE); @@ -977,7 +1002,13 @@ knote_enqueue(struct knote *kn) TAILQ_INSERT_TAIL(&kq->kq_head, kn, kn_tqe); kn->kn_status |= KN_QUEUED; - kq->kq_count++; + ++kq->kq_count; + + /* + * Send SIGIO on request (typically set up as a mailbox signal) + */ + if (kq->kq_sigio && (kq->kq_state & KQ_ASYNC) && kq->kq_count == 1) + pgsigio(kq->kq_sigio, SIGIO, 0); crit_exit(); kqueue_wakeup(kq); } diff --git a/sys/sys/event.h b/sys/sys/event.h index 139264d2b7..f8b9560a8f 100644 --- a/sys/sys/event.h +++ b/sys/sys/event.h @@ -24,7 +24,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/sys/event.h,v 1.5.2.6 2003/02/09 15:28:13 nectar Exp $ - * $DragonFly: src/sys/sys/event.h,v 1.6 2006/05/20 02:42:13 dillon Exp $ + * $DragonFly: src/sys/sys/event.h,v 1.7 2007/01/15 01:26:56 dillon Exp $ */ #ifndef _SYS_EVENT_H_ @@ -176,7 +176,9 @@ extern void knote_fdclose(struct proc *p, int fd); extern int kqueue_register(struct kqueue *kq, struct kevent *kev, struct thread *td); -#else /* !_KERNEL */ +#endif /* !_KERNEL */ + +#if !defined(_KERNEL) || defined(_KERNEL_VIRTUAL) #include struct timespec; diff --git a/sys/sys/eventvar.h b/sys/sys/eventvar.h index 73e52c7b96..61d712f594 100644 --- a/sys/sys/eventvar.h +++ b/sys/sys/eventvar.h @@ -24,7 +24,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/sys/eventvar.h,v 1.1.2.2 2000/07/18 21:49:12 jlemon Exp $ - * $DragonFly: src/sys/sys/eventvar.h,v 1.6 2006/06/10 20:00:17 dillon Exp $ + * $DragonFly: src/sys/sys/eventvar.h,v 1.7 2007/01/15 01:26:56 dillon Exp $ */ #ifndef _SYS_EVENTVAR_H_ @@ -45,6 +45,9 @@ #ifndef _SYS_SELINFO_H_ #include #endif +#ifndef _SYS_FILEDESC_H_ +#include +#endif #define KQ_NEVENTS 8 /* minimize copy{in,out} calls */ @@ -53,11 +56,13 @@ struct kqueue { TAILQ_HEAD(kqlist, knote) kq_head; /* list of pending event */ int kq_count; /* number of pending events */ + struct sigio *kq_sigio; struct selinfo kq_sel; struct filedesc *kq_fdp; int kq_state; #define KQ_SEL 0x01 #define KQ_SLEEP 0x02 +#define KQ_ASYNC 0x04 struct kevent kq_kev[KQ_NEVENTS]; }; -- 2.11.4.GIT