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