1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_CPU_H_ 6 #define BASE_CPU_H_ 7 8 #include <string> 9 #include <tuple> 10 #include <vector> 11 12 #include "base/base_export.h" 13 #include "base/time/time.h" 14 #include "build/build_config.h" 15 16 namespace base { 17 18 #if defined(ARCH_CPU_X86_FAMILY) 19 namespace internal { 20 21 // Compute the CPU family and model based on the vendor and CPUID signature. 22 // Returns in order: family, model, extended family, extended model. 23 BASE_EXPORT std::tuple<int, int, int, int> ComputeX86FamilyAndModel( 24 const std::string& vendor, 25 int signature); 26 27 } // namespace internal 28 #endif // defined(ARCH_CPU_X86_FAMILY) 29 30 // Query information about the processor. 31 class BASE_EXPORT CPU final { 32 public: 33 CPU(); 34 35 enum IntelMicroArchitecture { 36 PENTIUM, 37 SSE, 38 SSE2, 39 SSE3, 40 SSSE3, 41 SSE41, 42 SSE42, 43 AVX, 44 AVX2, 45 MAX_INTEL_MICRO_ARCHITECTURE 46 }; 47 48 // Accessors for CPU information. vendor_name()49 const std::string& vendor_name() const { return cpu_vendor_; } signature()50 int signature() const { return signature_; } stepping()51 int stepping() const { return stepping_; } model()52 int model() const { return model_; } family()53 int family() const { return family_; } type()54 int type() const { return type_; } extended_model()55 int extended_model() const { return ext_model_; } extended_family()56 int extended_family() const { return ext_family_; } has_mmx()57 bool has_mmx() const { return has_mmx_; } has_sse()58 bool has_sse() const { return has_sse_; } has_sse2()59 bool has_sse2() const { return has_sse2_; } has_sse3()60 bool has_sse3() const { return has_sse3_; } has_ssse3()61 bool has_ssse3() const { return has_ssse3_; } has_sse41()62 bool has_sse41() const { return has_sse41_; } has_sse42()63 bool has_sse42() const { return has_sse42_; } has_popcnt()64 bool has_popcnt() const { return has_popcnt_; } has_avx()65 bool has_avx() const { return has_avx_; } has_avx2()66 bool has_avx2() const { return has_avx2_; } has_aesni()67 bool has_aesni() const { return has_aesni_; } has_non_stop_time_stamp_counter()68 bool has_non_stop_time_stamp_counter() const { 69 return has_non_stop_time_stamp_counter_; 70 } is_running_in_vm()71 bool is_running_in_vm() const { return is_running_in_vm_; } 72 73 IntelMicroArchitecture GetIntelMicroArchitecture() const; cpu_brand()74 const std::string& cpu_brand() const { return cpu_brand_; } 75 76 #if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) || defined(OS_BSD) || \ 77 defined(OS_AIX) 78 enum class CoreType { 79 kUnknown = 0, 80 kOther, 81 kSymmetric, 82 kBigLittle_Little, 83 kBigLittle_Big, 84 kBigLittleBigger_Little, 85 kBigLittleBigger_Big, 86 kBigLittleBigger_Bigger, 87 kMaxValue = kBigLittleBigger_Bigger 88 }; 89 90 // Attempts to guess the core types of individual CPU cores based on frequency 91 // information from /sys/devices/system/cpu/cpuN/cpufreq/cpuinfo_max_freq. 92 // Beware that it is kernel/hardware dependent whether the information from 93 // sys is accurate. Returns a reference to a static-storage vector (leaked on 94 // shutdown) with the guessed type for core N at index N. 95 static const std::vector<CoreType>& GetGuessedCoreTypes(); 96 97 struct TimeInStateEntry { 98 CPU::CoreType core_type; // type of the cores in this cluster. 99 uint32_t cluster_core_index; // index of the first core in the cluster. 100 uint64_t core_frequency_khz; 101 TimeDelta cumulative_time; 102 }; 103 using TimeInState = std::vector<TimeInStateEntry>; 104 105 // For each CPU core, emits the cumulative time spent in different frequency 106 // states into the output parameter (replacing its current contents). One 107 // entry in the output parameter is added for each cluster core index 108 // + frequency state combination with a non-zero CPU time value. Returns false 109 // on failure. We return the usage via an output parameter to allow reuse of 110 // TimeInState's std::vector by the caller, e.g. to avoid allocations between 111 // repeated calls to this method. 112 // 113 // NOTE: Currently only supported on Linux/Android, and only on kernels with 114 // cpufreq-stats driver. 115 static bool GetTimeInState(TimeInState&); 116 117 // For each CPU core, emits the total cumulative wall time spent in any idle 118 // state into the output parameter (replacing its current contents). Returns 119 // false on failure. We return the usage via an output parameter to allow 120 // reuse of TimeInState's std::vector by the caller, e.g. to avoid allocations 121 // between repeated calls to this method. 122 // 123 // NOTE: Currently only supported on Linux/Android, and only on kernels with 124 // cpuidle driver. 125 using CoreIdleTimes = std::vector<TimeDelta>; 126 static bool GetCumulativeCoreIdleTimes(CoreIdleTimes&); 127 #endif // defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) || defined(OS_BSD) 128 // defined(OS_AIX) 129 130 private: 131 // Query the processor for CPUID information. 132 void Initialize(); 133 134 int signature_; // raw form of type, family, model, and stepping 135 int type_; // process type 136 int family_; // family of the processor 137 int model_; // model of processor 138 int stepping_; // processor revision number 139 int ext_model_; 140 int ext_family_; 141 bool has_mmx_; 142 bool has_sse_; 143 bool has_sse2_; 144 bool has_sse3_; 145 bool has_ssse3_; 146 bool has_sse41_; 147 bool has_sse42_; 148 bool has_popcnt_; 149 bool has_avx_; 150 bool has_avx2_; 151 bool has_aesni_; 152 bool has_non_stop_time_stamp_counter_; 153 bool is_running_in_vm_; 154 std::string cpu_vendor_; 155 std::string cpu_brand_; 156 }; 157 158 } // namespace base 159 160 #endif // BASE_CPU_H_ 161