Subject: Re: interrupting kevent()
To: Bill Stouder-Studenmund <wrstuden@netbsd.org>
From: Antti Kantee <pooka@cs.hut.fi>
List: tech-kern
Date: 10/25/2007 13:44:05
--9jxsPFA5p3P2qPhR
Content-Type: text/plain; charset=iso-8859-1
Content-Disposition: inline
Content-Transfer-Encoding: 8bit
On Wed Oct 24 2007 at 22:52:51 -0700, Bill Stouder-Studenmund wrote:
> The canonical way I know to do this is to create a pipe and add a kevent
> to listen to it. That way you get what you want w/o any kernel mods. Plus,
> if you use an atomic write (everything in one write{,v}() call), then you
> can use the write to the pipe as a form of ITC (Inter-Thread
> Communication) - not only do you wake the thread, but you carry the
> message w/o needing locks on the sending side.
Yes, but see other mails in the thread. And no are locks needed now
either.
> The concern/objection I have to what you do have is that it doesn't follow
> kevent methodology. I think your kevent should show up as an event. As it
> stands, you only get an event if there is nothing else going on, and it
> shows up out-of-band with the events. A busy server could delay
> conveying the "tickle" for a few system calls.
Except it isn't a real event. A signal doesn't show up as a real event.
A timeout doesn't show up as a real event. Why should this?
There was a bug in the patch which caused a tickle to be returned even
if there were real events pending. That was unintentional (obviously).
I'm attaching a new version where this is fixed.
> So I'd like to politely ask you to go back to the drawing board. While I
> think something other than a pipe could be cute, I think we should do
> something that will work in more cases than just your current one.
Unfortunately with just vague handwaving I have no idea of what you
want here. Pending the kitchen_sink.h design, I'll use this method in
my local tree and commit something general.
--
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"
--9jxsPFA5p3P2qPhR
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="kticklev2.patch"
Index: 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_event.c 8 Oct 2007 15:12:07 -0000 1.41
+++ kern_event.c 25 Oct 2007 10:33:23 -0000
@@ -958,8 +958,11 @@ kqueue_scan(struct file *fp, size_t maxe
simple_lock(&kq->kq_lock);
if (kq->kq_count == 0) {
if (timeout < 0) {
+ simple_unlock(&kq->kq_lock);
error = EWOULDBLOCK;
+ } else if (kq->kq_state & KQ_TICKLED) {
simple_unlock(&kq->kq_lock);
+ error = EINTR;
} else {
kq->kq_state |= KQ_SLEEP;
error = ltsleep(kq, PSOCK | PCATCH | PNORELOCK,
@@ -1061,6 +1064,11 @@ kqueue_scan(struct file *fp, size_t maxe
&kq->kq_kev[0], ulistp, nevents, nkev);
*retval = maxevents - count;
+ /* We are returning, clear tickle-indicator */
+ simple_lock(&kq->kq_lock);
+ kq->kq_state &= ~KQ_TICKLED;
+ simple_unlock(&kq->kq_lock);
+
return (error);
}
@@ -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;
--9jxsPFA5p3P2qPhR--