scudo-standalone: Add GetRSS method on Linux
authorBastian Kersting <bkersting@google.com>
Thu, 8 Dec 2022 20:22:42 +0000 (12:22 -0800)
committerVitaly Buka <vitalybuka@google.com>
Thu, 8 Dec 2022 21:38:24 +0000 (13:38 -0800)
This change adds a GetRSS method on Linux that parses
the number from /proc/self/statm. This change is part
of splitting up https://reviews.llvm.org/D126752.

Reviewed By: vitalybuka, cryptoad

Differential Revision: https://reviews.llvm.org/D139430

compiler-rt/lib/scudo/standalone/common.cpp
compiler-rt/lib/scudo/standalone/common.h
compiler-rt/lib/scudo/standalone/linux.cpp
compiler-rt/lib/scudo/standalone/tests/common_test.cpp

index 666f954..67fd238 100644 (file)
@@ -35,4 +35,8 @@ void NORETURN dieOnMapUnmapError(uptr SizeIfOOM) {
   die();
 }
 
+#if !SCUDO_LINUX
+u64 GetRSS() { return 0; }
+#endif
+
 } // namespace scudo
index bc3dfec..3d70bad 100644 (file)
@@ -132,6 +132,8 @@ u32 getNumberOfCPUs();
 
 const char *getEnv(const char *Name);
 
+u64 GetRSS();
+
 u64 getMonotonicTime();
 
 u32 getThreadID();
index c77c1bb..4966b49 100644 (file)
@@ -19,6 +19,7 @@
 #include <fcntl.h>
 #include <linux/futex.h>
 #include <sched.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/mman.h>
@@ -180,6 +181,36 @@ bool getRandom(void *Buffer, uptr Length, UNUSED bool Blocking) {
 extern "C" WEAK int async_safe_write_log(int pri, const char *tag,
                                          const char *msg);
 
+static u64 GetRSSFromBuffer(const char *Buf) {
+  // The format of the file is:
+  // 1084 89 69 11 0 79 0
+  // We need the second number which is RSS in pages.
+  const char *Pos = Buf;
+  // Skip the first number.
+  while (*Pos >= '0' && *Pos <= '9')
+    Pos++;
+  // Skip whitespaces.
+  while (!(*Pos >= '0' && *Pos <= '9') && *Pos != 0)
+    Pos++;
+  // Read the number.
+  u64 Rss = 0;
+  for (; *Pos >= '0' && *Pos <= '9'; Pos++)
+    Rss = Rss * 10 + static_cast<u64>(*Pos) - '0';
+  return Rss * getPageSizeCached();
+}
+
+u64 GetRSS() {
+  auto Fd = open("/proc/self/statm", O_RDONLY);
+  char Buf[64];
+  s64 Len = read(Fd, Buf, sizeof(Buf) - 1);
+  close(Fd);
+  if (Len <= 0)
+    return 0;
+  Buf[Len] = 0;
+
+  return GetRSSFromBuffer(Buf);
+}
+
 void outputRaw(const char *Buffer) {
   if (&async_safe_write_log) {
     constexpr s32 AndroidLogInfo = 4;
index 711e3b2..e459c7b 100644 (file)
@@ -69,4 +69,23 @@ TEST(ScudoCommonTest, Zeros) {
   unmap(P, Size, 0, &Data);
 }
 
+#if SCUDO_LINUX
+TEST(ScudoCommonTest, GetRssFromBuffer) {
+  constexpr size_t AllocSize = 10000000;
+  constexpr u64 Error = 3000000;
+  constexpr size_t Runs = 10;
+
+  u64 Rss = scudo::GetRSS();
+  EXPECT_GT(Rss, 0);
+
+  std::vector<std::unique_ptr<char[]>> Allocs(Runs);
+  for (auto &Alloc : Allocs) {
+    Alloc.reset(new char[AllocSize]());
+    u64 Prev = Rss;
+    Rss = scudo::GetRSS();
+    EXPECT_LE(std::abs(static_cast<int64_t>(Rss - AllocSize - Prev)), Error);
+  }
+}
+#endif // SCUDO_LINUX
+
 } // namespace scudo