Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 6 Apr 2000 23:49:05 -0500
From:      Jonathan Lemon <jlemon@flugsvamp.com>
To:        Matthew Dillon <dillon@apollo.backplane.com>
Cc:        Jonathan Lemon <jlemon@flugsvamp.com>, Archie Cobbs <archie@whistle.com>, freebsd-arch@freebsd.org
Subject:   Re: RFC: kqueue API and rough code
Message-ID:  <20000406234905.K80578@prism.flugsvamp.com>
In-Reply-To: <200004070401.VAA93492@apollo.backplane.com>
References:  <200004070107.SAA97591@bubba.whistle.com> <200004070220.TAA92896@apollo.backplane.com> <20000406220454.J80578@prism.flugsvamp.com> <200004070401.VAA93492@apollo.backplane.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Thu, Apr 06, 2000 at 09:01:39PM -0700, Matthew Dillon wrote:
> 
>     Hey! (I snap my fingers), I got it!
> 
>     There is no need to copy anything back and forth from user space to
>     kernel space!
> 
>     It's simple, really.  How about this API:
> 
> 	qfd = kqueue();
> 	kqueuectl(qfd, filter, fd, struct event *ev);
> 	ev = kevent(qfd, timeout);
> 
> 	or (another way to do kevent):
> 
> 	n = kevent(qfd, struct event **ary, int nmax, struct timeval *timeout);
> 
>     The key thing here is that the kernel creates its own internal data 
>     structure which has the descriptor, filter operation, and a pointer
>     to the *USER* event structure.  The kernel would not otherwise copy
>     the user event structure into kernel space nor would it copy it back
>     to return the event.

Exactly.  Now, this is just what the code does at the moment, only
slightly differently.  In the scheme above, every "registration", 
via kqueuectl, copies in (filter, fd, ev), and then the kernel
additionally copies in (data, flags), as those are also input parameters.
So far, this turns out to be one more element than the current structure.

When returning data, the kernel does a copyout of (data, flags) to
the saved event structure, and then copies out the pointer to the
structure.  This saves one copy over what I have now.

In total, this comes out equal to just copying (data,flags,ident,filter).

The only difference that I can see is that with the scheme above,
the user-level code must keep the data in the same location, which
may not be ideal for some applications.  It also binds the implementation
between user and kernel a little tighter than I would like.

Looking at it another way, I use (event/filter) as a capability
descriptor to user space rather than a pointer.  It seems that if
you simply had (void *udata) field to the kevent structure,
then it would be easy for you to implement your method above.  Then
specific filters (which understand the layout of the structure
that *uevent points to) could be written access to extended data:

	struct user_event {
		int 	priority;
 	    	void	(*dispatch)(struct event *ev);
		int 	thread;
		struct kevent {
	 	    int		fd;
 		    short	filter;
 		    short	flags;
	 	    long	data;
		    void	*uevent;
		}
	}

How about that?  The kernel only cares about `struct kevent'.  
It won't touch the 'uevent' pointer at all.   In theory, you
could use the `data' field as a pointer, but for uniformity
I'd rather just add one more field.
--
Jonathan




To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-arch" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20000406234905.K80578>