Thread (8 messages) 8 messages, 5 authors, 2011-08-03

Usage of unlikely in RCU code

From: Dave Hylands <hidden>
Date: 2011-08-01 23:30:11

Hi Julie,

On Mon, Aug 1, 2011 at 2:28 PM, Julie Sullivan [off-list ref] wrote:
Hi list,

I'm looking at RCU at the moment and (on reading a recent article by
Paul McKenney on LWN) I've spotted something I'm a bit confused by in
this code, a function which is defined in kernel/rcutree_plugin.h:

void __rcu_read_unlock(void)
{
? ? ? ?struct task_struct *t = current;

? ? ? ?barrier(); ?/* needed if we ever invoke rcu_read_unlock in rcutree.c */
? ? ? ?--t->rcu_read_lock_nesting;
? ? ? ?barrier(); ?/* decrement before load of ->rcu_read_unlock_special */
? ? ? ?if (t->rcu_read_lock_nesting == 0 &&
? ? ? ? ? ?unlikely(ACCESS_ONCE(t->rcu_read_unlock_special)))
? ? ? ? ? ? ? ?rcu_read_unlock_special(t);
#ifdef CONFIG_PROVE_LOCKING
? ? ? ?WARN_ON_ONCE(ACCESS_ONCE(t->rcu_read_lock_nesting) < 0);
#endif /* #ifdef CONFIG_PROVE_LOCKING */
}

Specifically, the conditional

?if (t->rcu_read_lock_nesting == 0 &&
? ? ? ? ? ?unlikely(ACCESS_ONCE(t->rcu_read_unlock_special)))
? ? ? ? ? ? ? ?rcu_read_unlock_special(t);

I've googled for 'likely/unlikely' and i've seen

?if (unlikely(...

before in kernel code, and I might understand if the logical operator
here were || not &&, but why is the 'unlikely' attribute only applied
to the second operand here? Because both must be evaluated, with
left-to-right associativity, and then both must be true for the branch
to be taken, right?
Yes - both must be true for the branch to be taken.

However, if the first portion t->rcu_read_lock_nesting == 0 fails,
then the unlikely portion won't be evaluated.
C uses short-circuit evaluation for boolean expressions, whereas some
other languages like Pascal would evaluate both sides of the && before
determining the outcome.
If it's necessary for branch
prediction/optimization purposes shouldn't it be applied to both or
the first one?
Maybe its neither likely nor unlikely?
Or might the operands also be re-ordered by the
compiler or processor so that the second is evaluated before the
first?
C absolutely guarantees that the second will NEVER be evaluated before
the first. Otherwise, things like this:

if ( ptr && ptr->field )

could fail if ptr was NULL.

-- 
Dave Hylands
Shuswap, BC, Canada
http://www.davehylands.com
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help