jump label

这段代码的反汇编如下所示
static inline bool test_idle_cores(int cpu, bool def)
{
        struct sched_domain_shared *sds;

        if (static_branch_unlikely(&sched_smt_present)) {
                sds = rcu_dereference(per_cpu(sd_llc_shared, cpu));
                if (sds)
                        return READ_ONCE(sds->has_idle_cores);
        }

        return def;
}


0000000000000884 <test_idle_cores>:
{
     884:       12001c21        and     w1, w1, #0xff
#define JUMP_LABEL_NOP_SIZE             AARCH64_INSN_SIZE

static __always_inline bool arch_static_branch(struct static_key *key,
                                               bool branch)
{
        asm_volatile_goto(
     888:       d503201f        nop
}
     88c:       2a0103e0        mov     w0, w1
     890:       d65f03c0        ret
                sds = rcu_dereference(per_cpu(sd_llc_shared, cpu));
     894:       90000003        adrp    x3, 0 <__per_cpu_offset>
     898:       91000063        add     x3, x3, #0x0
     89c:       90000002        adrp    x2, 0 <sd_llc_shared>
     8a0:       91000042        add     x2, x2, #0x0
     8a4:       f860d860        ldr     x0, [x3, w0, sxtw #3]
     8a8:       f8606840        ldr     x0, [x2, x0]
                if (sds)
     8ac:       b4ffff00        cbz     x0, 88c <test_idle_cores+0x8>
                        return READ_ONCE(sds->has_idle_cores);
     8b0:       b9400800        ldr     w0, [x0, #8]
     8b4:       7100001f        cmp     w0, #0x0
     8b8:       1a9f07e1        cset    w1, ne  // ne = any
     8bc:       17fffff4        b       88c <test_idle_cores+0x8>
	 
为什么会是这样呢,我们看看static_branch_likely的实现	 
如果使能jump_label的话是先如下,如果没有的话就等同普通的unlikely	 
#define static_branch_unlikely(x)						\
({										\
	bool branch;								\
	if (__builtin_types_compatible_p(typeof(*x), struct static_key_true))	\
		branch = arch_static_branch_jump(&(x)->key, false);		\
	else if (__builtin_types_compatible_p(typeof(*x), struct static_key_false)) \
		branch = arch_static_branch(&(x)->key, false);			\
	else									\
		branch = ____wrong_branch_error();				\
	unlikely_notrace(branch);							\
})
	 
由于本例中的sched_smt_present 默认为false,所以我们看看	 arch_static_branch的实现
	 
	 
static __always_inline bool arch_static_branch(struct static_key *key,
					       bool branch)
{
	asm_volatile_goto(
		"1:	nop					\n\t"
		 "	.pushsection	__jump_table, \"aw\"	\n\t"
		 "	.align		3			\n\t"
		 "	.long		1b - ., %l[l_yes] - .	\n\t"
		 "	.quad		%c0 - .			\n\t"
		 "	.popsection				\n\t"
		 :  :  "i"(&((char *)key)[branch]) :  : l_yes);

	return false;
l_yes:
	return true;
}

可以和上面的汇编对比下。这里也可以看出static_branch_unlikely 是一个宏,会被展开,最后就是一行unlikely_notrace
可见static_branch_unlikely 是包含unlikely_notrace.
简单理解就是
仔细看代码就会发现 static_branch_likely 不等于 !static_branch_unlikely 同样!static_branch_likely 也不等于static_branch_unlikely.
可以通过反汇编查询上面两种情况的区别. 性能上也是有差异的,取决于key的初始值是true还是false.
那什么时候用!static_branch_unlikely这个组合呢?
那就是当key是false时,static_branch_unlikely 对应的就是nop,但是代码中又不需要这个条件成立时,可以自己体会下.

猜你喜欢

转载自blog.csdn.net/tiantao2012/article/details/115437930