这段代码的反汇编如下所示
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,但是代码中又不需要这个条件成立时,可以自己体会下.