2008-03-12 08:12:40

by Oleg Nesterov

[permalink] [raw]
Subject: Q: (stupid) can't we "fix" hlist_for_each_entry() ?

hlist_for_each_entry/hlist_for_each_entry_rcu doesn't actually need 4
arguments, it could be

#define hlist_for_each_entry_rcu(pos, head, member) \
for (pos = hlist_entry((head)->first, typeof(*(pos)), member); \
rcu_dereference(pos) != hlist_entry(NULL, typeof(*(pos)), member) && \
({ prefetch((pos)->member.next); 1; }); \
(pos) = hlist_entry((pos)->member.next, typeof(*(pos)), member))

Or,

#define hlist_for_each_entry_rcu(pos, head, member) \
for (pos = (void*)(head)->first; \
rcu_dereference(pos) && ({ prefetch(((hlist_node*)pos)->next); 1; }) && \
({ (pos) = hlist_entry((void*)(pos), typeof(*(pos)), member)); 1; }); \
(pos) = (void*)(pos)->member.next)

Q: is it worth "fixing" ?

If yes, what is the "right" way to do this? These macros are spread all over
the kernel...

Oleg.


2008-03-12 09:49:57

by Peter Zijlstra

[permalink] [raw]
Subject: Re: Q: (stupid) can't we "fix" hlist_for_each_entry() ?

On Wed, 2008-03-12 at 11:12 +0300, Oleg Nesterov wrote:
> hlist_for_each_entry/hlist_for_each_entry_rcu doesn't actually need 4
> arguments, it could be
>
> #define hlist_for_each_entry_rcu(pos, head, member) \
> for (pos = hlist_entry((head)->first, typeof(*(pos)), member); \
> rcu_dereference(pos) != hlist_entry(NULL, typeof(*(pos)), member) && \
> ({ prefetch((pos)->member.next); 1; }); \
> (pos) = hlist_entry((pos)->member.next, typeof(*(pos)), member))
>
> Or,
>
> #define hlist_for_each_entry_rcu(pos, head, member) \
> for (pos = (void*)(head)->first; \
> rcu_dereference(pos) && ({ prefetch(((hlist_node*)pos)->next); 1; }) && \
> ({ (pos) = hlist_entry((void*)(pos), typeof(*(pos)), member)); 1; }); \
> (pos) = (void*)(pos)->member.next)
>
> Q: is it worth "fixing" ?

I'm in favour.

> If yes, what is the "right" way to do this? These macros are spread all over
> the kernel...

The usual way would be to prepare a git tree for Linus to pull right
after -rc1 I think was the best point, and at the same time supply
Andrew with a bunch of patches fixing up the various users in his tree.

2008-03-12 12:54:20

by Paul E. McKenney

[permalink] [raw]
Subject: Re: Q: (stupid) can't we "fix" hlist_for_each_entry() ?

On Wed, Mar 12, 2008 at 11:12:01AM +0300, Oleg Nesterov wrote:
> hlist_for_each_entry/hlist_for_each_entry_rcu doesn't actually need 4
> arguments, it could be
>
> #define hlist_for_each_entry_rcu(pos, head, member) \
> for (pos = hlist_entry((head)->first, typeof(*(pos)), member); \
> rcu_dereference(pos) != hlist_entry(NULL, typeof(*(pos)), member) && \
> ({ prefetch((pos)->member.next); 1; }); \
> (pos) = hlist_entry((pos)->member.next, typeof(*(pos)), member))
>
> Or,
>
> #define hlist_for_each_entry_rcu(pos, head, member) \
> for (pos = (void*)(head)->first; \
> rcu_dereference(pos) && ({ prefetch(((hlist_node*)pos)->next); 1; }) && \
> ({ (pos) = hlist_entry((void*)(pos), typeof(*(pos)), member)); 1; }); \
> (pos) = (void*)(pos)->member.next)
>
> Q: is it worth "fixing" ?

I have already come out in favor: http://lwn.net/Articles/262464/
answer to Quick Quiz 3. ;-)

The first option above looks more straightforward to me.

> If yes, what is the "right" way to do this? These macros are spread all over
> the kernel...

Peter's approach looked reasonable to me.

Thanx, Paul

2008-03-12 17:28:35

by Andrew Morton

[permalink] [raw]
Subject: Re: Q: (stupid) can't we "fix" hlist_for_each_entry() ?

On Wed, 12 Mar 2008 10:48:50 +0100 Peter Zijlstra <[email protected]> wrote:

> On Wed, 2008-03-12 at 11:12 +0300, Oleg Nesterov wrote:
> > hlist_for_each_entry/hlist_for_each_entry_rcu doesn't actually need 4
> > arguments, it could be
> >
> > #define hlist_for_each_entry_rcu(pos, head, member) \
> > for (pos = hlist_entry((head)->first, typeof(*(pos)), member); \
> > rcu_dereference(pos) != hlist_entry(NULL, typeof(*(pos)), member) && \
> > ({ prefetch((pos)->member.next); 1; }); \
> > (pos) = hlist_entry((pos)->member.next, typeof(*(pos)), member))
> >
> > Or,
> >
> > #define hlist_for_each_entry_rcu(pos, head, member) \
> > for (pos = (void*)(head)->first; \
> > rcu_dereference(pos) && ({ prefetch(((hlist_node*)pos)->next); 1; }) && \
> > ({ (pos) = hlist_entry((void*)(pos), typeof(*(pos)), member)); 1; }); \
> > (pos) = (void*)(pos)->member.next)
> >
> > Q: is it worth "fixing" ?
>
> I'm in favour.
>
> > If yes, what is the "right" way to do this? These macros are spread all over
> > the kernel...
>
> The usual way would be to prepare a git tree for Linus to pull right
> after -rc1 I think was the best point, and at the same time supply
> Andrew with a bunch of patches fixing up the various users in his tree.

That, or create new functions with new names, migrate over to them
piecemeal and later remove the old functions.

It's a bit of a problem that there is no alternative name.

eh, send over the jumbopatch after 2.6.25 is released - I'll take care of it.