Home | History | Annotate | Download | only in mac
      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 #include <stddef.h>
     10 
     11 #include <algorithm>
     12 
     13 #include "base/base_export.h"
     14 #include "base/logging.h"
     15 #include "base/macros.h"
     16 
     17 // Use ScopedMachVM to supervise ownership of pages in the current process
     18 // through the Mach VM subsystem. Pages allocated with vm_allocate can be
     19 // released when exiting a scope with ScopedMachVM.
     20 //
     21 // The Mach VM subsystem operates on a page-by-page basis, and a single VM
     22 // allocation managed by a ScopedMachVM object may span multiple pages. As far
     23 // as Mach is concerned, allocated pages may be deallocated individually. This
     24 // is in contrast to higher-level allocators such as malloc, where the base
     25 // address of an allocation implies the size of an allocated block.
     26 // Consequently, it is not sufficient to just pass the base address of an
     27 // allocation to ScopedMachVM, it also needs to know the size of the
     28 // allocation. To avoid any confusion, both the base address and size must
     29 // be page-aligned.
     30 //
     31 // When dealing with Mach VM, base addresses will naturally be page-aligned,
     32 // but user-specified sizes may not be. If there's a concern that a size is
     33 // not page-aligned, use the mach_vm_round_page macro to correct it.
     34 //
     35 // Example:
     36 //
     37 //   vm_address_t address = 0;
     38 //   vm_size_t size = 12345;  // This requested size is not page-aligned.
     39 //   kern_return_t kr =
     40 //       vm_allocate(mach_task_self(), &address, size, VM_FLAGS_ANYWHERE);
     41 //   if (kr != KERN_SUCCESS) {
     42 //     return false;
     43 //   }
     44 //   ScopedMachVM vm_owner(address, mach_vm_round_page(size));
     45 
     46 namespace base {
     47 namespace mac {
     48 
     49 class BASE_EXPORT ScopedMachVM {
     50  public:
     51   explicit ScopedMachVM(vm_address_t address = 0, vm_size_t size = 0)
     52       : address_(address), size_(size) {
     53     DCHECK_EQ(address % PAGE_SIZE, 0u);
     54     DCHECK_EQ(size % PAGE_SIZE, 0u);
     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