1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_MAC_SCOPED_MACH_VM_H_ 6 #define BASE_MAC_SCOPED_MACH_VM_H_ 7 8 #include <mach/mach.h> 9 10 #include <algorithm> 11 12 #include "base/base_export.h" 13 #include "base/basictypes.h" 14 #include "base/logging.h" 15 16 // Use ScopedMachVM to supervise ownership of pages in the current process 17 // through the Mach VM subsystem. Pages allocated with vm_allocate can be 18 // released when exiting a scope with ScopedMachVM. 19 // 20 // The Mach VM subsystem operates on a page-by-page basis, and a single VM 21 // allocation managed by a ScopedMachVM object may span multiple pages. As far 22 // as Mach is concerned, allocated pages may be deallocated individually. This 23 // is in contrast to higher-level allocators such as malloc, where the base 24 // address of an allocation implies the size of an allocated block. 25 // Consequently, it is not sufficient to just pass the base address of an 26 // allocation to ScopedMachVM, it also needs to know the size of the 27 // allocation. To avoid any confusion, both the base address and size must 28 // be page-aligned. 29 // 30 // When dealing with Mach VM, base addresses will naturally be page-aligned, 31 // but user-specified sizes may not be. If there's a concern that a size is 32 // not page-aligned, use the mach_vm_round_page macro to correct it. 33 // 34 // Example: 35 // 36 // vm_address_t address = 0; 37 // vm_size_t size = 12345; // This requested size is not page-aligned. 38 // kern_return_t kr = 39 // vm_allocate(mach_task_self(), &address, size, VM_FLAGS_ANYWHERE); 40 // if (kr != KERN_SUCCESS) { 41 // return false; 42 // } 43 // ScopedMachVM vm_owner(address, mach_vm_round_page(size)); 44 45 namespace base { 46 namespace mac { 47 48 class BASE_EXPORT ScopedMachVM { 49 public: 50 explicit ScopedMachVM(vm_address_t address = 0, vm_size_t size = 0) 51 : address_(address), 52 size_(size) { 53 DCHECK(address % PAGE_SIZE == 0); 54 DCHECK(size % PAGE_SIZE == 0); 55 } 56 57 ~ScopedMachVM() { 58 if (size_) { 59 vm_deallocate(mach_task_self(), address_, size_); 60 } 61 } 62 63 void reset(vm_address_t address = 0, vm_size_t size = 0); 64 65 vm_address_t address() const { 66 return address_; 67 } 68 69 vm_size_t size() const { 70 return size_; 71 } 72 73 void swap(ScopedMachVM& that) { 74 std::swap(address_, that.address_); 75 std::swap(size_, that.size_); 76 } 77 78 void release() { 79 address_ = 0; 80 size_ = 0; 81 } 82 83 private: 84 vm_address_t address_; 85 vm_size_t size_; 86 87 DISALLOW_COPY_AND_ASSIGN(ScopedMachVM); 88 }; 89 90 } // namespace mac 91 } // namespace base 92 93 #endif // BASE_MAC_SCOPED_MACH_VM_H_ 94