op_cpufreq.c

Go to the documentation of this file.
00001 
00013 #include <stdio.h>
00014 #include <stdlib.h>
00015 
00016 #include "op_fileio.h"
00017 
00018 /*
00019  * Use frequency information from /proc/cpuinfo. This should be available in most case.
00020  * However, this number is the current cpu frequency which could be in the idle state.
00021  * We should actually report the max frequency because the cpu should switch into the
00022  * highest power state when running.
00023  */
00024 static double op_cpu_freq_cpuinfo(void)
00025 {
00026     double fval = 0.0;
00027     unsigned long uval;
00028     char * line = NULL;
00029 
00030     FILE * fp = op_try_open_file("/proc/cpuinfo", "r");
00031     if (!fp)
00032         return 0.0;
00033 
00034     while (1) {
00035         line = op_get_line(fp);
00036 
00037         if (!line)
00038             break;
00039 
00040         if (line[0] == '\0') {
00041             free(line);
00042             continue;
00043         }
00044 
00045         /* x86/parisc/ia64/x86_64 */
00046         if (sscanf(line, "cpu MHz : %lf", &fval) == 1)
00047             break;
00048         /* ppc/ppc64 */
00049         if (sscanf(line, "clock : %lfMHz", &fval) == 1)
00050             break;
00051         /* alpha */
00052         if (sscanf(line, "cycle frequency [Hz] : %lu", &uval) == 1) {
00053             fval = uval / 1E6;
00054             break;
00055         }
00056         /* sparc64 if CONFIG_SMP only */
00057         if (sscanf(line, "Cpu0ClkTck : %lx", &uval) == 1) {
00058             fval = uval / 1E6;
00059             break;
00060         }
00061         /* mips including loongson2 */
00062         if (sscanf(line, "BogoMIPS      : %lu", &uval) == 1) {
00063             fval = uval * 3 / 2;
00064             break;
00065         }
00066         /* s390 doesn't provide cpu freq, checked up to 2.6-test4 */
00067 
00068         free(line);
00069     }
00070 
00071     if (line)
00072         free(line);
00073     op_close_file(fp);
00074 
00075     return fval;
00076 }
00077 
00078 
00079 /*
00080  * Use frequency information from /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq
00081  * This number is the maximum cpu frequency of the processor.
00082  */
00083 static double op_cpu_freq_sys_devices(void)
00084 {
00085     double fval = 0.0;
00086     char * line = NULL;
00087 
00088     FILE * fp = op_try_open_file("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq", "r");
00089     if (!fp)
00090         return 0.0;
00091 
00092     while (1) {
00093         line = op_get_line(fp);
00094 
00095         if (!line)
00096             break;
00097 
00098         if (line[0] == '\0') {
00099             free(line);
00100             continue;
00101         }
00102 
00103         if (sscanf(line, "%lf", &fval) == 1)
00104             break;
00105 
00106         free(line);
00107     }
00108 
00109     if (line)
00110         free(line);
00111     op_close_file(fp);
00112 
00113     return fval;
00114 }
00115 
00116 
00117 double op_cpu_frequency(void)
00118 {
00119     /*
00120      * Typically, system changes the frequency scaling of the cpus
00121      * based on the workload.  /proc/cpuinfo reports the current
00122      * frequency value which might not be at the maximum at the time
00123      * of query.  Since cpu switch into running state with max frequency
00124      * when under workload, we should make sure to report the max frequency
00125      * value acquiring from /sys/devices when available.
00126      */
00127 
00128     double freq = op_cpu_freq_sys_devices();
00129     if (freq == 0) {
00130         freq = op_cpu_freq_cpuinfo();
00131     }
00132     return freq;
00133 }

Generated on 8 Nov 2012 for Oprofile by  doxygen 1.6.1