DECLARE_STATIC_KEY_FALSE--static key学习记录

最近在看kernel5.4.26的调度器代码,看到下面的:

static int  
select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_flags)  
{  
        struct sched_domain *tmp, *sd = NULL;  
        int cpu = smp_processor_id();  
        int new_cpu = prev_cpu;  
        int want_affine = 0;  
        int sync = (wake_flags & WF_SYNC) && !(current->flags & PF_EXITING);  
  
        if (sd_flag & SD_BALANCE_WAKE) {  
                record_wakee(p);  
  
                if (sched_energy_enabled()) {  //这个数值在哪里设置的呢?
                        new_cpu = find_energy_efficient_cpu(p, prev_cpu, sync);  
                        if (new_cpu >= 0)  
                                return new_cpu;  
                        new_cpu = prev_cpu;  
                }  
  
                want_affine = !wake_wide(p) && cpumask_test_cpu(cpu, p->cpus_ptr);  
        }  

如下所示:

#if defined(CONFIG_ENERGY_MODEL) && defined(CONFIG_CPU_FREQ_GOV_SCHEDUTIL)  
  
#define perf_domain_span(pd) (to_cpumask(((pd)->em_pd->cpus)))  
  
DECLARE_STATIC_KEY_FALSE(sched_energy_present);  
  
static inline bool sched_energy_enabled(void)  
{  
        return static_branch_unlikely(&sched_energy_present);  
}  
  
#else /* ! (CONFIG_ENERGY_MODEL && CONFIG_CPU_FREQ_GOV_SCHEDUTIL) */  
  
#define perf_domain_span(pd) NULL  
static inline bool sched_energy_enabled(void) { return false; }  
  
#endif /* CONFIG_ENERGY_MODEL && CONFIG_CPU_FREQ_GOV_SCHEDUTIL */  

  1. 如果调度器是使用EAS并且cpufreq governor使用的是scheduitl,则返回sched_energy_present数值
  2. 否则直接返回false.

那么sched_energy_present数值怎么被设置的呢?

#if defined(CONFIG_ENERGY_MODEL) && defined(CONFIG_CPU_FREQ_GOV_SCHEDUTIL)  
DEFINE_STATIC_KEY_FALSE(sched_energy_present);  

也需要满足两个定义才会声明此变量

#define DEFINE_STATIC_KEY_FALSE(name)   \                                                                                                                                 
    struct static_key_false name = STATIC_KEY_FALSE_INIT  
  
#define STATIC_KEY_FALSE_INIT (struct static_key_false){ .key = STATIC_KEY_INIT_FALSE, }  
  
#define STATIC_KEY_INIT_FALSE                   \  
    { .enabled = { 0 },                 \  
    ┊ { .entries = (void *)JUMP_TYPE_FALSE } }  
  
#define JUMP_TYPE_FALSE     0UL                                                                                                                                           

可以看到DEFINE_STATIC_KEY_FALSE是设置sched_energy_present为false的,即enable=0.

那么这个数值在哪里设置为enable为非0数值的呢?

/* 
1. sched domain构建,即topology的构建,在系统初始化的时候. 
2. 有cpu插拔动作的时候都会调用这个函数,重构sched domain. 
*/  
void partition_sched_domains_locked(int ndoms_new, cpumask_var_t doms_new[],struct sched_domain_attr *dattr_new)  
{  
.................  
#if defined(CONFIG_ENERGY_MODEL) && defined(CONFIG_CPU_FREQ_GOV_SCHEDUTIL)  
    /* Build perf. domains: */  
    for (i = 0; i < ndoms_new; i++) {  
        for (j = 0; j < n && !sched_energy_update; j++) {  
            if (cpumask_equal(doms_new[i], doms_cur[j]) &&cpu_rq(cpumask_first(doms_cur[j]))->rd->pd) {  
                has_eas = true;  
                goto match3;  
            }  
        }  
        /* No match - add perf. domains for a new rd */  
        has_eas |= build_perf_domains(doms_new[i]); //has_eas = true,否则energy mode没有建立,EAS不能使用  
match3:   
        ;  
    }     
    sched_energy_set(has_eas);  
#endif    
................  
}  
  
  
static void sched_energy_set(bool has_eas)     
{                                              
    if (!has_eas && static_branch_unlikely(&sched_energy_present)) {                                                                                                      
        if (sched_debug())                     
            pr_info("%s: stopping EAS\n", __func__);  
        static_branch_disable_cpuslocked(&sched_energy_present);  
    } else if (has_eas && !static_branch_unlikely(&sched_energy_present)) {  
        if (sched_debug())                     
            pr_info("%s: starting EAS\n", __func__);  
        static_branch_enable_cpuslocked(&sched_energy_present);  
    }                                          
}     

我们看下static_branch_enable_cpuslocked(&sched_energy_present)这么定义的?

#define static_branch_enable_cpuslocked(x)  static_key_enable_cpuslocked(&(x)->key)                                                                                       
  
void static_key_enable_cpuslocked(struct static_key *key)                                                                                                                 
{            
    STATIC_KEY_CHECK_USE(key);  
    lockdep_assert_cpus_held();                      
             
    if (atomic_read(&key->enabled) > 0) {            
        WARN_ON_ONCE(atomic_read(&key->enabled) != 1);  
        return;  
    }        
             
    jump_label_lock();  
    if (atomic_read(&key->enabled) == 0) {           
        atomic_set(&key->enabled, -1);               
        jump_label_update(key);  
        /*  
        ┊* See static_key_slow_inc().               
        ┊*/  
        atomic_set_release(&key->enabled, 1);  
    }        
    jump_label_unlock();  
}            
EXPORT_SYMBOL_GPL(static_key_enable_cpuslocked);     

可以看到sched_energy_present被设置成非0数值了. 这样sched_energy_enabled()也就返回true了,可以走EAS流程选择target_cpu.

为何使用static key呢?
查看文档说明如下:

Static keys allows the inclusion of seldom used features in
performance-sensitive fast-path kernel code, via a GCC feature and a code
patching technique. A quick example::

	DEFINE_STATIC_KEY_FALSE(key);

	...

        if (static_branch_unlikely(&key))
                do unlikely code
        else
                do likely code

	...
	static_branch_enable(&key);
	...
	static_branch_disable(&key);
	...

The static_branch_unlikely() branch will be generated into the code with as little
impact to the likely code path as possible.

其实就是对经常使用的代码进行优化,并且这个数值很少被改变.

参考文献:
static-key简介

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值