[sanitizer][fuchsia] Implement ReleaseMemoryPagesToOS

The `zx_vmar_op_range` allows us to decommit memory pages without
needing a handle to the underlying vmo, as long as we have a handle to
a vmar that contains this mapping. This allows us to implement the
`ReleaseMemoryPagesToOS` function by decommitting the memory using a
handle to the root vmar.

Reviewed By: mcgrathr

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

GitOrigin-RevId: 98c21ae7a8ec587febc899753b63054ae9aea9d6
diff --git a/lib/sanitizer_common/sanitizer_fuchsia.cpp b/lib/sanitizer_common/sanitizer_fuchsia.cpp
index 5ad20d0..e721788 100644
--- a/lib/sanitizer_common/sanitizer_fuchsia.cpp
+++ b/lib/sanitizer_common/sanitizer_fuchsia.cpp
@@ -381,9 +381,18 @@
   UnmapOrDieVmar(addr, size, _zx_vmar_root_self());
 }
 
-// This is used on the shadow mapping, which cannot be changed.
-// Zircon doesn't have anything like MADV_DONTNEED.
-void ReleaseMemoryPagesToOS(uptr beg, uptr end) {}
+void ReleaseMemoryPagesToOS(uptr beg, uptr end) {
+  uptr beg_aligned = RoundUpTo(beg, PAGE_SIZE);
+  uptr end_aligned = RoundDownTo(end, PAGE_SIZE);
+  if (beg_aligned < end_aligned) {
+    zx_handle_t root_vmar = _zx_vmar_root_self();
+    CHECK_NE(root_vmar, ZX_HANDLE_INVALID);
+    zx_status_t status =
+        _zx_vmar_op_range(root_vmar, ZX_VMAR_OP_DECOMMIT, beg_aligned,
+                          end_aligned - beg_aligned, nullptr, 0);
+    CHECK_EQ(status, ZX_OK);
+  }
+}
 
 void DumpProcessMap() {
   // TODO(mcgrathr): write it