xref: /aosp_15_r20/external/cronet/base/apple/scoped_mach_vm.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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