op_cpu_type.c

Go to the documentation of this file.
00001 
00012 #include <stdio.h>
00013 #include <stdlib.h>
00014 #include <string.h>
00015 #include <sys/utsname.h>
00016 #include <ctype.h>
00017 #include <errno.h>
00018 #include <fnmatch.h>
00019 
00020 #include "op_cpu_type.h"
00021 #include "op_hw_specific.h"
00022 
00023 struct cpu_descr {
00024     char const * pretty;
00025     char const * name;
00026     op_cpu cpu;
00027     unsigned int nr_counters;
00028 };
00029 
00030 static struct cpu_descr const cpu_descrs[MAX_CPU_TYPE] = {
00031     { "Pentium Pro", "i386/ppro", CPU_PPRO, 2 },
00032     { "PII", "i386/pii", CPU_PII, 2 },
00033     { "PIII", "i386/piii", CPU_PIII, 2 },
00034     { "Athlon", "i386/athlon", CPU_ATHLON, 4 },
00035     { "CPU with timer interrupt", "timer", CPU_TIMER_INT, 1 },
00036     { "CPU with RTC device", "rtc", CPU_RTC, 1 },
00037     { "P4 / Xeon", "i386/p4", CPU_P4, 8 },
00038     { "IA64", "ia64/ia64", CPU_IA64, 4 },
00039     { "Itanium", "ia64/itanium", CPU_IA64_1, 4 },
00040     { "Itanium 2", "ia64/itanium2", CPU_IA64_2, 4 },
00041     { "AMD64 processors", "x86-64/hammer", CPU_HAMMER, 4 },
00042     { "P4 / Xeon with 2 hyper-threads", "i386/p4-ht", CPU_P4_HT2, 4 },
00043     { "Alpha EV4", "alpha/ev4", CPU_AXP_EV4, 2 },
00044     { "Alpha EV5", "alpha/ev5", CPU_AXP_EV5, 3 },
00045     { "Alpha PCA56", "alpha/pca56", CPU_AXP_PCA56, 3 },
00046     { "Alpha EV6", "alpha/ev6", CPU_AXP_EV6, 2 },
00047     { "Alpha EV67", "alpha/ev67", CPU_AXP_EV67, 20 },
00048     { "Pentium M (P6 core)", "i386/p6_mobile", CPU_P6_MOBILE, 2 },
00049     { "ARM/XScale PMU1", "arm/xscale1", CPU_ARM_XSCALE1, 3 },
00050     { "ARM/XScale PMU2", "arm/xscale2", CPU_ARM_XSCALE2, 5 },
00051     { "ppc64 POWER4", "ppc64/power4", CPU_PPC64_POWER4, 8 },
00052     { "ppc64 POWER5", "ppc64/power5", CPU_PPC64_POWER5, 6 },
00053     { "ppc64 POWER5+", "ppc64/power5+", CPU_PPC64_POWER5p, 6 },
00054     { "ppc64 970", "ppc64/970", CPU_PPC64_970, 8 },
00055     { "MIPS 20K", "mips/20K", CPU_MIPS_20K, 1},
00056     { "MIPS 24K", "mips/24K", CPU_MIPS_24K, 2},
00057     { "MIPS 25K", "mips/25K", CPU_MIPS_25K, 2},
00058     { "MIPS 34K", "mips/34K", CPU_MIPS_34K, 2},
00059     { "MIPS 5K", "mips/5K", CPU_MIPS_5K, 2},
00060     { "MIPS R10000", "mips/r10000", CPU_MIPS_R10000, 2 },
00061     { "MIPS R12000", "mips/r12000", CPU_MIPS_R12000, 4 },
00062     { "QED RM7000", "mips/rm7000", CPU_MIPS_RM7000, 1 },
00063     { "PMC-Sierra RM9000", "mips/rm9000", CPU_MIPS_RM9000, 2 },
00064     { "Sibyte SB1", "mips/sb1", CPU_MIPS_SB1, 4 },
00065     { "NEC VR5432", "mips/vr5432", CPU_MIPS_VR5432, 2 },
00066     { "NEC VR5500", "mips/vr5500", CPU_MIPS_VR5500, 2 },
00067     { "e500", "ppc/e500", CPU_PPC_E500, 4 },
00068     { "e500v2", "ppc/e500v2", CPU_PPC_E500_2, 4 },
00069     { "Core Solo / Duo", "i386/core", CPU_CORE, 2 },
00070     { "PowerPC G4", "ppc/7450",  CPU_PPC_7450, 6 },
00071     { "Core 2", "i386/core_2", CPU_CORE_2, 2 },
00072     { "ppc64 POWER6", "ppc64/power6", CPU_PPC64_POWER6, 4 },
00073     { "ppc64 970MP", "ppc64/970MP", CPU_PPC64_970MP, 8 },
00074     { "ppc64 Cell Broadband Engine", "ppc64/cell-be", CPU_PPC64_CELL, 8 },
00075     { "AMD64 family10", "x86-64/family10", CPU_FAMILY10, 4 },
00076     { "ppc64 PA6T", "ppc64/pa6t", CPU_PPC64_PA6T, 6 },
00077     { "ARM 11MPCore", "arm/mpcore", CPU_ARM_MPCORE, 2 },
00078     { "ARM V6 PMU", "arm/armv6", CPU_ARM_V6, 3 },
00079     { "ppc64 POWER5++", "ppc64/power5++", CPU_PPC64_POWER5pp, 6 },
00080     { "e300", "ppc/e300", CPU_PPC_E300, 4 },
00081     { "AVR32", "avr32", CPU_AVR32, 3 },
00082     { "ARM Cortex-A8", "arm/armv7", CPU_ARM_V7, 5 },
00083     { "Intel Architectural Perfmon", "i386/arch_perfmon", CPU_ARCH_PERFMON, 0},
00084     { "AMD64 family11h", "x86-64/family11h", CPU_FAMILY11H, 4 },
00085     { "ppc64 POWER7", "ppc64/power7", CPU_PPC64_POWER7, 6 },
00086     { "ppc64 compat version 1", "ppc64/ibm-compat-v1", CPU_PPC64_IBM_COMPAT_V1, 4 },
00087     { "Intel Core/i7", "i386/core_i7", CPU_CORE_I7, 4 },
00088     { "Intel Atom", "i386/atom", CPU_ATOM, 2 },
00089     { "Loongson2", "mips/loongson2", CPU_MIPS_LOONGSON2, 2 },
00090     { "Intel Nehalem microarchitecture", "i386/nehalem", CPU_NEHALEM, 4 },
00091     { "ARM Cortex-A9", "arm/armv7-ca9", CPU_ARM_V7_CA9, 7 },
00092     { "MIPS 74K", "mips/74K", CPU_MIPS_74K, 4},
00093     { "MIPS 1004K", "mips/1004K", CPU_MIPS_1004K, 2},
00094     { "AMD64 family12h", "x86-64/family12h", CPU_FAMILY12H, 4 },
00095     { "AMD64 family14h", "x86-64/family14h", CPU_FAMILY14H, 4 },
00096     { "AMD64 family15h", "x86-64/family15h", CPU_FAMILY15H, 6 },
00097     { "Intel Westmere microarchitecture", "i386/westmere", CPU_WESTMERE, 4 },
00098     { "ARMv7 Scorpion", "arm/armv7-scorpion", CPU_ARM_SCORPION, 5 },
00099     { "ARMv7 ScorpionMP", "arm/armv7-scorpionmp", CPU_ARM_SCORPIONMP, 5 },
00100     { "Intel Sandy Bridge microarchitecture", "i386/sandybridge", CPU_SANDYBRIDGE, 8 },
00101     { "TILE64", "tile/tile64", CPU_TILE_TILE64, 2 },
00102     { "TILEPro", "tile/tilepro", CPU_TILE_TILEPRO, 4 },
00103     { "TILE-GX", "tile/tilegx", CPU_TILE_TILEGX, 4 },
00104     { "IBM System z10", "s390/z10", CPU_S390_Z10, 1 },
00105     { "IBM zEnterprise z196", "s390/z196", CPU_S390_Z196, 1 },
00106     { "Intel Ivy Bridge microarchitecture", "i386/ivybridge", CPU_IVYBRIDGE, 8 },
00107     { "ARM Cortex-A5", "arm/armv7-ca5", CPU_ARM_V7_CA5, 3 },
00108     { "ARM Cortex-A7", "arm/armv7-ca7", CPU_ARM_V7_CA7, 5 },
00109     { "ARM Cortex-A15", "arm/armv7-ca15", CPU_ARM_V7_CA15, 7 },
00110 };
00111  
00112 static size_t const nr_cpu_descrs = sizeof(cpu_descrs) / sizeof(struct cpu_descr);
00113 
00114 static char * _get_cpuinfo_cpu_type_line(char * buf, int len, const char * prefix, int token)
00115 {
00116     char * ret = NULL;
00117     char * end = NULL;
00118     int prefix_len = strlen(prefix);
00119     FILE * fp = fopen("/proc/cpuinfo", "r");
00120 
00121     if (!fp) {
00122         perror("Unable to open /proc/cpuinfo\n");
00123         return ret;
00124     }
00125 
00126     memset(buf, 0, len);
00127 
00128     while (!ret) {
00129         if (fgets(buf, len, fp) == NULL) {
00130             fprintf(stderr, "Did not find processor type in /proc/cpuinfo.\n");
00131             break;
00132         }
00133         if (!strncmp(buf, prefix, prefix_len)) {
00134             ret = buf + prefix_len;
00135             /* Strip leading whitespace and ':' delimiter */
00136             while (*ret && (*ret == ':' || isspace(*ret)))
00137                 ++ret;
00138             buf = ret;
00139             /* if token param 0 then read the whole line else
00140              * first token only. */
00141             if (token == 0) {
00142                 /* Trim trailing whitespace */
00143                 end = buf + strlen(buf) - 1;
00144                 while (isspace(*end))
00145                     --end;
00146                 *(++end) = '\0';
00147                 break;
00148             } else {
00149                 /* Scan ahead to the end of the token */
00150                 while (*buf && !isspace(*buf))
00151                     ++buf;
00152                 /* Trim trailing whitespace */
00153                 *buf = '\0';
00154                 break;
00155             }
00156         }
00157     }
00158 
00159     fclose(fp);
00160     return ret;
00161 }
00162 
00163 static char * _get_cpuinfo_cpu_type(char * buf, int len, const char * prefix)
00164 {
00165     return _get_cpuinfo_cpu_type_line(buf, len, prefix, 1);
00166 }
00167 
00168 static op_cpu _get_ppc64_cpu_type(void)
00169 {
00170     int i;
00171     size_t len;
00172     char line[100], cpu_type_str[64], cpu_name_lowercase[64], * cpu_name;
00173 
00174     cpu_name = _get_cpuinfo_cpu_type(line, 100, "cpu");
00175     if (!cpu_name)
00176         return CPU_NO_GOOD;
00177 
00178     len = strlen(cpu_name);
00179     for (i = 0; i < (int)len ; i++)
00180         cpu_name_lowercase[i] = tolower(cpu_name[i]);
00181 
00182     cpu_type_str[0] = '\0';
00183     strcat(cpu_type_str, "ppc64/");
00184     strncat(cpu_type_str, cpu_name_lowercase, len);
00185     return op_get_cpu_number(cpu_type_str);
00186 }
00187 
00188 static op_cpu _get_arm_cpu_type(void)
00189 {
00190     unsigned long cpuid, vendorid;
00191     char line[100];
00192     char * cpu_part, * cpu_implementer;
00193 
00194     cpu_implementer = _get_cpuinfo_cpu_type(line, 100, "CPU implementer");
00195     if (!cpu_implementer)
00196         return CPU_NO_GOOD;
00197 
00198     errno = 0;
00199     vendorid = strtoul(cpu_implementer, NULL, 16);
00200     if (errno) {
00201         fprintf(stderr, "Unable to parse CPU implementer %s\n", cpu_implementer);
00202         return CPU_NO_GOOD;
00203     }
00204 
00205     cpu_part = _get_cpuinfo_cpu_type(line, 100, "CPU part");
00206     if (!cpu_part)
00207         return CPU_NO_GOOD;
00208 
00209     errno = 0;
00210     cpuid = strtoul(cpu_part, NULL, 16);
00211     if (errno) {
00212         fprintf(stderr, "Unable to parse CPU part %s\n", cpu_part);
00213         return CPU_NO_GOOD;
00214     }
00215 
00216     if (vendorid == 0x41) {     /* ARM Ltd. */
00217         switch (cpuid) {
00218         case 0xb36:
00219         case 0xb56:
00220         case 0xb76:
00221             return op_get_cpu_number("arm/armv6");
00222         case 0xb02:
00223             return op_get_cpu_number("arm/mpcore");
00224         case 0xc05:
00225             return op_get_cpu_number("arm/armv7-ca5");
00226         case 0xc07:
00227             return op_get_cpu_number("arm/armv7-ca7");
00228         case 0xc08:
00229             return op_get_cpu_number("arm/armv7");
00230         case 0xc09:
00231             return op_get_cpu_number("arm/armv7-ca9");
00232         case 0xc0f:
00233             return op_get_cpu_number("arm/armv7-ca15");
00234         }
00235     } else if (vendorid == 0x69) {  /* Intel xscale */
00236         switch (cpuid >> 9) {
00237         case 1:
00238             return op_get_cpu_number("arm/xscale1");
00239         case 2:
00240             return op_get_cpu_number("arm/xscale2");
00241         }
00242     }
00243 
00244     return CPU_NO_GOOD;
00245 }
00246 
00247 static op_cpu _get_tile_cpu_type(void)
00248 {
00249     int i;
00250     size_t len;
00251     char line[100], cpu_type_str[64], cpu_name_lowercase[64], * cpu_name;
00252 
00253     cpu_name = _get_cpuinfo_cpu_type(line, 100, "model name");
00254     if (!cpu_name)
00255         return CPU_NO_GOOD;
00256 
00257     len = strlen(cpu_name);
00258     for (i = 0; i < (int)len ; i++)
00259         cpu_name_lowercase[i] = tolower(cpu_name[i]);
00260 
00261     cpu_type_str[0] = '\0';
00262     strcat(cpu_type_str, "tile/");
00263     strncat(cpu_type_str, cpu_name_lowercase, len);
00264     return op_get_cpu_number(cpu_type_str);
00265 }
00266 
00267 #if defined(__x86_64__) || defined(__i386__)
00268 int op_is_cpu_vendor(char * vendor)
00269 {
00270     return cpuid_vendor(vendor);
00271 }
00272 
00273 static unsigned cpuid_eax(unsigned func)
00274 {
00275     cpuid_data d;
00276 
00277     cpuid(func, &d);
00278     return d.eax;
00279 }
00280 
00281 static inline int perfmon_available(void)
00282 {
00283         unsigned eax;
00284         if (cpuid_eax(0) < 10)
00285                 return 0;
00286         eax = cpuid_eax(10);
00287         if ((eax & 0xff) == 0)
00288                 return 0;
00289         return (eax >> 8) & 0xff;
00290 }
00291 
00292 static int cpu_info_number(char *name, unsigned long *number)
00293 {
00294         char buf[100];
00295         char *end;
00296 
00297         if (!_get_cpuinfo_cpu_type(buf, sizeof buf, name))
00298                 return 0;
00299         *number = strtoul(buf, &end, 0);
00300         return end > buf;
00301 }
00302 
00303 static op_cpu _get_intel_cpu_type(void)
00304 {
00305     unsigned eax, family, model;
00306 
00307     if (perfmon_available())
00308         return op_cpu_specific_type(CPU_ARCH_PERFMON);
00309 
00310     /* Handle old non arch perfmon CPUs */
00311     eax = cpuid_signature();
00312     family = cpu_family(eax);
00313     model = cpu_model(eax);
00314 
00315     if (family == 6) {
00316         /* Reproduce kernel p6_init logic. Only for non arch perfmon cpus */
00317         switch (model) {
00318         case 0 ... 2:
00319             return op_get_cpu_number("i386/ppro");
00320         case 3 ... 5:
00321             return op_get_cpu_number("i386/pii");
00322         case 6 ... 8:
00323         case 10 ... 11:
00324             return op_get_cpu_number("i386/piii");
00325         case 9:
00326         case 13:
00327             return op_get_cpu_number("i386/p6_mobile");
00328         }
00329     } else if (family == 15) {
00330         unsigned long siblings;
00331 
00332         /* Reproduce kernel p4_init() logic */
00333         if (model > 6 || model == 5)
00334             return CPU_NO_GOOD;
00335         if (!cpu_info_number("siblings", &siblings) ||
00336             siblings == 1)
00337             return op_get_cpu_number("i386/p4");
00338         if (siblings == 2)
00339             return op_get_cpu_number("i386/p4-ht");
00340     }
00341     return CPU_NO_GOOD;         
00342 }
00343 
00344 static op_cpu _get_amd_cpu_type(void)
00345 {
00346     unsigned eax, family, model;
00347     op_cpu ret = CPU_NO_GOOD;
00348 
00349     eax = cpuid_signature();
00350     family = cpu_family(eax);
00351     model = cpu_model(eax);
00352 
00353     switch (family) {
00354     case 0x0f:
00355         ret = op_get_cpu_number("x86-64/hammer");
00356         break;
00357     case 0x10:
00358         ret = op_get_cpu_number("x86-64/family10");
00359         break;
00360     case 0x11:
00361         ret = op_get_cpu_number("x86-64/family11h");
00362         break;
00363     case 0x12:
00364         ret = op_get_cpu_number("x86-64/family12h");
00365         break;
00366     case 0x14:
00367         ret = op_get_cpu_number("x86-64/family14h");
00368         break;
00369     case 0x15:
00370         switch (model) {
00371         case 0x00 ... 0x0f:
00372             ret = op_get_cpu_number("x86-64/family15h");
00373             break;      
00374         default:
00375             break;
00376         }
00377         break;
00378     default:
00379         break;
00380     }
00381 
00382     return ret;         
00383 }
00384 
00385 static op_cpu _get_x86_64_cpu_type(void)
00386 {
00387     op_cpu ret = CPU_NO_GOOD;
00388 
00389     if (cpuid_vendor("GenuineIntel")) {
00390         ret = _get_intel_cpu_type();
00391     } else if (cpuid_vendor("AuthenticAMD")) {
00392         ret = _get_amd_cpu_type();
00393     }
00394 
00395     return ret;
00396 }
00397 
00398 #else
00399 static op_cpu _get_x86_64_cpu_type(void)
00400 {
00401     return CPU_NO_GOOD;
00402 }
00403 #endif
00404 
00405 struct mips_cpu_descr
00406 {
00407     const char * key;
00408     const char * value;
00409 };
00410 
00411 static struct mips_cpu_descr mips_cpu_descrs[] = {
00412     { .key = "MIPS 5Kc", .value = "mips/5K" },      /* CPU_5KC */
00413     { .key = "MIPS 20Kc", .value = "mips/20K" },        /* CPU_20KC */
00414     { .key = "MIPS 24Kc", .value = "mips/24K" },        /* CPU_24K */
00415     { .key = "MIPS 25Kc", .value = "mips/25K" },        /* CPU_25KF */
00416     { .key = "MIPS 34Kc", .value = "mips/34K" },        /* CPU_34K */
00417     { .key = "MIPS 74Kc", .value = "mips/74K" },        /* CPU_74K */
00418     { .key = "MIPS M14Kc", .value = "mips/M14Kc" },     /* CPU_M14KC */
00419     { .key = "RM9000", .value = "mips/rm9000" },        /* CPU_RM9000 */
00420     { .key = "R10000", .value = "mips/r10000" },        /* CPU_R10000 */
00421     { .key = "R12000", .value = "mips/r12000" },        /* CPU_R12000 */
00422     { .key = "R14000", .value = "mips/r12000" },        /* CPU_R14000 */
00423     { .key = "ICT Loongson-2", .value = "mips/loongson2" }, /* CPU_LOONGSON2 */
00424     { .key = NULL, .value = NULL }
00425 };
00426 
00427 static const char * _get_mips_op_name(const char * key)
00428 {
00429     struct mips_cpu_descr * p_it = mips_cpu_descrs;
00430     size_t len;
00431 
00432 
00433     while (p_it->key != NULL) {
00434         len = strlen(p_it->key);
00435         if (0 == strncmp(key, p_it->key, len))
00436             return p_it->value;
00437         ++p_it;
00438     }
00439     return NULL;
00440 }
00441 
00442 static op_cpu _get_mips_cpu_type(void)
00443 {
00444     char line[100];
00445     char * cpu_model;
00446     const char * op_name = NULL;
00447 
00448     cpu_model = _get_cpuinfo_cpu_type_line(line, 100, "cpu model", 0);
00449     if (!cpu_model)
00450         return CPU_NO_GOOD;
00451 
00452     op_name = _get_mips_op_name(cpu_model);
00453 
00454     if (op_name)
00455         return op_get_cpu_number(op_name);
00456     return CPU_NO_GOOD;
00457 }
00458 
00459 static op_cpu __get_cpu_type_alt_method(void)
00460 {
00461     struct utsname uname_info;
00462     if (uname(&uname_info) < 0) {
00463         perror("uname failed");
00464         return CPU_NO_GOOD;
00465     }
00466     if (strncmp(uname_info.machine, "x86_64", 6) == 0 || 
00467         fnmatch("i?86", uname_info.machine, 0) == 0) {
00468         return _get_x86_64_cpu_type();
00469     }
00470     if (strncmp(uname_info.machine, "ppc64", 5) == 0) {
00471         return _get_ppc64_cpu_type();
00472     }
00473     if (strncmp(uname_info.machine, "arm", 3) == 0) {
00474         return _get_arm_cpu_type();
00475     }
00476     if (strncmp(uname_info.machine, "tile", 4) == 0) {
00477         return _get_tile_cpu_type();
00478     }
00479     if (strncmp(uname_info.machine, "mips", 4) == 0) {
00480         return _get_mips_cpu_type();
00481     }
00482     return CPU_NO_GOOD;
00483 }
00484 
00485 int op_cpu_variations(op_cpu cpu_type)
00486 {
00487     switch (cpu_type) {
00488     case  CPU_ARCH_PERFMON:
00489         return 1;
00490     default:
00491         return 0;
00492     }
00493 }
00494 
00495 
00496 op_cpu op_cpu_base_type(op_cpu cpu_type)
00497 {
00498     /* All the processors that support CPU_ARCH_PERFMON */
00499     switch (cpu_type) {
00500     case CPU_CORE_2:
00501     case CPU_CORE_I7:
00502     case CPU_ATOM:
00503     case CPU_NEHALEM:
00504     case CPU_WESTMERE:
00505     case CPU_SANDYBRIDGE:
00506     case CPU_IVYBRIDGE:
00507         return CPU_ARCH_PERFMON;
00508     default:
00509         /* assume processor in a class by itself */
00510         return cpu_type;
00511     }
00512 }
00513 
00514 op_cpu op_get_cpu_type(void)
00515 {
00516     int cpu_type = CPU_NO_GOOD;
00517     char str[100];
00518     FILE * fp;
00519 
00520     fp = fopen("/proc/sys/dev/oprofile/cpu_type", "r");
00521     if (!fp) {
00522         /* Try 2.6's oprofilefs one instead. */
00523         fp = fopen("/dev/oprofile/cpu_type", "r");
00524         if (!fp) {
00525             if ((cpu_type = __get_cpu_type_alt_method()) == CPU_NO_GOOD) {
00526                 fprintf(stderr, "Unable to open cpu_type file for reading\n");
00527                 fprintf(stderr, "Make sure you have done opcontrol --init\n");
00528             }
00529             return cpu_type;
00530         }
00531     }
00532 
00533     if (!fgets(str, 99, fp)) {
00534         fprintf(stderr, "Could not read cpu type.\n");
00535         fclose(fp);
00536         return cpu_type;
00537     }
00538 
00539     cpu_type = op_get_cpu_number(str);
00540 
00541     if (op_cpu_variations(cpu_type))
00542         cpu_type = op_cpu_specific_type(cpu_type);
00543 
00544     fclose(fp);
00545 
00546     return cpu_type;
00547 }
00548 
00549 
00550 op_cpu op_get_cpu_number(char const * cpu_string)
00551 {
00552     int cpu_type = CPU_NO_GOOD;
00553     size_t i;
00554     
00555     for (i = 0; i < nr_cpu_descrs; ++i) {
00556         if (!strcmp(cpu_descrs[i].name, cpu_string)) {
00557             cpu_type = cpu_descrs[i].cpu;
00558             break;
00559         }
00560     }
00561 
00562     /* Attempt to convert into a number */
00563     if (cpu_type == CPU_NO_GOOD)
00564         sscanf(cpu_string, "%d\n", &cpu_type);
00565     
00566     if (cpu_type <= CPU_NO_GOOD || cpu_type >= MAX_CPU_TYPE)
00567         cpu_type = CPU_NO_GOOD;
00568 
00569     return cpu_type;
00570 }
00571 
00572 
00573 char const * op_get_cpu_type_str(op_cpu cpu_type)
00574 {
00575     if (cpu_type <= CPU_NO_GOOD || cpu_type >= MAX_CPU_TYPE)
00576         return "invalid cpu type";
00577 
00578     return cpu_descrs[cpu_type].pretty;
00579 }
00580 
00581 
00582 char const * op_get_cpu_name(op_cpu cpu_type)
00583 {
00584     if (cpu_type <= CPU_NO_GOOD || cpu_type >= MAX_CPU_TYPE)
00585         return "invalid cpu type";
00586 
00587     return cpu_descrs[cpu_type].name;
00588 }
00589 
00590 
00591 int op_get_nr_counters(op_cpu cpu_type)
00592 {
00593     int cnt;
00594 
00595     if (cpu_type <= CPU_NO_GOOD || cpu_type >= MAX_CPU_TYPE)
00596         return 0;
00597 
00598     cnt = arch_num_counters(cpu_type);
00599     if (cnt >= 0)
00600         return cnt;
00601 
00602     return op_cpu_has_timer_fs()
00603         ? cpu_descrs[cpu_type].nr_counters + 1
00604         : cpu_descrs[cpu_type].nr_counters;
00605 }
00606 
00607 int op_cpu_has_timer_fs(void)
00608 {
00609     static int cached_has_timer_fs_p = -1;
00610     FILE * fp;
00611 
00612     if (cached_has_timer_fs_p != -1)
00613         return cached_has_timer_fs_p;
00614 
00615     fp = fopen("/dev/oprofile/timer", "r");
00616     cached_has_timer_fs_p = !!fp;
00617     if (fp)
00618         fclose(fp);
00619 
00620     return cached_has_timer_fs_p;
00621 }

Generated on 8 Nov 2012 for Oprofile by  doxygen 1.6.1