On Fri, 22 Jan 2010, Jilles Tjoelker wrote:

On Fri, Jan 22, 2010 at 07:55:47AM -0800, Randall Stewart wrote:
On Jan 22, 2010, at 7:33 AM, Ivan Voras wrote:

On 01/22/10 16:10, Ed Schouten wrote:
* Ivan Voras<ivo...@freebsd.org>  wrote:
This is a good and useful addition! I think Windows has
implemented a
generalization of this (called "wait objects" or something like
that),
which effectively allows a select()- (or in this case kqueue())-like
syscall to wait on both file descriptors and condvars (as well as
probably other MS-style objects). It's useful for multiplexing
events
for dissimilar sources.

NtWaitForSingleObject(), NtWaitForMultipleObjects(), etc. :-)

Yes, I was thinking about WaitForMultipleObjects() - I sometimes
wished I had it in FreeBSD :)

I think the hackers@ side of the thread is missing the original link
to the patch file offered for review, so here it is:

http://people.freebsd.org/~rrs/kque_umtx.patch

Cool.

My kqueue-fu level is too low to be really useful here but from what
I've read it looks like a logical and even reasonably clean way of
doing it.

thanks it made sense to me ;-)

If I read the comment at filt_umtxattach() correctly, in the best
case you would need an extension to the kevent structure to add more
fields like data & udata (for passing values back and forth between
userland and kernel). I agree with this - it would be very
convenient for some future purposes (like file modification
notification) if the kernel filter could both accept and return a
struct of data from/to the userland.

Yeah, more arguments inside the kevent would allow me to add the
COND_CV_WAIT* where a lock and condition are passed
in as well... But I was hesitant to add more than was already there
since doing
so would cause ABI ripples that I did not want to face.

I don't think passing the lock is needed.

Traditional way (error handling omitted):

pthread_mutex_lock(&M);
while (!P)
        pthread_cond_wait(&C, &M);
do_work();
pthread_mutex_unlock(&M);

The thread must be registered as a waiter before unlocking the mutex,
otherwise a wakeup could be lost.

Possible kqueue way (error handling omitted):

kq = kqueue();
pthread_mutex_lock(&M);
while (!P)
{
        pthread_cond_kqueue_register_wait_np(&C, kq);
        pthread_mutex_unlock(&M);
        nevents = kevent(kq, NULL, 0, events, 1, NULL);
        ... handle other events ...
        pthread_mutex_lock(&M);
}
do_work();
pthread_mutex_unlock(&M);
close(kq);

This is ugly from the userland point of view -- if you need
this, I would encompass everything in a kq event object
thingie.  As in:

/*
 * Create an object containing everything you need to wait
 * or signal kqueue events.
 */
kq = kqueue();
kq_obj = kq_create(kq, ...);

kq_lock(&kq_obj);
while (!P)
{
        /* Atomically unlocks kq_obj and blocks. */
        nevents = kq_wait(&kq_obj, ...);

        /* When you wakeup, kq_obj is locked again. */
}

do_work();  /* Wouldn't you want to unlock before this? */
kq_unlock(&kq_obj);


/* From another thread, you could do: */
kq_lock(&kq_obj);
if (kq_waiters(&kq_obj) > 0)
        kq_signal(&kq_obj);  /* or kq_broadcast() */
kq_unlock(&kq_obj);


--
DE
_______________________________________________
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"

Reply via email to