Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(222)

Unified Diff: third_party/tcmalloc/chromium/src/base/sysinfo.cc

Issue 7050034: Merge google-perftools r109 (the current contents of third_party/tcmalloc/vendor) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/tcmalloc/chromium/src/base/sysinfo.cc
===================================================================
--- third_party/tcmalloc/chromium/src/base/sysinfo.cc (revision 87277)
+++ third_party/tcmalloc/chromium/src/base/sysinfo.cc (working copy)
@@ -56,6 +56,7 @@
#endif
#include "base/sysinfo.h"
#include "base/commandlineflags.h"
+#include "base/dynamic_annotations.h" // for RunningOnValgrind
#include "base/logging.h"
#include "base/cycleclock.h"
@@ -110,20 +111,23 @@
// 8K), so it's not an ideal solution.
const char* GetenvBeforeMain(const char* name) {
#if defined(HAVE___ENVIRON) // if we have it, it's declared in unistd.h
- const int namelen = strlen(name);
- for (char** p = __environ; *p; p++) {
- if (!memcmp(*p, name, namelen) && (*p)[namelen] == '=') // it's a match
- return *p + namelen+1; // point after =
+ if (__environ) { // can exist but be NULL, if statically linked
+ const int namelen = strlen(name);
+ for (char** p = __environ; *p; p++) {
+ if (!memcmp(*p, name, namelen) && (*p)[namelen] == '=') // it's a match
+ return *p + namelen+1; // point after =
+ }
+ return NULL;
}
- return NULL;
-#elif defined(PLATFORM_WINDOWS)
+#endif
+#if defined(PLATFORM_WINDOWS)
// TODO(mbelshe) - repeated calls to this function will overwrite the
// contents of the static buffer.
- static char envbuf[1024]; // enough to hold any envvar we care about
- if (!GetEnvironmentVariableA(name, envbuf, sizeof(envbuf)-1))
+ static char envvar_buf[1024]; // enough to hold any envvar we care about
+ if (!GetEnvironmentVariableA(name, envvar_buf, sizeof(envvar_buf)-1))
return NULL;
- return envbuf;
-#else
+ return envvar_buf;
+#endif
// static is ok because this function should only be called before
// main(), when we're single-threaded.
static char envbuf[16<<10];
@@ -151,7 +155,6 @@
p = endp + 1;
}
return NULL; // env var never found
-#endif
}
// This takes as an argument an environment-variable name (like
@@ -206,7 +209,7 @@
static double cpuinfo_cycles_per_second = 1.0; // 0.0 might be dangerous
static int cpuinfo_num_cpus = 1; // Conservative guess
-static void SleepForMilliseconds(int milliseconds) {
+void SleepForMilliseconds(int milliseconds) {
#ifdef PLATFORM_WINDOWS
_sleep(milliseconds); // Windows's _sleep takes milliseconds argument
#else
@@ -233,6 +236,29 @@
return guess;
}
+// ReadIntFromFile is only called on linux and cygwin platforms.
+#if defined(__linux__) || defined(__CYGWIN__) || defined(__CYGWIN32__)
+// Helper function for reading an int from a file. Returns true if successful
+// and the memory location pointed to by value is set to the value read.
+static bool ReadIntFromFile(const char *file, int *value) {
+ bool ret = false;
+ int fd = open(file, O_RDONLY);
+ if (fd != -1) {
+ char line[1024];
+ char* err;
+ memset(line, '\0', sizeof(line));
+ read(fd, line, sizeof(line) - 1);
+ const int temp_value = strtol(line, &err, 10);
+ if (line[0] != '\0' && (*err == '\n' || *err == '\0')) {
+ *value = temp_value;
+ ret = true;
+ }
+ close(fd);
+ }
+ return ret;
+}
+#endif
+
// WARNING: logging calls back to InitializeSystemInfo() so it must
// not invoke any logging code. Also, InitializeSystemInfo() can be
// called before main() -- in fact it *must* be since already_called
@@ -245,31 +271,44 @@
if (already_called) return;
already_called = true;
- // I put in a never-called reference to EstimateCyclesPerSecond() here
- // to silence the compiler for OS's that don't need it
- if (0) EstimateCyclesPerSecond(0);
+ bool saw_mhz = false;
+ if (RunningOnValgrind()) {
+ // Valgrind may slow the progress of time artificially (--scale-time=N
+ // option). We thus can't rely on CPU Mhz info stored in /sys or /proc
+ // files. Thus, actually measure the cps.
+ cpuinfo_cycles_per_second = EstimateCyclesPerSecond(100);
+ saw_mhz = true;
+ }
+
#if defined(__linux__) || defined(__CYGWIN__) || defined(__CYGWIN32__)
char line[1024];
char* err;
+ int freq;
+ // If the kernel is exporting the tsc frequency use that. There are issues
+ // where cpuinfo_max_freq cannot be relied on because the BIOS may be
+ // exporintg an invalid p-state (on x86) or p-states may be used to put the
+ // processor in a new mode (turbo mode). Essentially, those frequencies
+ // cannot always be relied upon. The same reasons apply to /proc/cpuinfo as
+ // well.
+ if (!saw_mhz &&
+ ReadIntFromFile("/sys/devices/system/cpu/cpu0/tsc_freq_khz", &freq)) {
+ // The value is in kHz (as the file name suggests). For example, on a
+ // 2GHz warpstation, the file contains the value "2000000".
+ cpuinfo_cycles_per_second = freq * 1000.0;
+ saw_mhz = true;
+ }
+
// If CPU scaling is in effect, we want to use the *maximum* frequency,
// not whatever CPU speed some random processor happens to be using now.
- bool saw_mhz = false;
- const char* pname0 = "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq";
- int fd0 = open(pname0, O_RDONLY);
- if (fd0 != -1) {
- memset(line, '\0', sizeof(line));
- read(fd0, line, sizeof(line));
- const int max_freq = strtol(line, &err, 10);
- if (line[0] != '\0' && (*err == '\n' || *err == '\0')) {
- // The value is in kHz. For example, on a 2GHz machine, the file
- // contains the value "2000000". Historically this file contained no
- // newline, but at some point the kernel started appending a newline.
- cpuinfo_cycles_per_second = max_freq * 1000.0;
- saw_mhz = true;
- }
- close(fd0);
+ if (!saw_mhz &&
+ ReadIntFromFile("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq",
+ &freq)) {
+ // The value is in kHz. For example, on a 2GHz machine, the file
+ // contains the value "2000000".
+ cpuinfo_cycles_per_second = freq * 1000.0;
+ saw_mhz = true;
}
// Read /proc/cpuinfo for other values, and if there is no cpuinfo_max_freq.
@@ -277,11 +316,14 @@
int fd = open(pname, O_RDONLY);
if (fd == -1) {
perror(pname);
- cpuinfo_cycles_per_second = EstimateCyclesPerSecond(1000);
+ if (!saw_mhz) {
+ cpuinfo_cycles_per_second = EstimateCyclesPerSecond(1000);
+ }
return; // TODO: use generic tester instead?
}
double bogo_clock = 1.0;
+ bool saw_bogo = false;
int num_cpus = 0;
line[0] = line[1] = '\0';
int chars_read = 0;
@@ -305,29 +347,38 @@
if (newline != NULL)
*newline = '\0';
- if (!saw_mhz && strncmp(line, "cpu MHz", sizeof("cpu MHz")-1) == 0) {
+ // When parsing the "cpu MHz" and "bogomips" (fallback) entries, we only
+ // accept postive values. Some environments (virtual machines) report zero,
+ // which would cause infinite looping in WallTime_Init.
+ if (!saw_mhz && strncasecmp(line, "cpu MHz", sizeof("cpu MHz")-1) == 0) {
const char* freqstr = strchr(line, ':');
if (freqstr) {
cpuinfo_cycles_per_second = strtod(freqstr+1, &err) * 1000000.0;
- if (freqstr[1] != '\0' && *err == '\0')
+ if (freqstr[1] != '\0' && *err == '\0' && cpuinfo_cycles_per_second > 0)
saw_mhz = true;
}
- } else if (strncmp(line, "bogomips", sizeof("bogomips")-1) == 0) {
+ } else if (strncasecmp(line, "bogomips", sizeof("bogomips")-1) == 0) {
const char* freqstr = strchr(line, ':');
- if (freqstr)
+ if (freqstr) {
bogo_clock = strtod(freqstr+1, &err) * 1000000.0;
- if (freqstr == NULL || freqstr[1] == '\0' || *err != '\0')
- bogo_clock = 1.0;
- } else if (strncmp(line, "processor", sizeof("processor")-1) == 0) {
+ if (freqstr[1] != '\0' && *err == '\0' && bogo_clock > 0)
+ saw_bogo = true;
+ }
+ } else if (strncasecmp(line, "processor", sizeof("processor")-1) == 0) {
num_cpus++; // count up every time we see an "processor :" entry
}
} while (chars_read > 0);
close(fd);
if (!saw_mhz) {
- // If we didn't find anything better, we'll use bogomips, but
- // we're not happy about it.
- cpuinfo_cycles_per_second = bogo_clock;
+ if (saw_bogo) {
+ // If we didn't find anything better, we'll use bogomips, but
+ // we're not happy about it.
+ cpuinfo_cycles_per_second = bogo_clock;
+ } else {
+ // If we don't even have bogomips, we'll use the slow estimation.
+ cpuinfo_cycles_per_second = EstimateCyclesPerSecond(1000);
+ }
}
if (cpuinfo_cycles_per_second == 0.0) {
cpuinfo_cycles_per_second = 1.0; // maybe unnecessary, but safe
@@ -458,7 +509,7 @@
char* buf, int buf_size) {
CHECK_LT(snprintf(buf, buf_size,
spec,
- pid ? pid : getpid()), buf_size);
+ static_cast<int>(pid ? pid : getpid())), buf_size);
}
#endif
@@ -771,7 +822,8 @@
Buffer::kBufSize);
} else {
CHECK_LT(snprintf(object_path.buf_, Buffer::kBufSize,
- "/proc/%d/path/%s", pid_, mapinfo->pr_mapname),
+ "/proc/%d/path/%s",
+ static_cast<int>(pid_), mapinfo->pr_mapname),
Buffer::kBufSize);
}
ssize_t len = readlink(object_path.buf_, current_filename_, PATH_MAX);
@@ -882,9 +934,10 @@
// Helper to add the list of mapped shared libraries to a profile.
// Fill formatted "/proc/self/maps" contents into buffer 'buf' of size 'size'
-// and return the actual size occupied in 'buf'.
+// and return the actual size occupied in 'buf'. We fill wrote_all to true
+// if we successfully wrote all proc lines to buf, false else.
// We do not provision for 0-terminating 'buf'.
-int FillProcSelfMaps(char buf[], int size) {
+int FillProcSelfMaps(char buf[], int size, bool* wrote_all) {
ProcMapsIterator::Buffer iterbuf;
ProcMapsIterator it(0, &iterbuf); // 0 means "current pid"
@@ -892,10 +945,17 @@
int64 inode;
char *flags, *filename;
int bytes_written = 0;
+ *wrote_all = true;
while (it.Next(&start, &end, &flags, &offset, &inode, &filename)) {
- bytes_written += it.FormatLine(buf + bytes_written, size - bytes_written,
- start, end, flags, offset, inode, filename,
- 0);
+ const int line_length = it.FormatLine(buf + bytes_written,
+ size - bytes_written,
+ start, end, flags, offset,
+ inode, filename, 0);
+ if (line_length == 0)
+ *wrote_all = false; // failed to write this line out
+ else
+ bytes_written += line_length;
+
}
return bytes_written;
}

Powered by Google App Engine
This is Rietveld 408576698