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>