Linux Kernel Architecture

(Jacob Rumans) #1
Mauerer app03.tex V1 - 09/04/2008 6:11pm Page 1199

Appendix C: Notes on C


❑ __builtin_expect(long exp, long c)helps the compiler optimize branch predictions.exp
specifies the result value of an expression that is computed, whereascreturns the expected
result — 0 or 1. As an example, take a look at the followingifquery:


if (expression) {
/* Yes */
}
else {
/* No */
}

If this is to be optimized, and it is expected that the condition will return the value 1 in most
cases, the__builtin_expectfunction can be used as follows:

if (__builtin_expect(expression, 1)) {
/* Yes */
}
else {
/* No */
}

The compiler influences the branch predictionsof the processor in such a way that, by prefer-
ence, the first branch is computed in advance.
The kernel defines the following two macros to identify likely and unlikely branches in the code:

<compiler.h>
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)

The double negation!!is used for two reasons:

❑ It enables the macros to be used with pointers that are implicitly converted into a truth
value.
❑ Truth values greater than zero (explicitly allowed in C) are standardized to 1 as expected
by__builtin_expect.

The macros are employed at many points in the kernel; for instance, in the implementation of the
slab allocator as follows:
mm/slab.c
if (likely(ac->avail < ac->limit)) {
STATS_INC_FREEHIT(cachep);
ac_entry(ac)[ac->avail++] = objp;
return;
} else {
STATS_INC_FREEMISS(cachep);
cache_flusharray(cachep, ac);
ac_entry(ac)[ac->avail++] = objp;
}

The example shows that__builtin_expectcan be used not only for simple values, but also for
conditions that must first be evaluated.
Free download pdf