<div dir="ltr">Can we have a (unit) test for that?</div><div class="gmail_extra"><br><br><div class="gmail_quote">On Tue, Sep 3, 2013 at 3:09 PM, Alexander Potapenko <span dir="ltr"><<a href="mailto:glider@google.com" target="_blank">glider@google.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: glider<br>
Date: Tue Sep  3 06:09:16 2013<br>
New Revision: 189789<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=189789&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=189789&view=rev</a><br>
Log:<br>
[TSan] Move the /proc/self/maps parsing logic to sanitizer_common<br>
<br>
Provide a generic way for the tools to generate memory profiles from contents of /proc/self/maps<br>
<br>
<br>
Modified:<br>
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc<br>
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps.h<br>
    compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc<br>
<br>
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc?rev=189789&r1=189788&r2=189789&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc?rev=189789&r1=189788&r2=189789&view=diff</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc (original)<br>
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc Tue Sep  3 06:09:16 2013<br>
@@ -403,6 +403,30 @@ static bool IsDecimal(char c) {<br>
   return c >= '0' && c <= '9';<br>
 }<br>
<br>
+static bool IsHex(char c) {<br>
+  return (c >= '0' && c <= '9')<br>
+      || (c >= 'a' && c <= 'f');<br>
+}<br>
+<br>
+static uptr ReadHex(const char *p) {<br>
+  uptr v = 0;<br>
+  for (; IsHex(p[0]); p++) {<br>
+    if (p[0] >= '0' && p[0] <= '9')<br>
+      v = v * 16 + p[0] - '0';<br>
+    else<br>
+      v = v * 16 + p[0] - 'a' + 10;<br>
+  }<br>
+  return v;<br>
+}<br>
+<br>
+static uptr ReadDecimal(const char *p) {<br>
+  uptr v = 0;<br>
+  for (; IsDecimal(p[0]); p++)<br>
+    v = v * 10 + p[0] - '0';<br>
+  return v;<br>
+}<br>
+<br>
+<br>
 bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,<br>
                                char filename[], uptr filename_size,<br>
                                uptr *protection) {<br>
@@ -473,6 +497,30 @@ bool MemoryMappingLayout::GetObjectNameA<br>
                                        protection);<br>
 }<br>
<br>
+void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size) {<br>
+  char *smaps = 0;<br>
+  uptr smaps_cap = 0;<br>
+  uptr smaps_len = ReadFileToBuffer("/proc/self/smaps",<br>
+      &smaps, &smaps_cap, 64<<20);<br>
+  uptr total = 0;<br>
+  uptr start = 0;<br>
+  bool file = false;<br>
+  const char *pos = smaps;<br>
+  while (pos < smaps + smaps_len) {<br>
+    if (IsHex(pos[0])) {<br>
+      start = ReadHex(pos);<br>
+      for (; *pos != '/' && *pos > '\n'; pos++) {}<br>
+      file = *pos == '/';<br>
+    } else if (internal_strncmp(pos, "Rss:", 4) == 0) {<br>
+      for (; *pos < '0' || *pos > '9'; pos++) {}<br>
+      uptr rss = ReadDecimal(pos) * 1024;<br>
+      cb(start, rss, file, stats, stats_size);<br>
+    }<br>
+    while (*pos++ != '\n') {}<br>
+  }<br>
+  UnmapOrDie(smaps, smaps_cap);<br>
+}<br>
+<br>
 enum MutexState {<br>
   MtxUnlocked = 0,<br>
   MtxLocked = 1,<br>
<br>
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps.h?rev=189789&r1=189788&r2=189789&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps.h?rev=189789&r1=189788&r2=189789&view=diff</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps.h (original)<br>
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps.h Tue Sep  3 06:09:16 2013<br>
@@ -32,7 +32,7 @@ class MemoryMappingLayout {<br>
   }<br>
 };<br>
<br>
-#else  // _WIN32<br>
+#else  // SANITIZER_WINDOWS<br>
 #if SANITIZER_LINUX<br>
 struct ProcSelfMapsBuff {<br>
   char *data;<br>
@@ -118,7 +118,15 @@ class MemoryMappingLayout {<br>
 # endif<br>
 };<br>
<br>
-#endif  // _WIN32<br>
+typedef void (*fill_profile_f)(uptr start, uptr rss, bool file,<br>
+                               /*out*/uptr *stats, uptr stats_size);<br>
+<br>
+// Parse the contents of /proc/self/smaps and generate a memory profile.<br>
+// |cb| is a tool-specific callback that fills the |stats| array containing<br>
+// |stats_size| elements.<br>
+void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size);<br>
+<br>
+#endif  // SANITIZER_WINDOWS<br>
<br>
 }  // namespace __sanitizer<br>
<br>
<br>
Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc?rev=189789&r1=189788&r2=189789&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc?rev=189789&r1=189788&r2=189789&view=diff</a><br>

==============================================================================<br>
--- compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc (original)<br>
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc Tue Sep  3 06:09:16 2013<br>
@@ -72,70 +72,33 @@ ScopedInRtl::~ScopedInRtl() {<br>
 }<br>
 #endif<br>
<br>
-static bool ishex(char c) {<br>
-  return (c >= '0' && c <= '9')<br>
-      || (c >= 'a' && c <= 'f');<br>
-}<br>
-<br>
-static uptr readhex(const char *p) {<br>
-  uptr v = 0;<br>
-  for (; ishex(p[0]); p++) {<br>
-    if (p[0] >= '0' && p[0] <= '9')<br>
-      v = v * 16 + p[0] - '0';<br>
-    else<br>
-      v = v * 16 + p[0] - 'a' + 10;<br>
-  }<br>
-  return v;<br>
-}<br>
-<br>
-static uptr readdec(const char *p) {<br>
-  uptr v = 0;<br>
-  for (; p[0] >= '0' && p[0] <= '9' ; p++)<br>
-    v = v * 10 + p[0] - '0';<br>
-  return v;<br>
+void FillProfileCallback(uptr start, uptr rss, bool file,<br>
+                         uptr *mem, uptr stats_size) {<br>
+  CHECK_EQ(7, stats_size);<br>
+  mem[6] += rss;  // total<br>
+  start >>= 40;<br>
+  if (start < 0x10)  // shadow<br>
+    mem[0] += rss;<br>
+  else if (start >= 0x20 && start < 0x30)  // compat modules<br>
+    mem[file ? 1 : 2] += rss;<br>
+  else if (start >= 0x7e)  // modules<br>
+    mem[file ? 1 : 2] += rss;<br>
+  else if (start >= 0x60 && start < 0x62)  // traces<br>
+    mem[3] += rss;<br>
+  else if (start >= 0x7d && start < 0x7e)  // heap<br>
+    mem[4] += rss;<br>
+  else  // other<br>
+    mem[5] += rss;<br>
 }<br>
<br>
 void WriteMemoryProfile(char *buf, uptr buf_size) {<br>
-  char *smaps = 0;<br>
-  uptr smaps_cap = 0;<br>
-  uptr smaps_len = ReadFileToBuffer("/proc/self/smaps",<br>
-      &smaps, &smaps_cap, 64<<20);<br>
-  uptr mem[6] = {};<br>
-  uptr total = 0;<br>
-  uptr start = 0;<br>
-  bool file = false;<br>
-  const char *pos = smaps;<br>
-  while (pos < smaps + smaps_len) {<br>
-    if (ishex(pos[0])) {<br>
-      start = readhex(pos);<br>
-      for (; *pos != '/' && *pos > '\n'; pos++) {}<br>
-      file = *pos == '/';<br>
-    } else if (internal_strncmp(pos, "Rss:", 4) == 0) {<br>
-      for (; *pos < '0' || *pos > '9'; pos++) {}<br>
-      uptr rss = readdec(pos) * 1024;<br>
-      total += rss;<br>
-      start >>= 40;<br>
-      if (start < 0x10)  // shadow<br>
-        mem[0] += rss;<br>
-      else if (start >= 0x20 && start < 0x30)  // compat modules<br>
-        mem[file ? 1 : 2] += rss;<br>
-      else if (start >= 0x7e)  // modules<br>
-        mem[file ? 1 : 2] += rss;<br>
-      else if (start >= 0x60 && start < 0x62)  // traces<br>
-        mem[3] += rss;<br>
-      else if (start >= 0x7d && start < 0x7e)  // heap<br>
-        mem[4] += rss;<br>
-      else  // other<br>
-        mem[5] += rss;<br>
-    }<br>
-    while (*pos++ != '\n') {}<br>
-  }<br>
-  UnmapOrDie(smaps, smaps_cap);<br>
+  uptr mem[7] = {};<br>
+  __sanitizer::GetMemoryProfile(FillProfileCallback, mem, 7);<br>
   char *buf_pos = buf;<br>
   char *buf_end = buf + buf_size;<br>
   buf_pos += internal_snprintf(buf_pos, buf_end - buf_pos,<br>
       "RSS %zd MB: shadow:%zd file:%zd mmap:%zd trace:%zd heap:%zd other:%zd\n",<br>
-      total >> 20, mem[0] >> 20, mem[1] >> 20, mem[2] >> 20,<br>
+      mem[6] >> 20, mem[0] >> 20, mem[1] >> 20, mem[2] >> 20,<br>
       mem[3] >> 20, mem[4] >> 20, mem[5] >> 20);<br>
   struct mallinfo mi = __libc_mallinfo();<br>
   buf_pos += internal_snprintf(buf_pos, buf_end - buf_pos,<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br><br clear="all"><div><br></div>-- <br><div>Alexey Samsonov, MSK</div>
</div>