Index: runtime/vm/virtual_memory_fuchsia.cc |
diff --git a/runtime/vm/virtual_memory_fuchsia.cc b/runtime/vm/virtual_memory_fuchsia.cc |
index bfbac54b2b2738181611f6e3d25fb0bb19660868..0e627ecc81026f061c2450b3a2f54f57dac0ea5c 100644 |
--- a/runtime/vm/virtual_memory_fuchsia.cc |
+++ b/runtime/vm/virtual_memory_fuchsia.cc |
@@ -7,13 +7,27 @@ |
#include "vm/virtual_memory.h" |
+#include <magenta/status.h> |
#include <magenta/syscalls.h> |
-#include <unistd.h> // NOLINT |
+#include <sys/mman.h> |
+#include <unistd.h> |
#include "platform/assert.h" |
+#include "vm/isolate.h" |
#include "vm/memory_region.h" |
#include "vm/os.h" |
+// #define VIRTUAL_MEMORY_LOGGING 1 |
+#if defined(VIRTUAL_MEMORY_LOGGING) |
+#define LOG_ERR(msg, ...) \ |
+ OS::PrintErr("VMVM: %s:%d: " msg, __FILE__, __LINE__, ##__VA_ARGS__) |
+#define LOG_INFO(msg, ...) \ |
+ OS::Print("VMVM: %s:%d: " msg, __FILE__, __LINE__, ##__VA_ARGS__) |
+#else |
+#define LOG_ERR(msg, ...) |
+#define LOG_INFO(msg, ...) |
+#endif // defined(VIRTUAL_MEMORY_LOGGING) |
+ |
namespace dart { |
uword VirtualMemory::page_size_ = 0; |
@@ -25,65 +39,86 @@ void VirtualMemory::InitOnce() { |
VirtualMemory* VirtualMemory::ReserveInternal(intptr_t size) { |
- mx_handle_t vmo = MX_HANDLE_INVALID; |
- mx_status_t status = mx_vmo_create(size, 0u, &vmo); |
+ mx_handle_t vmar = MX_HANDLE_INVALID; |
+ uword addr = 0; |
+ const uint32_t flags = MX_VM_FLAG_COMPACT | MX_VM_FLAG_CAN_MAP_SPECIFIC | |
+ MX_VM_FLAG_CAN_MAP_READ | MX_VM_FLAG_CAN_MAP_WRITE | |
+ MX_VM_FLAG_CAN_MAP_EXECUTE; |
+ mx_status_t status = |
+ mx_vmar_allocate(mx_vmar_root_self(), 0, size, flags, &vmar, &addr); |
if (status != NO_ERROR) { |
- return NULL; |
- } |
- |
- // TODO(zra): map with PERM_NONE, when that works, and relax with |
- // Commit and Protect when they are implemented. |
- // Issue MG-161. |
- const int prot = |
- MX_VM_FLAG_PERM_READ | MX_VM_FLAG_PERM_WRITE | MX_VM_FLAG_PERM_EXECUTE; |
- uintptr_t addr; |
- status = mx_vmar_map(mx_vmar_root_self(), 0, vmo, 0, size, prot, &addr); |
- if (status != NO_ERROR) { |
- mx_handle_close(vmo); |
- FATAL("VirtualMemory::ReserveInternal FAILED"); |
+ LOG_ERR("mx_vmar_allocate(size = %ld) failed: %s\n", size, |
+ mx_status_get_string(status)); |
return NULL; |
} |
MemoryRegion region(reinterpret_cast<void*>(addr), size); |
- return new VirtualMemory(region, vmo); |
+ return new VirtualMemory(region, vmar); |
} |
VirtualMemory::~VirtualMemory() { |
if (!embedder_allocated()) { |
- // TODO(zra): Use reserved_size_. |
- // Issue MG-162. |
- uintptr_t addr = reinterpret_cast<uintptr_t>(address()); |
- mx_status_t status = |
- mx_vmar_unmap(mx_vmar_root_self(), addr, 0 /*reserved_size_*/); |
+ mx_handle_t vmar = static_cast<mx_handle_t>(handle()); |
+ mx_status_t status = mx_vmar_destroy(vmar); |
if (status != NO_ERROR) { |
- FATAL("VirtualMemory::~VirtualMemory: unamp FAILED"); |
+ LOG_ERR("mx_vmar_destroy failed: %s\n", mx_status_get_string(status)); |
} |
- |
- status = mx_handle_close(handle()); |
+ status = mx_handle_close(vmar); |
if (status != NO_ERROR) { |
- FATAL("VirtualMemory::~VirtualMemory: handle_close FAILED"); |
+ LOG_ERR("mx_handle_close failed: %s\n", mx_status_get_string(status)); |
} |
} |
} |
-bool VirtualMemory::FreeSubSegment(void* address, intptr_t size) { |
- // TODO(zra): It should be possible to free a subsegment after |
- // Issue MG-162 is addressed. |
- return false; |
+bool VirtualMemory::FreeSubSegment(int32_t handle, |
+ void* address, |
+ intptr_t size) { |
+ mx_handle_t vmar = static_cast<mx_handle_t>(handle); |
+ mx_status_t status = |
+ mx_vmar_unmap(vmar, reinterpret_cast<uintptr_t>(address), size); |
+ if (status != NO_ERROR) { |
+ LOG_ERR("mx_vmar_unmap failed: %s\n", mx_status_get_string(status)); |
+ return false; |
+ } |
+ return true; |
} |
bool VirtualMemory::Commit(uword addr, intptr_t size, bool executable) { |
- // TODO(zra): Implement when the protections for a mapping can be changed. |
- // Issue MG-133. |
+ ASSERT(Contains(addr)); |
+ ASSERT(Contains(addr + size) || (addr + size == end())); |
+ mx_handle_t vmo = MX_HANDLE_INVALID; |
+ mx_status_t status = mx_vmo_create(size, 0u, &vmo); |
+ if (status != NO_ERROR) { |
+ LOG_ERR("mx_vmo_create(%ld) failed: %s\n", size, |
+ mx_status_get_string(status)); |
+ return false; |
+ } |
+ |
+ mx_handle_t vmar = static_cast<mx_handle_t>(handle()); |
+ const size_t offset = addr - start(); |
+ const uint32_t flags = MX_VM_FLAG_SPECIFIC | MX_VM_FLAG_PERM_READ | |
+ MX_VM_FLAG_PERM_WRITE | MX_VM_FLAG_PERM_EXECUTE; |
+ uintptr_t mapped_addr; |
+ status = mx_vmar_map(vmar, offset, vmo, 0, size, flags, &mapped_addr); |
+ if (status != NO_ERROR) { |
+ mx_handle_close(vmo); |
+ LOG_ERR("mx_vmar_map(%ld, %ld, %u) failed: %s\n", offset, size, flags, |
+ mx_status_get_string(status)); |
+ return false; |
+ } |
+ if (addr != mapped_addr) { |
+ LOG_ERR("mx_vmar_map: addr != mapped_addr: %lx != %lx\n", addr, |
+ mapped_addr); |
+ return false; |
+ } |
return true; |
} |
bool VirtualMemory::Protect(void* address, intptr_t size, Protection mode) { |
- // TODO(zra): Implement when Fuchsia has an mprotect-like call. |
return true; |
} |