From owner-freebsd-hackers@FreeBSD.ORG Mon Nov 15 19:11:34 2010 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id EED46106564A for ; Mon, 15 Nov 2010 19:11:33 +0000 (UTC) (envelope-from jhb@freebsd.org) Received: from cyrus.watson.org (cyrus.watson.org [65.122.17.42]) by mx1.freebsd.org (Postfix) with ESMTP id B11598FC20 for ; Mon, 15 Nov 2010 19:11:33 +0000 (UTC) Received: from bigwig.baldwin.cx (66.111.2.69.static.nyinternet.net [66.111.2.69]) by cyrus.watson.org (Postfix) with ESMTPSA id 3E80E46B5B; Mon, 15 Nov 2010 14:11:33 -0500 (EST) Received: from jhbbsd.localnet (smtp.hudson-trading.com [209.249.190.9]) by bigwig.baldwin.cx (Postfix) with ESMTPSA id 402F38A009; Mon, 15 Nov 2010 14:11:32 -0500 (EST) From: John Baldwin To: Paul LeoNerd Evans Date: Mon, 15 Nov 2010 14:10:45 -0500 User-Agent: KMail/1.13.5 (FreeBSD/7.3-CBSD-20101102; KDE/4.4.5; amd64; ; ) References: <20101112184000.GS11110@cel.leo> <201011151125.42697.jhb@freebsd.org> <20101115181211.GV11110@cel.leo> In-Reply-To: <20101115181211.GV11110@cel.leo> MIME-Version: 1.0 Content-Type: Text/Plain; charset="iso-8859-15" Content-Transfer-Encoding: 7bit Message-Id: <201011151410.46130.jhb@freebsd.org> X-Greylist: Sender succeeded SMTP AUTH, not delayed by milter-greylist-4.2.6 (bigwig.baldwin.cx); Mon, 15 Nov 2010 14:11:32 -0500 (EST) X-Virus-Scanned: clamav-milter 0.96.3 at bigwig.baldwin.cx X-Virus-Status: Clean X-Spam-Status: No, score=-1.9 required=4.2 tests=BAYES_00 autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on bigwig.baldwin.cx Cc: freebsd-hackers@freebsd.org Subject: Re: Managing userland data pointers in kqueue/kevent X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 15 Nov 2010 19:11:34 -0000 On Monday, November 15, 2010 1:12:11 pm Paul LeoNerd Evans wrote: > On Mon, Nov 15, 2010 at 11:25:42AM -0500, John Baldwin wrote: > > I think the assumption is that userland actually maintains a reference on the > > specified object (e.g. a file descriptor) and will know to drop the associated > > data when the file descriptor is closed. That is, think of the kevent as a > > member of an eventable object rather than a separate object that has a > > reference to the eventable object. When the eventable object's reference > > count drops to zero in userland, then the kevent should be deleted, either via > > EV_DELETE, or implicitly (e.g. by closing the associated file descriptor). > > Ah. Well, that could be considered a bit more awkward for the use case I > wanted to apply. The idea was that the udata would refer effectively > to a closure, to invoke when the event happens. The idea being you can > just add an event watcher by, say: > > $ev->EV_SET( $pid, EVFILT_PROC, 0, NOTE_EXIT, 0, sub { > print STDERR "The child process $pid has now exited\n"; > } ); > > So, the kernel's udata pointer effectively holds the only reference to > this anonymous closure. It's much more flexible this way, especially for > oneshot events like that. > > The beauty is also that the kevents() loop can simply know that the > udata is always a code reference so just has to invoke it to do whatever > the original caller wanted to do. > > Keep in mind my use-case here; I'm not trying to be one specific > application, it's a general-purpose kevent-wrapping library. So is GCD (Apple's libdispatch). It also implements closures on top of kevent. However, the way it works is that it doesn't expose kevent() directly, instead it uses kevent to implement asynchronous I/O on a socket for example, and since it is logically managing the life cycle of a socket, it knows when the socket is closed and cleans up then. > > I think in your case you should not give the kevent a reference to your > > object, but instead remove the associated event for a given object when an > > object's refcount drops to zero. > > Well that's certainly doable in longrunning watches, but I don't think > it sounds very convenient for a oneshot event; see the above example for > justification. For the above case, if you know an event is one shot, you should either use EV_ONESHOT, or use a wrapper around the closure that clears the event after the closure runs (or possibly before the closure runs?) > Also it again begs my question, worth repeating here: > > On Friday, November 12, 2010 1:40:00 pm Paul LeoNerd Evans wrote: > > I had > > thought the point of kqueue/kevent is the O(1) nature of it, which is > > among why the kernel is storing that void *udata pointer in the first > > place. If I have to store a mapping from every filter+identity back to > > my data pointer, why does the kernel store one at all? I could just > > ignore the udata field and use my mapping for my own purposes. > > If you're saying that in my not-so-rare use case, I don't want to be > using udata, and instead keeping my own mapping, why does the kernel > provide this udata field at all? Your use case is rare. Almost all consumers of kevent() that I've seen use kevent() as one part of a system that maintain the lifecycle of objects. Those objects are only accessed within the system, so the system knows when an object is closed and can release the resources at the same time. -- John Baldwin