Usage of unlikely in RCU code

Dave Hylands dhylands at gmail.com
Mon Aug 1 19:30:11 EDT 2011


Hi Julie,

On Mon, Aug 1, 2011 at 2:28 PM, Julie Sullivan <kernelmail.jms at gmail.com> 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



More information about the Kernelnewbies mailing list