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,
Built-in Function: long __builtin_expect (long exp, long c)
You may use __builtin_expect to provide the compiler with branch prediction information.
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,
/**
* 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;
}
Whereas, unlikely macro is used as,
/**
* 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;
}
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
#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;
}