bornfree
bornfree

Reputation: 2528

Understanding hlist_bl_for_each_entry_rcu macro in Linux Kernel

While browsing Linux kernel source, I found hlist_bl_for_each_entry_rcu macro.Below is its definition

for (pos = hlist_bl_first_rcu(head);                            \
                pos &&                                                  \
                ({ tpos = hlist_bl_entry(pos, typeof(*tpos), member); 1; }); \
                pos = rcu_dereference_raw(pos->next))

This macro is used in __d_lookup() to get the dentry. What I do not understand is the line

({ tpos = hlist_bl_entry(pos, typeof(*tpos), member); 1; });

It gets the tpos. What is the use of 1 here ? How to understand this condition in the for loop ?

Upvotes: 1

Views: 204

Answers (1)

a3f
a3f

Reputation: 8657

If you were writing it macroless, it would probably look like this:

for (pos = hlist_bl_first_rcu(head); pos; pos = rcu_dereference_raw(pos->next)) {
    tpos = hlist_bl_entry(pos, typeof(*tpos), member);

    /* do something with pos and tpos */

}

For the macro, you would want to move tpos = hlist_bl_entry(pos, typeof(*tpos), member); into the for (...), so the user only has to supply the for block. In the macroless version, you want tpos' value set every time pos is non-NULL, thus you add it in the loop condition after a pos &&:

pos && (tpos = hlist_bl_entry(pos, typeof(*tpos), member))

but now tops non-nullness becomes a loop condition, so you tell C to ignore the return value:

pos && ((tpos = hlist_bl_entry(pos, typeof(*tpos), member)), 1)

but kernel code is GNU C anyway, so you may use statement expressions instead:

pos && ({ tpos = hlist_bl_entry(pos, typeof(*tpos), member); 1; })

Upvotes: 2

Related Questions