summaryrefslogtreecommitdiff
path: root/chromium/base/cpu.cc
diff options
context:
space:
mode:
authorZeno Albisser <zeno.albisser@theqtcompany.com>2014-12-05 15:04:29 +0100
committerAndras Becsi <andras.becsi@theqtcompany.com>2014-12-09 10:49:28 +0100
commitaf6588f8d723931a298c995fa97259bb7f7deb55 (patch)
tree060ca707847ba1735f01af2372e0d5e494dc0366 /chromium/base/cpu.cc
parent2fff84d821cc7b1c785f6404e0f8091333283e74 (diff)
downloadqtwebengine-chromium-af6588f8d723931a298c995fa97259bb7f7deb55.tar.gz
BASELINE: Update chromium to 40.0.2214.28 and ninja to 1.5.3.
Change-Id: I759465284fd64d59ad120219cbe257f7402c4181 Reviewed-by: Andras Becsi <andras.becsi@theqtcompany.com>
Diffstat (limited to 'chromium/base/cpu.cc')
-rw-r--r--chromium/base/cpu.cc115
1 files changed, 83 insertions, 32 deletions
diff --git a/chromium/base/cpu.cc b/chromium/base/cpu.cc
index dcba3b6e73e..ef3309dad18 100644
--- a/chromium/base/cpu.cc
+++ b/chromium/base/cpu.cc
@@ -4,15 +4,17 @@
#include "base/cpu.h"
+#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include "base/basictypes.h"
+#include "base/strings/string_piece.h"
#include "build/build_config.h"
#if defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX))
-#include "base/file_util.h"
+#include "base/files/file_util.h"
#include "base/lazy_instance.h"
#endif
@@ -44,6 +46,7 @@ CPU::CPU()
has_avx_hardware_(false),
has_aesni_(false),
has_non_stop_time_stamp_counter_(false),
+ has_broken_neon_(false),
cpu_vendor_("unknown") {
Initialize();
}
@@ -90,52 +93,99 @@ uint64 _xgetbv(uint32 xcr) {
#endif // ARCH_CPU_X86_FAMILY
#if defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX))
+class LazyCpuInfoValue {
+ public:
+ LazyCpuInfoValue() : has_broken_neon_(false) {
+ // This function finds the value from /proc/cpuinfo under the key "model
+ // name" or "Processor". "model name" is used in Linux 3.8 and later (3.7
+ // and later for arm64) and is shown once per CPU. "Processor" is used in
+ // earler versions and is shown only once at the top of /proc/cpuinfo
+ // regardless of the number CPUs.
+ const char kModelNamePrefix[] = "model name\t: ";
+ const char kProcessorPrefix[] = "Processor\t: ";
+
+ // This function also calculates whether we believe that this CPU has a
+ // broken NEON unit based on these fields from cpuinfo:
+ unsigned implementer = 0, architecture = 0, variant = 0, part = 0,
+ revision = 0;
+ const struct {
+ const char key[17];
+ unsigned *result;
+ } kUnsignedValues[] = {
+ {"CPU implementer", &implementer},
+ {"CPU architecture", &architecture},
+ {"CPU variant", &variant},
+ {"CPU part", &part},
+ {"CPU revision", &revision},
+ };
+
+ std::string contents;
+ ReadFileToString(FilePath("/proc/cpuinfo"), &contents);
+ DCHECK(!contents.empty());
+ if (contents.empty()) {
+ return;
+ }
-// Returns the string found in /proc/cpuinfo under the key "model name" or
-// "Processor". "model name" is used in Linux 3.8 and later (3.7 and later for
-// arm64) and is shown once per CPU. "Processor" is used in earler versions and
-// is shown only once at the top of /proc/cpuinfo regardless of the number CPUs.
-std::string ParseCpuInfo() {
- const char kModelNamePrefix[] = "model name\t: ";
- const char kProcessorPrefix[] = "Processor\t: ";
- std::string contents;
- ReadFileToString(FilePath("/proc/cpuinfo"), &contents);
- DCHECK(!contents.empty());
- std::string cpu_brand;
- if (!contents.empty()) {
std::istringstream iss(contents);
std::string line;
while (std::getline(iss, line)) {
- if (line.compare(0, strlen(kModelNamePrefix), kModelNamePrefix) == 0) {
- cpu_brand.assign(line.substr(strlen(kModelNamePrefix)));
- break;
+ if (brand_.empty() &&
+ (line.compare(0, strlen(kModelNamePrefix), kModelNamePrefix) == 0 ||
+ line.compare(0, strlen(kProcessorPrefix), kProcessorPrefix) == 0)) {
+ brand_.assign(line.substr(strlen(kModelNamePrefix)));
}
- if (line.compare(0, strlen(kProcessorPrefix), kProcessorPrefix) == 0) {
- cpu_brand.assign(line.substr(strlen(kProcessorPrefix)));
- break;
+
+ for (size_t i = 0; i < arraysize(kUnsignedValues); i++) {
+ const char *key = kUnsignedValues[i].key;
+ const size_t len = strlen(key);
+
+ if (line.compare(0, len, key) == 0 &&
+ line.size() >= len + 1 &&
+ (line[len] == '\t' || line[len] == ' ' || line[len] == ':')) {
+ size_t colon_pos = line.find(':', len);
+ if (colon_pos == std::string::npos) {
+ continue;
+ }
+
+ const StringPiece line_sp(line);
+ StringPiece value_sp = line_sp.substr(colon_pos + 1);
+ while (!value_sp.empty() &&
+ (value_sp[0] == ' ' || value_sp[0] == '\t')) {
+ value_sp = value_sp.substr(1);
+ }
+
+ // The string may have leading "0x" or not, so we use strtoul to
+ // handle that.
+ char *endptr;
+ std::string value(value_sp.as_string());
+ unsigned long int result = strtoul(value.c_str(), &endptr, 0);
+ if (*endptr == 0 && result <= UINT_MAX) {
+ *kUnsignedValues[i].result = result;
+ }
+ }
}
}
+
+ has_broken_neon_ =
+ implementer == 0x51 &&
+ architecture == 7 &&
+ variant == 1 &&
+ part == 0x4d &&
+ revision == 0;
}
- return cpu_brand;
-}
-class LazyCpuInfoValue {
- public:
- LazyCpuInfoValue() : value_(ParseCpuInfo()) {}
- const std::string& value() { return value_; }
+ const std::string& brand() const { return brand_; }
+ bool has_broken_neon() const { return has_broken_neon_; }
private:
- const std::string value_;
+ std::string brand_;
+ bool has_broken_neon_;
DISALLOW_COPY_AND_ASSIGN(LazyCpuInfoValue);
};
-base::LazyInstance<LazyCpuInfoValue> g_lazy_cpu_brand =
+base::LazyInstance<LazyCpuInfoValue>::Leaky g_lazy_cpuinfo =
LAZY_INSTANCE_INITIALIZER;
-const std::string& CpuBrandInfo() {
- return g_lazy_cpu_brand.Get().value();
-}
-
#endif // defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) ||
// defined(OS_LINUX))
@@ -219,7 +269,8 @@ void CPU::Initialize() {
has_non_stop_time_stamp_counter_ = (cpu_info[3] & (1 << 8)) != 0;
}
#elif defined(ARCH_CPU_ARM_FAMILY) && (defined(OS_ANDROID) || defined(OS_LINUX))
- cpu_brand_.assign(CpuBrandInfo());
+ cpu_brand_.assign(g_lazy_cpuinfo.Get().brand());
+ has_broken_neon_ = g_lazy_cpuinfo.Get().has_broken_neon();
#endif
}