[compiler-rt] r338228 - [XRay][compiler-rt] FDR Mode: Use mmap instead of internal allocator

Dean Michael Berris via llvm-commits llvm-commits at lists.llvm.org
Sun Jul 29 22:56:42 PDT 2018


Author: dberris
Date: Sun Jul 29 22:56:42 2018
New Revision: 338228

URL: http://llvm.org/viewvc/llvm-project?rev=338228&view=rev
Log:
[XRay][compiler-rt] FDR Mode: Use mmap instead of internal allocator

Summary:
This change moves FDR mode to use `internal_mmap(...)` from
sanitizer_common instead of the internal allocator interface. We're
doing this to sidestep the alignment issues we encounter with the
`InternalAlloc(...)` functions returning pointers that have some magic
bytes at the beginning.

XRay copies bytes into the buffer memory, and does not require the magic
bytes tracking the other sanitizers use when allocating/deallocating
buffers.

Reviewers: kpw, eizan

Subscribers: llvm-commits

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

Modified:
    compiler-rt/trunk/lib/xray/xray_buffer_queue.cc

Modified: compiler-rt/trunk/lib/xray/xray_buffer_queue.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/xray/xray_buffer_queue.cc?rev=338228&r1=338227&r2=338228&view=diff
==============================================================================
--- compiler-rt/trunk/lib/xray/xray_buffer_queue.cc (original)
+++ compiler-rt/trunk/lib/xray/xray_buffer_queue.cc Sun Jul 29 22:56:42 2018
@@ -13,17 +13,50 @@
 //
 //===----------------------------------------------------------------------===//
 #include "xray_buffer_queue.h"
-#include "sanitizer_common/sanitizer_allocator_internal.h"
 #include "sanitizer_common/sanitizer_common.h"
 #include "sanitizer_common/sanitizer_libc.h"
+#include "sanitizer_common/sanitizer_posix.h"
 #include <memory>
+#include <sys/mman.h>
+
+#ifndef MAP_NORESERVE
+// no-op on NetBSD (at least), unsupported flag on FreeBSD
+#define MAP_NORESERVE 0
+#endif
 
 using namespace __xray;
 using namespace __sanitizer;
 
+template <class T> static T *allocRaw(size_t N) {
+  // TODO: Report errors?
+  // We use MAP_NORESERVE on platforms where it's supported to ensure that the
+  // pages we're allocating for XRay never end up in pages that can be swapped
+  // in/out. We're doing this because for FDR mode, we want to ensure that
+  // writes to the buffers stay resident in memory to prevent XRay itself from
+  // causing swapping/thrashing.
+  //
+  // In the case when XRay pages cannot be swapped in/out or there's not enough
+  // RAM to back these pages, we're willing to cause a segmentation fault
+  // instead of introducing latency in the measurement. We assume here that
+  // there are enough pages that are swappable in/out outside of the buffers
+  // being used by FDR mode (which are bounded and configurable anyway) to allow
+  // us to keep using always-resident memory.
+  //
+  // TODO: Make this configurable?
+  void *A = reinterpret_cast<void *>(
+      internal_mmap(NULL, N * sizeof(T), PROT_WRITE | PROT_READ,
+                    MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0));
+  return (A == MAP_FAILED) ? nullptr : reinterpret_cast<T *>(A);
+}
+
+template <class T> static void deallocRaw(T *ptr, size_t N) {
+  // TODO: Report errors?
+  if (ptr != nullptr)
+    internal_munmap(ptr, N);
+}
+
 template <class T> static T *initArray(size_t N) {
-  auto A = reinterpret_cast<T *>(
-      InternalAlloc(N * sizeof(T), nullptr, kCacheLineSize));
+  auto A = allocRaw<T>(N);
   if (A != nullptr)
     while (N > 0)
       new (A + (--N)) T();
@@ -42,19 +75,19 @@ BufferQueue::BufferQueue(size_t B, size_
     // Clean up the buffers we've already allocated.
     for (auto B = Buffers, E = Buffers + BufferCount; B != E; ++B)
       B->~BufferRep();
-    InternalFree(Buffers);
+    deallocRaw(Buffers, N);
     Success = false;
     return;
   };
 
   for (size_t i = 0; i < N; ++i) {
     auto &T = Buffers[i];
-    void *Tmp = InternalAlloc(BufferSize, nullptr, 64);
+    void *Tmp = allocRaw<char>(BufferSize);
     if (Tmp == nullptr) {
       Success = false;
       return;
     }
-    void *Extents = InternalAlloc(sizeof(BufferExtents), nullptr, 64);
+    auto *Extents = allocRaw<BufferExtents>(1);
     if (Extents == nullptr) {
       Success = false;
       return;
@@ -62,7 +95,7 @@ BufferQueue::BufferQueue(size_t B, size_
     auto &Buf = T.Buff;
     Buf.Data = Tmp;
     Buf.Size = B;
-    Buf.Extents = reinterpret_cast<BufferExtents *>(Extents);
+    Buf.Extents = Extents;
     OwnedBuffers[i] = Tmp;
   }
   Success = true;
@@ -128,11 +161,11 @@ BufferQueue::~BufferQueue() {
   for (auto I = Buffers, E = Buffers + BufferCount; I != E; ++I) {
     auto &T = *I;
     auto &Buf = T.Buff;
-    InternalFree(Buf.Data);
-    InternalFree(Buf.Extents);
+    deallocRaw(Buf.Data, Buf.Size);
+    deallocRaw(Buf.Extents, 1);
   }
   for (auto B = Buffers, E = Buffers + BufferCount; B != E; ++B)
     B->~BufferRep();
-  InternalFree(Buffers);
-  InternalFree(OwnedBuffers);
+  deallocRaw(Buffers, BufferCount);
+  deallocRaw(OwnedBuffers, BufferCount);
 }




More information about the llvm-commits mailing list