Re: [take25 1/6] kevent: Description.

From: Evgeniy Polyakov
Date: Fri Nov 24 2006 - 06:47:48 EST


On Thu, Nov 23, 2006 at 12:00:45PM -0800, Ulrich Drepper (drepper@xxxxxxxxxx) wrote:
> Evgeniy Polyakov wrote:
> >uidx is an index, starting from which there are unread entries. It is
> >updated by userspace when it commits entries, so it is 'consumer'
> >pointer, while kidx is an index where kernel will put new entries, i.e.
> >'producer' index. We definitely need them both.
> >Userspace can only update (implicitly by calling kevent_commit()) uidx.
>
> Right, which is why exporting this entry is not needed. Keep the
> interface as small as possible.

If there are several callers of kevent_commit(), uidx can be changed far
than first user expects, so there should be possibility to check that
value. It is thus exported into shared ring buffer structure.

> Userlevel has to maintain its own index. Just assume kevent_wait
> returns 10 new entries and you have multiple threads. In this case all
> threads take their turns and pick an entry from the ring buffer. This
> basically has to be done with something like this (I ignore wrap-arounds
> here to simplify the example):
>
> int getidx() {
> while (uidx < kidx)
> if (atomic_cmpxchg(uidx, uidx + 1, uidx) == 0)
> return uidx;
> return -1;
> }
>
> Very much simplified but it should show that we need a writable copy of
> the uidx. And this value at any time must be consistent with the index
> the kernel assumes.

I seriously doubt it is simpler than having index provided by kernel.

> The current ring_uidx value can at best be used to reinitialize the
> userlevel uidx value after each kevent_wait call but this is unnecessary
> at best (since uidx must already have this value) and racy in problem
> cases (what if more than one thread gets woken concurrently with uidx
> having the same value and one thread stores the uidx value and
> immediately increments it to get an index; the second store would
> overwrite the increment).
>
> I can assure you that any implementation I write would not use the
> ring_uidx value. Only trivial, single-threaded examples like you
> ring_buffer.c could ever take advantage of this value. It's not worth it.

You propose to make uidx shared local variable - it is doable, but it
is not required - userspace can use kernel's variable, since it is
updated exactly in the places where that index is changed.

> --
> â Ulrich Drepper â Red Hat, Inc. â 444 Castro St â Mountain View,
> CA â
> -
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at http://vger.kernel.org/majordomo-info.html

--
Evgeniy Polyakov
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/