[compiler-rt] r342584 - [sanitizer][fuchsia] Fix VMAR leak

Kostya Kortchinsky via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 19 12:50:35 PDT 2018


Author: cryptoad
Date: Wed Sep 19 12:50:35 2018
New Revision: 342584

URL: http://llvm.org/viewvc/llvm-project?rev=342584&view=rev
Log:
[sanitizer][fuchsia] Fix VMAR leak

Summary:
Destroy and close a range's vmar if all its memory was unmapped.

This addresses some performance regression due to the proliferation of vmars
when Secondary backed allocations are concerned with Scudo on Fuchsia.

When a Secondary backed allocation was freed, the associated
`ReservedAddressRange` was going away after unmapping the entirety of the
mapping, but without getting rid of the associated vmar properly (which
was created specifically for that mapping). This resulted in an increase of
defunct vmars, that in turn slowed down further new vmar allocations.

This appears to solve ZX-2560/ZX-2642, at least on QEMU.

Reviewers: flowerhack, mcgrathr, phosek, mseaborn

Reviewed By: mcgrathr

Subscribers: kubamracek, delcypher, #sanitizers, llvm-commits

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

Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_fuchsia.cc

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_fuchsia.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_fuchsia.cc?rev=342584&r1=342583&r2=342584&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_fuchsia.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_fuchsia.cc Wed Sep 19 12:50:35 2018
@@ -277,14 +277,22 @@ void UnmapOrDieVmar(void *addr, uptr siz
 
 void ReservedAddressRange::Unmap(uptr addr, uptr size) {
   CHECK_LE(size, size_);
-  if (addr == reinterpret_cast<uptr>(base_))
-    // If we unmap the whole range, just null out the base.
-    base_ = (size == size_) ? nullptr : reinterpret_cast<void*>(addr + size);
-  else
+  const zx_handle_t vmar = static_cast<zx_handle_t>(os_handle_);
+  if (addr == reinterpret_cast<uptr>(base_)) {
+    if (size == size_) {
+      // Destroying the vmar effectively unmaps the whole mapping.
+      _zx_vmar_destroy(vmar);
+      _zx_handle_close(vmar);
+      os_handle_ = static_cast<uptr>(ZX_HANDLE_INVALID);
+      DecreaseTotalMmap(size);
+      return;
+    }
+  } else {
     CHECK_EQ(addr + size, reinterpret_cast<uptr>(base_) + size_);
-  size_ -= size;
-  UnmapOrDieVmar(reinterpret_cast<void *>(addr), size,
-                 static_cast<zx_handle_t>(os_handle_));
+  }
+  // Partial unmapping does not affect the fact that the initial range is still
+  // reserved, and the resulting unmapped memory can't be reused.
+  UnmapOrDieVmar(reinterpret_cast<void *>(addr), size, vmar);
 }
 
 // This should never be called.




More information about the llvm-commits mailing list