Understanding Linux kernel likely and unlikely macros

Linux kernel defines likely and unlikely macros in kernel source code include/linux/compiler.h as

# define likely(x)      __builtin_expect(!!(x), 1)
# define unlikely(x)    __builtin_expect(!!(x), 0)

As per GCC documentation, __builtin_expect has been described as,

[bash] Built-in Function: long __builtin_expect (long exp, long c) You may use __builtin_expect to provide the compiler with branch prediction information. [/bash]
if (__builtin_expect (x, 0))
  foo ();

indicates that we do not expect to call foo,
since we expect x to be zero. 

Since you are limited to integral expressions for exp,
you should use constructions such as

if (__builtin_expect (ptr != NULL, 1))
  foo (*ptr);

when testing pointer or floating-point values.

likely macro is used something like below in Linux kernel,

[bash] /** * kpp_request_alloc() – allocates kpp request * * @tfm: KPP tfm handle allocated with crypto_alloc_kpp() * @gfp: allocation flags * * Return: allocated handle in case of success or NULL in case of an error. */ static inline struct kpp_request *kpp_request_alloc(struct crypto_kpp *tfm, gfp_t gfp) { struct kpp_request *req; req = kmalloc(sizeof(*req) + crypto_kpp_reqsize(tfm), gfp); if (likely(req)) kpp_request_set_tfm(req, tfm); return req; } [/bash]

Whereas, unlikely macro is used as,

[bash] /** * xdr_stream_encode_u32 – Encode a 32-bit integer * @xdr: pointer to xdr_stream * @n: integer to encode * * Return values: * On success, returns length in bytes of XDR buffer consumed * %-EMSGSIZE on XDR buffer overflow */ static inline ssize_t xdr_stream_encode_u32(struct xdr_stream *xdr, __u32 n) { const size_t len = sizeof(n); __be32 *p = xdr_reserve_space(xdr, len); if (unlikely(!p)) return -EMSGSIZE; *p = cpu_to_be32(n); return len; } [/bash]

When we tried to emulate same likely & unlikely in application to understand how it works, you can check below program with comments to understand macros meanings,

 $ vim understanding_likely_unlikely.c 
[bash] #include <stdio.h> # define likely(x) __builtin_expect(!!(x), 1) # define unlikely(x) __builtin_expect(!!(x), 0) int main(int argc, char **argv) { int x = 1; if (__builtin_expect(x, 0)) { printf("Value of x was expected to be 0 but x is =%d\n", x); //this shouldn’t get called if x is 0 } if(unlikely(x)) { printf("Value of x was expected to be 0 but x is =%d\n", x); //this shouldn’t get called if x is 0 } if (__builtin_expect(x, 1)) { printf("Value of x is expected to be 1\n"); //this should get called if x is 1 } if(likely(x)) { printf("Value of x is expected to be 1\n"); //this should get called if x is 1 } return 0; } [/bash]

Leave a Comment