对照ftrace跟踪cpufreq 的结果,分析cpufreq工作过程

来源:互联网 发布:金融大数据案例 编辑:程序博客网 时间:2024/05/14 22:39

AUTHOR: Joseph Yang (杨红刚) <ganggexiongqi@gmail.com>
CONTENT: 对照ftrace跟踪cpufreq 的结果,分析cpufreq工作过程
NOTE: linux-3.0
LAST MODIFIED:09-19-2011
-----------------------------------------------------------------------------------------------------------
Distributed and Embedded System Lab (分布式嵌入式系统实验室,兰州大学)


//说明: 有些函数或宏无法跟踪到,

结构:

1. 操作步骤

2. 跟踪结果

3.跟踪结果分析

4. func_list_latest

=========================================================================

1 ------------------ 操作步骤

Snail:/home/snail/Desktop# mount -t debugfs nodev /sys/kernel/debug
Snail:/home/snail/Desktop# cd /sys/kernel/debug/tracing/
Snail:/sys/kernel/debug/tracing# cat /tmp/func_list_latest > set_ftrace_filter  
Snail:/sys/kernel/debug/tracing# echo function_graph > current_tracer
Snail:/sys/kernel/debug/tracing# sysctl kernel.ftrace_enabled=1
kernel.ftrace_enabled = 1
Snail:/sys/kernel/debug/tracing# echo 1 > tracing_enabled
Snail:/sys/kernel/debug/tracing# cat trace_pipe > /tmp/result&
[1] 4618

//do sth

Snail:/sys/devices/system/cpu/cpu0/cpufreq# cat scaling_governor
performance
Snail:/sys/devices/system/cpu/cpu0/cpufreq# cat affected_cpus
0
Snail:/sys/devices/system/cpu/cpu0/cpufreq# cat related_cpus
0
Snail:/sys/devices/system/cpu/cpu0/cpufreq# cat scaling_available_governors
conservative ondemand userspace powersave performance
Snail:/sys/devices/system/cpu/cpu0/cpufreq# echo userspace > scaling_governor
Snail:/sys/devices/system/cpu/cpu0/cpufreq# cat scaling_available_frequencies
350000 700000 1050000 1400000 1750000 2100000 2450000 2800000
Snail:/sys/devices/system/cpu/cpu0/cpufreq# echo 2450000 > scaling_setspeed
Snail:/sys/devices/system/cpu/cpu0/cpufreq# cat stats/total_trans
1


//end trace
Snail:/sys/kernel/debug/tracing# echo 0 > tracing_enabled
Snail:/sys/kernel/debug/tracing#
[1]+  Done                    cat trace_pipe > /tmp/result
Snail:/sys/kernel/debug/tracing# vim /tmp/result
Snail:/sys/kernel/debug/tracing# cat /tmp/result > /home/snail/Desktop/cpufreq-trace/result_latest



2 -------------------跟踪结果


  //cat scaling_governor
 0)               |  show() {
 0)   2.492 us    |    cpufreq_cpu_get();
 0)   3.528 us    |    show_scaling_governor();
 0)   0.170 us    |    unlock_policy_rwsem_read();
 0)   0.873 us    |    cpufreq_cpu_put();
 0) + 13.733 us   |  }
 ------------------------------------------
 0)    cat-4950    =>    cat-4975   // cat affected_cpus
 ------------------------------------------

 0)               |  show() {
 0)   2.742 us    |    cpufreq_cpu_get();
 0)               |    show_affected_cpus() {
 0)   4.386 us    |      show_cpus();
 0)   5.438 us    |    }
 0)   0.169 us    |    unlock_policy_rwsem_read();
 0)   0.769 us    |    cpufreq_cpu_put();
 0) + 15.400 us   |  }
 ------------------------------------------
 0)    cat-4975    =>    cat-4985   // cat related_cpus
 ------------------------------------------

 0)               |  show() {
 0)   2.571 us    |    cpufreq_cpu_get();
 0)               |    show_related_cpus() {
 0)   3.999 us    |      show_cpus();
 0)   5.074 us    |    }
 0)   0.167 us    |    unlock_policy_rwsem_read();
 0)   0.827 us    |    cpufreq_cpu_put();
 0) + 14.607 us   |  }
 ------------------------------------------
 0)    cat-4985    =>    cat-5013    //cat scaling_available_governors
 ------------------------------------------

 0)               |  show() {
 0)   2.667 us    |    cpufreq_cpu_get();
 0)   5.805 us    |    show_scaling_available_governors();
 0)   0.161 us    |    unlock_policy_rwsem_read();
 0)   0.850 us    |    cpufreq_cpu_put();
 0) + 15.648 us   |  }
 ------------------------------------------
 0)    cat-5013    =>   bash-4850   //echo userspace > scaling_governor
 ------------------------------------------

 0)               |  store() {
 0)   2.506 us    |    cpufreq_cpu_get();
 0)               |    store_scaling_governor() {
 0)               |      cpufreq_get_policy() {
 0)   0.223 us    |        cpufreq_cpu_get();
 0)   0.832 us    |        cpufreq_cpu_put();
 0)   3.395 us    |      }
 0)   1.398 us    |      __find_governor();
 0)               |      __cpufreq_set_policy() {
 0)   0.469 us    |        __cpufreq_governor();
 0)               |        __cpufreq_governor() {
 0)   1.050 us    |          cpufreq_register_notifier();
 0)   4.993 us    |        }
 0)               |        __cpufreq_governor() {
 0)   0.777 us    |          __cpufreq_driver_target();
 0)   3.198 us    |        }
 0) + 16.492 us   |      }
 0) + 26.564 us   |    }
 0)   0.284 us    |    unlock_policy_rwsem_write();
 0)   0.237 us    |    cpufreq_cpu_put();
 0) + 35.884 us   |  }
 ------------------------------------------
 0)   bash-4850    =>    cat-5092   //cat scaling_available_frequencies
 ------------------------------------------

 0)               |  show() {
 0)   2.736 us    |    cpufreq_cpu_get();
 0)   0.160 us    |    unlock_policy_rwsem_read();
 0)   1.063 us    |    cpufreq_cpu_put();
 0) + 16.599 us   |  }
 ------------------------------------------
 0)    cat-5092    =>   bash-4850   //echo 2450000 > scaling_setspeed
 ------------------------------------------

 0)               |  store() {
 0)   2.583 us    |    cpufreq_cpu_get();
 0)               |    store_scaling_setspeed() {
 0)               |      __cpufreq_driver_target() {
 0)               |        cpufreq_notify_transition() {
 0)   0.330 us    |          adjust_jiffies();
 0)   7.025 us    |        }
 0)               |        cpufreq_notify_transition() {
 0)   0.170 us    |          adjust_jiffies();
 0)   5.439 us    |        }
 0) + 19.767 us   |      }
 0) + 24.867 us   |    }
 0)   0.300 us    |    unlock_policy_rwsem_write();
 0)   0.979 us    |    cpufreq_cpu_put();
 0) + 35.445 us   |  }
 ------------------------------------------
 0)   bash-4850    =>    cat-5153   //cat stats/total_trans
 ------------------------------------------

 0)               |  show() {
 0)   3.269 us    |    cpufreq_cpu_get();
 0)   0.190 us    |    unlock_policy_rwsem_read();
 0)   0.925 us    |    cpufreq_cpu_put();
 0) + 17.763 us   |  }



3 ----------------------跟踪结果分析



首先,
     我们分析下切换governor的过程:
      用户空间用户设置参数,内核空间要调用 store(),
      在store()中,
                   调用cpufreq_cpu_get() 取得cpufreq_policy 类型的cpufreq_cpu_data的副本,
      对cpufreq_cpu_data引用计数增一。然后要调用lock_policy_rwsem_write取得
      获取写锁cpu_policy_rwsem。
      再调用ret = fattr->store(policy, buf, count);根据我们使用ftrace跟踪的结果可以看出,
      实际调用了 store_scaling_governor()。该函数 为指定的CPU存储 policy。
      该函数调用cpufreq_get_policy()取得cpufreq_policy 类型的cpufreq_cpu_data的副本,
      对cpufreq_cpu_data引用计数增一。再把从用户空间传递过来的governor的名字
      存入局部变量str_governor中。
                   之后调用cpufreq_parse_governor对保存在str_governor中的
      governor名字进行解析,如果名字为performance或者powersave,则在入口参数policy中
      返回相应指示。否则,调用__find_governor将str_governor与cpufreq_governor_list上各个\
      governor比较,有跟str_governor相同的governor则返回它对应的结构的指针到入口
      参数governor。
                   接着,调用__cpufreq_set_policy设置新的policy [1],它复制旧policy 的
       cpuinfo域到新的policy的cpuinfo域。检查如果频率参数设置。再检查cpu的运行频率
       可以设定到新policy的指定的范围内。通知链上的各个事件监听者根据自己的特殊
       要求调整policy(CPUFREQ_ADJUST)。通知链上的各个事件监听者,如果硬件不兼容
       的话,可以调整policy(CPUFREQ_INCOMPATIBLE)。再检查cpu的运行频率可以设定
       到新policy的指定的范围内。通知链上的各个事件监听者新的policy启用。这时
       不兼容的硬件将会被停止,并向用户通知。
       接下来,如果定义了cpufreq_driver->setpolicy方法,则调用。否则,调用__cpufreq_governor
       (CPUFREQ_GOV_STOP), 即,停止governor对相应cpu的管理。
       设置新的governor,调用__cpufreq_governor(CPUFREQ_GOV_START)。在__cpufreq_governor
       中,间接调用了cpufreq_register_notifier,通知监听者
       CPUFREQ_POLICY_NOTIFIER --- policy改变。 再次调用__cpufreq_governor(CPUFREQ_GOV_LIMITS),
       通知链上的各个事件监听者cpu的频率范围已经改变。间接调用了
       __cpufreq_driver_target 用于执行cpufreq_driver->target。
              
               调用unlock_policy_rwsem_write释放锁cpu_policy_rwsem。调用cpufreq_cpu_put,
       对cpufreq_policy* 类型data所指向的结构的引用计数减一。store执行完毕,返回。
   
           [1] : policy由三部分组成: "policy,governor,min,max"
 
再次,分析下频率切换的处理(这里,governor已经切换为 userspace)  
      用户空间用户设置参数,内核空间要调用 store(),
      在store()中,
      
      调用cpufreq_cpu_get() 取得cpufreq_policy 类型的cpufreq_cpu_data的副本,
      对cpufreq_cpu_data引用计数增一。然后要调用lock_policy_rwsem_write取得
      获取写锁cpu_policy_rwsem。
       
       调用store_scaling_setspeed用于设置新的频率。
       policy->governor->store_setspeed(policy, freq),该语句,间接调用了
       __cpufreq_driver_target,  在__cpufreq_driver_target执行期间,
       cpufreq_notify_transition两次被调用(可能CPUFREQ_PRECHANGE/CPUFREQ_POSTCHANGE)。
       cpufreq_transition_notifier_list链上的监听者,       被通知频率的改变。并调用,
       adjust_jiffies,重新计算更新loops_per_jiffy值。
       
        调用unlock_policy_rwsem_write释放锁cpu_policy_rwsem。调用cpufreq_cpu_put,
       对cpufreq_policy* 类型data所指向的结构的引用计数减一。

 




 4 -------------func_list_latest

unlock_policy_rwsem_read
unlock_policy_rwsem_write
cpufreq_cpu_get
cpufreq_cpu_put
adjust_jiffies
cpufreq_notify_transition
__find_governor
show_cpuinfo_cur_freq  
show_scaling_governor
store_scaling_governor
show_scaling_driver
show_scaling_available_governors
show_cpus
show_related_cpus
show_affected_cpus
store_scaling_setspeed
show_scaling_setspeed
show_bios_limit
show  
store  
cpufreq_sysfs_release
cpufreq_add_dev  
cpufreq_remove_dev
cpufreq_get
cpufreq_bp_suspend
cpufreq_bp_resume
cpufreq_register_notifier  
cpufreq_unregister_notifier  
__cpufreq_driver_target
cpufreq_driver_target
__cpufreq_driver_getavg
__cpufreq_governor
cpufreq_register_governor
cpufreq_unregister_governor
cpufreq_get_policy  
__cpufreq_set_policy
cpufreq_update_policy
cpufreq_register_driver
cpufreq_unregister_driver