From owner-freebsd-arch Thu Apr 6 22:16:47 2000 Delivered-To: freebsd-arch@freebsd.org Received: from ns1.yes.no (ns1.yes.no [195.204.136.10]) by hub.freebsd.org (Postfix) with ESMTP id 49B4737B5ED for ; Thu, 6 Apr 2000 22:16:45 -0700 (PDT) (envelope-from eivind@bitbox.follo.net) Received: from bitbox.follo.net (bitbox.follo.net [195.204.143.218]) by ns1.yes.no (8.9.3/8.9.3) with ESMTP id HAA16744 for ; Fri, 7 Apr 2000 07:20:19 +0200 (CEST) Received: (from eivind@localhost) by bitbox.follo.net (8.8.8/8.8.6) id HAA35292 for freebsd-arch@freebsd.org; Fri, 7 Apr 2000 07:16:44 +0200 (CEST) Received: from prism.flugsvamp.com (cb58709-a.mdsn1.wi.home.com [24.17.241.9]) by hub.freebsd.org (Postfix) with ESMTP id 9D32737C237 for ; Thu, 6 Apr 2000 22:16:01 -0700 (PDT) (envelope-from jlemon@flugsvamp.com) Received: (from jlemon@localhost) by prism.flugsvamp.com (8.9.3/8.9.3) id AAA44895; Fri, 7 Apr 2000 00:19:29 -0500 (CDT) (envelope-from jlemon) Date: Fri, 7 Apr 2000 00:19:29 -0500 From: Jonathan Lemon To: Matthew Dillon Cc: Jonathan Lemon , Archie Cobbs , freebsd-arch@freebsd.org Subject: Re: RFC: kqueue API and rough code Message-ID: <20000407001929.N80578@prism.flugsvamp.com> References: <200004070107.SAA97591@bubba.whistle.com> <200004070220.TAA92896@apollo.backplane.com> <20000406220454.J80578@prism.flugsvamp.com> <200004070340.UAA93335@apollo.backplane.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Mailer: Mutt 1.0pre2i In-Reply-To: <200004070340.UAA93335@apollo.backplane.com> Sender: owner-freebsd-arch@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG I won't analyze this too much, since I think that with Matt's next reply, we moved much closer to an agreement. But I wanted to comment on a few things: On Thu, Apr 06, 2000 at 08:40:19PM -0700, Matthew Dillon wrote: > Consider a program that is linked against three or four third party > libraries... for example, consider a program linked against the X11 > libraries. > > Now lets say that the X11 libraries are multi-threaded and want to use > the kernel queue mechanism to handle events asynchronously in the > user space of the program using the library. > > It is not possible for the X11 libraries to do this if they happen to use > a different dispatch mechanism then your main loop uses. In fact, if you > look at how X (and other non-embedded subsystems) are organized, it is > precisely this problem that leads to an inability to scale their > interfaces. i.e. you can't use your neat cool event mechanism if you > have to call another library's code that serves as the main loop for your > program rather then you being able to serve as the main loop for your > program. My vision in this scenario is that each library will create it's own kqueue, and register the events that it is interested in within that kqueue. This way there is no conflict between events registered by a library, and those registered by the main program. (recall that the uniqifier for an event within a kqueue is (ident/filter). The libraries then either run in their own thread, and register their thread with the main process, _or_ they register the kq descriptor with the main process, and the process calls the library when there is an event pending. main code: poll( bunch of kq's ) call_library(kq) library: event = kevent(kq, ....) > /* > * Module implements an asynchronous write with timeout. > */ > somemodule_messing_with_some_tcp_connection(struct manage *m) > { > setdispatch(m->fd, m, module_write, priority, EVENT_WRITE); > setdispatch(m->fd, m, module_read, priority, EVENT_READ); > /* returns here */ > } > > module_write(int fd, struct manage *m, int r) > { > issues write and either clears the dispatch function > or allows it to remain, depending. > } > > module_read(int fd, struct manage *m, int r) > { > issues read, deals with read data. > } As a matter of fact, this pretty closely matches a project that I'm working on. What's missing here is the definition of setdispatch() and dispatch(). I see these as being: setdispatch(fd, m, function, priority, filter) { kq = module_kq(m); save_info(fd, filter, m, function, priority, ....) kevent(kq, fd, filter, ...) } dispatch() { (fd, filter, data) = fetch_event(kq) (fcn, m, pri) = retrieve_info(kq, fd, filter) fcn(m, fd, r, data) } Note that the only difference is that this forces the user to keep a (fd/filter) --> udata mapping table; I agree that by allowing this pointer to be passed to/from the kernel, it can save the application some lookup time. > Notice a couple of things? Like for example the above code is > completely independant of any other module or library. It does not > require a central loop to read events nor does it have to use the > same support library that some other library might use to implement > event handling. But only if the event dispatch and user data > ('m' in this case, which the kernel does not interpret but simply > passes to the event handler) are directly supported by the kernel. In essence, you seem to be arguing for a dispatch() mechanism in the kernel, which allows functions to be registered, and the kernel makes a direct callback. Without this, you still have to have a user-level dispatcher, which pulls events off a queue and then does the dispatch. However, the mechanism here isn't designed to be a dispatch function, although it doesn't preclude later implementation of one either. -- Jonathan To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-arch" in the body of the message