Subject: interrupting kevent()
To: None <tech-kern@netbsd.org>
From: Antti Kantee <pooka@cs.hut.fi>
List: tech-kern
Date: 10/23/2007 15:45:49
--YiEDa0DAkWCtVeE4
Content-Type: text/plain; charset=iso-8859-1
Content-Disposition: inline
Content-Transfer-Encoding: 8bit
Hi,
I have a dual eventloop/thread model and I need to interrupt the event
call from a thread sometimes. I didn't find any sensible way of doing
this, so I added a KEVENT_TICKLE ioctl() to kqueue for interrupting
the wait.
Did I miss something or does the following look ok?
--
Antti Kantee <pooka@iki.fi> Of course he runs NetBSD
http://www.iki.fi/pooka/ http://www.NetBSD.org/
"la qualité la plus indispensable du cuisinier est l'exactitude"
--YiEDa0DAkWCtVeE4
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="kqueue.patch"
Index: kern/kern_event.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_event.c,v
retrieving revision 1.41
diff -p -u -r1.41 kern_event.c
--- kern/kern_event.c 8 Oct 2007 15:12:07 -0000 1.41
+++ kern/kern_event.c 23 Oct 2007 12:28:23 -0000
@@ -956,7 +956,7 @@ kqueue_scan(struct file *fp, size_t maxe
kevp = kq->kq_kev;
s = splsched();
simple_lock(&kq->kq_lock);
- if (kq->kq_count == 0) {
+ if (kq->kq_count == 0 && (kq->kq_state & KQ_TICKLED) == 0) {
if (timeout < 0) {
error = EWOULDBLOCK;
simple_unlock(&kq->kq_lock);
@@ -976,6 +976,14 @@ kqueue_scan(struct file *fp, size_t maxe
goto done;
}
+ if (kq->kq_state & KQ_TICKLED) {
+ kq->kq_state &= ~KQ_TICKLED;
+ simple_unlock(&kq->kq_lock);
+ splx(s);
+ error = EINTR;
+ goto done;
+ }
+
/* mark end of knote list */
TAILQ_INSERT_TAIL(&kq->kq_head, marker, kn_tqe);
simple_unlock(&kq->kq_lock);
@@ -1098,6 +1106,9 @@ kqueue_write(struct file *fp, off_t *off
* KFILTER_BYNAME find name for filter, and return result in
* name, which is of size len.
* KFILTER_BYFILTER find filter for name. len is ignored.
+ *
+ * A third can be used to wake up a kevent:
+ * KEVENT_TICKLE
*/
/*ARGSUSED*/
static int
@@ -1105,9 +1116,11 @@ kqueue_ioctl(struct file *fp, u_long com
{
struct kfilter_mapping *km;
const struct kfilter *kfilter;
+ struct kqueue *kq;
char *name;
int error;
+ kq = (struct kqueue *)fp->f_data;
km = (struct kfilter_mapping *)data;
error = 0;
@@ -1136,6 +1149,13 @@ kqueue_ioctl(struct file *fp, u_long com
FREE(name, M_KEVENT);
break;
+ case KEVENT_TICKLE:
+ simple_lock(&kq->kq_lock);
+ kq->kq_state |= KQ_TICKLED;
+ simple_unlock(&kq->kq_lock);
+ kqueue_wakeup(kq);
+ break;
+
default:
error = ENOTTY;
Index: sys/event.h
===================================================================
RCS file: /cvsroot/src/sys/sys/event.h,v
retrieving revision 1.18
diff -p -u -r1.18 event.h
--- sys/event.h 21 Jul 2007 19:20:40 -0000 1.18
+++ sys/event.h 23 Oct 2007 12:28:26 -0000
@@ -141,6 +141,7 @@ struct kfilter_mapping {
#define KFILTER_BYFILTER _IOWR('k', 0, struct kfilter_mapping)
/* map name to filter (len ignored) */
#define KFILTER_BYNAME _IOWR('k', 1, struct kfilter_mapping)
+#define KEVENT_TICKLE _IO('k', 2)
#ifdef _KERNEL
#include <sys/mallocvar.h> /* for malloc types */
Index: sys/eventvar.h
===================================================================
RCS file: /cvsroot/src/sys/sys/eventvar.h,v
retrieving revision 1.7
diff -p -u -r1.7 eventvar.h
--- sys/eventvar.h 8 Oct 2007 15:45:54 -0000 1.7
+++ sys/eventvar.h 23 Oct 2007 12:28:29 -0000
@@ -45,6 +45,7 @@ struct kqueue {
struct filedesc *kq_fdp;
int kq_state;
#define KQ_SLEEP 0x01
+#define KQ_TICKLED 0x02
struct kevent kq_kev[KQ_NEVENTS];
};
--YiEDa0DAkWCtVeE4--