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