⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpufreq_ondemand.c

📁 xen虚拟机源代码安装包
💻 C
字号:
/* *  xen/arch/x86/acpi/cpufreq/cpufreq_ondemand.c * *  Copyright (C)  2001 Russell King *            (C)  2003 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>. *                      Jun Nakajima <jun.nakajima@intel.com> *             Feb 2008 Liu Jinsong <jinsong.liu@intel.com> *             Porting cpufreq_ondemand.c from Liunx 2.6.23 to Xen hypervisor  * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */#include <xen/types.h>#include <xen/percpu.h>#include <xen/cpumask.h>#include <xen/types.h>#include <xen/sched.h>#include <xen/timer.h>#include <asm/config.h>#include <acpi/cpufreq/cpufreq.h>#define DEF_FREQUENCY_UP_THRESHOLD              (80)#define MIN_DBS_INTERVAL                        (MICROSECS(100))#define MIN_SAMPLING_MILLISECS                  (20)#define MIN_STAT_SAMPLING_RATE                   \    (MIN_SAMPLING_MILLISECS * MILLISECS(1))#define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER    (1000)#define TRANSITION_LATENCY_LIMIT                (10 * 1000 )static uint64_t def_sampling_rate;/* Sampling types */enum {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE};static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info);static unsigned int dbs_enable;    /* number of CPUs using this policy */static struct dbs_tuners {    uint64_t     sampling_rate;    unsigned int up_threshold;    unsigned int ignore_nice;    unsigned int powersave_bias;} dbs_tuners_ins = {    .up_threshold = DEF_FREQUENCY_UP_THRESHOLD,    .ignore_nice = 0,    .powersave_bias = 0,};static struct timer dbs_timer[NR_CPUS];uint64_t get_cpu_idle_time(unsigned int cpu){    uint64_t idle_ns;    struct vcpu *v;    if ((v = idle_vcpu[cpu]) == NULL)        return 0;    idle_ns = v->runstate.time[RUNSTATE_running];    if (v->is_running)        idle_ns += NOW() - v->runstate.state_entry_time;    return idle_ns;}static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info){    unsigned int load = 0;    uint64_t cur_ns, idle_ns, total_ns;    struct cpufreq_policy *policy;    unsigned int j;    if (!this_dbs_info->enable)        return;    policy = this_dbs_info->cur_policy;    if (unlikely(policy->resume)) {        __cpufreq_driver_target(policy, policy->max,CPUFREQ_RELATION_H);        return;    }    cur_ns = NOW();    total_ns = cur_ns - this_dbs_info->prev_cpu_wall;    this_dbs_info->prev_cpu_wall = NOW();    if (total_ns < MIN_DBS_INTERVAL)        return;    /* Get Idle Time */    idle_ns = UINT_MAX;    for_each_cpu_mask(j, policy->cpus) {        uint64_t total_idle_ns;        unsigned int tmp_idle_ns;        struct cpu_dbs_info_s *j_dbs_info;        j_dbs_info = &per_cpu(cpu_dbs_info, j);        total_idle_ns = get_cpu_idle_time(j);        tmp_idle_ns = total_idle_ns - j_dbs_info->prev_cpu_idle;        j_dbs_info->prev_cpu_idle = total_idle_ns;        if (tmp_idle_ns < idle_ns)            idle_ns = tmp_idle_ns;    }    if (likely(total_ns > idle_ns))        load = (100 * (total_ns - idle_ns)) / total_ns;    /* Check for frequency increase */    if (load > dbs_tuners_ins.up_threshold) {        /* if we are already at full speed then break out early */        if (policy->cur == policy->max)            return;        __cpufreq_driver_target(policy, policy->max,CPUFREQ_RELATION_H);        return;    }    /* Check for frequency decrease */    /* if we cannot reduce the frequency anymore, break out early */    if (policy->cur == policy->min)        return;    /*     * The optimal frequency is the frequency that is the lowest that     * can support the current CPU usage without triggering the up     * policy. To be safe, we focus 10 points under the threshold.     */    if (load < (dbs_tuners_ins.up_threshold - 10)) {        unsigned int freq_next, freq_cur;        freq_cur = __cpufreq_driver_getavg(policy);        if (!freq_cur)            freq_cur = policy->cur;        freq_next = (freq_cur * load) / (dbs_tuners_ins.up_threshold - 10);        __cpufreq_driver_target(policy, freq_next, CPUFREQ_RELATION_L);    }}static void do_dbs_timer(void *dbs){    struct cpu_dbs_info_s *dbs_info = (struct cpu_dbs_info_s *)dbs;    if (!dbs_info->enable)        return;    dbs_check_cpu(dbs_info);    set_timer(&dbs_timer[dbs_info->cpu], NOW()+dbs_tuners_ins.sampling_rate);}static void dbs_timer_init(struct cpu_dbs_info_s *dbs_info){    dbs_info->enable = 1;    init_timer(&dbs_timer[dbs_info->cpu], do_dbs_timer,         (void *)dbs_info, dbs_info->cpu);    set_timer(&dbs_timer[dbs_info->cpu], NOW()+dbs_tuners_ins.sampling_rate);}static void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info){    dbs_info->enable = 0;    stop_timer(&dbs_timer[dbs_info->cpu]);}int cpufreq_governor_dbs(struct cpufreq_policy *policy, unsigned int event){    unsigned int cpu = policy->cpu;    struct cpu_dbs_info_s *this_dbs_info;    unsigned int j;    this_dbs_info = &per_cpu(cpu_dbs_info, cpu);    switch (event) {    case CPUFREQ_GOV_START:        if ((!cpu_online(cpu)) || (!policy->cur))            return -EINVAL;        if (policy->cpuinfo.transition_latency >            (TRANSITION_LATENCY_LIMIT * 1000)) {            printk(KERN_WARNING "ondemand governor failed to load "                "due to too long transition latency\n");            return -EINVAL;        }        if (this_dbs_info->enable)            /* Already enabled */            break;        dbs_enable++;        for_each_cpu_mask(j, policy->cpus) {            struct cpu_dbs_info_s *j_dbs_info;            j_dbs_info = &per_cpu(cpu_dbs_info, j);            j_dbs_info->cur_policy = policy;            j_dbs_info->prev_cpu_idle = get_cpu_idle_time(j);            j_dbs_info->prev_cpu_wall = NOW();        }        this_dbs_info->cpu = cpu;        /*         * Start the timerschedule work, when this governor         * is used for first time         */        if (dbs_enable == 1) {            def_sampling_rate = policy->cpuinfo.transition_latency *                DEF_SAMPLING_RATE_LATENCY_MULTIPLIER;            if (def_sampling_rate < MIN_STAT_SAMPLING_RATE)                def_sampling_rate = MIN_STAT_SAMPLING_RATE;            dbs_tuners_ins.sampling_rate = def_sampling_rate;        }        dbs_timer_init(this_dbs_info);        break;    case CPUFREQ_GOV_STOP:        dbs_timer_exit(this_dbs_info);        dbs_enable--;        break;    case CPUFREQ_GOV_LIMITS:        if (policy->max < this_dbs_info->cur_policy->cur)            __cpufreq_driver_target(this_dbs_info->cur_policy,                policy->max, CPUFREQ_RELATION_H);        else if (policy->min > this_dbs_info->cur_policy->cur)            __cpufreq_driver_target(this_dbs_info->cur_policy,                policy->min, CPUFREQ_RELATION_L);        break;    }    return 0;} 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -