Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(913)

Side by Side Diff: base/memory/shared_memory_handle_mac.cc

Issue 2555483002: Add POSIX shared memory support for Mac (Closed)
Patch Set: Readd Android ifdef. Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 #include "base/memory/shared_memory_handle.h" 5 #include "base/memory/shared_memory_handle.h"
6 6
7 #include <mach/mach_vm.h> 7 #include <mach/mach_vm.h>
8 #include <stddef.h> 8 #include <stddef.h>
9 #include <sys/mman.h> 9 #include <sys/mman.h>
10 #include <unistd.h> 10 #include <unistd.h>
11 11
12 #include "base/mac/mac_util.h" 12 #include "base/mac/mac_util.h"
13 #include "base/mac/mach_logging.h"
13 #include "base/posix/eintr_wrapper.h" 14 #include "base/posix/eintr_wrapper.h"
14 15
15 namespace base { 16 namespace base {
16 17
17 SharedMemoryHandle::SharedMemoryHandle() {} 18 SharedMemoryHandle::SharedMemoryHandle()
19 : type_(MACH), memory_object_(MACH_PORT_NULL) {}
20
21 SharedMemoryHandle::SharedMemoryHandle(
22 const base::FileDescriptor& file_descriptor)
23 : type_(POSIX), file_descriptor_(file_descriptor) {}
18 24
19 SharedMemoryHandle::SharedMemoryHandle(mach_vm_size_t size) { 25 SharedMemoryHandle::SharedMemoryHandle(mach_vm_size_t size) {
26 type_ = MACH;
20 mach_port_t named_right; 27 mach_port_t named_right;
21 kern_return_t kr = mach_make_memory_entry_64( 28 kern_return_t kr = mach_make_memory_entry_64(
22 mach_task_self(), 29 mach_task_self(),
23 &size, 30 &size,
24 0, // Address. 31 0, // Address.
25 MAP_MEM_NAMED_CREATE | VM_PROT_READ | VM_PROT_WRITE, 32 MAP_MEM_NAMED_CREATE | VM_PROT_READ | VM_PROT_WRITE,
26 &named_right, 33 &named_right,
27 MACH_PORT_NULL); // Parent handle. 34 MACH_PORT_NULL); // Parent handle.
28 if (kr != KERN_SUCCESS) { 35 if (kr != KERN_SUCCESS) {
29 memory_object_ = MACH_PORT_NULL; 36 memory_object_ = MACH_PORT_NULL;
30 return; 37 return;
31 } 38 }
32 39
33 memory_object_ = named_right; 40 memory_object_ = named_right;
34 size_ = size; 41 size_ = size;
35 pid_ = GetCurrentProcId(); 42 pid_ = GetCurrentProcId();
36 ownership_passes_to_ipc_ = false; 43 ownership_passes_to_ipc_ = false;
37 } 44 }
38 45
39 SharedMemoryHandle::SharedMemoryHandle(mach_port_t memory_object, 46 SharedMemoryHandle::SharedMemoryHandle(mach_port_t memory_object,
40 mach_vm_size_t size, 47 mach_vm_size_t size,
41 base::ProcessId pid) 48 base::ProcessId pid)
42 : memory_object_(memory_object), 49 : type_(MACH),
50 memory_object_(memory_object),
43 size_(size), 51 size_(size),
44 pid_(pid), 52 pid_(pid),
45 ownership_passes_to_ipc_(false) {} 53 ownership_passes_to_ipc_(false) {}
46 54
47 SharedMemoryHandle::SharedMemoryHandle(const SharedMemoryHandle& handle) { 55 SharedMemoryHandle::SharedMemoryHandle(const SharedMemoryHandle& handle)
56 : type_(handle.type_) {
48 CopyRelevantData(handle); 57 CopyRelevantData(handle);
49 } 58 }
50 59
51 SharedMemoryHandle& SharedMemoryHandle::operator=( 60 SharedMemoryHandle& SharedMemoryHandle::operator=(
52 const SharedMemoryHandle& handle) { 61 const SharedMemoryHandle& handle) {
53 if (this == &handle) 62 if (this == &handle)
54 return *this; 63 return *this;
55 64
65 type_ = handle.type_;
56 CopyRelevantData(handle); 66 CopyRelevantData(handle);
57 return *this; 67 return *this;
58 } 68 }
59 69
60 SharedMemoryHandle SharedMemoryHandle::Duplicate() const { 70 SharedMemoryHandle SharedMemoryHandle::Duplicate() const {
Robert Sesek 2016/12/07 16:39:42 Does this need an implementation for type_==POSIX
lawrencewu 2016/12/07 19:44:26 No, since my project doesn't use this. There's a c
61 if (!IsValid()) 71 if (!IsValid())
62 return SharedMemoryHandle(MACH_PORT_NULL, 0, 0); 72 return SharedMemoryHandle(MACH_PORT_NULL, 0, 0);
63 73
64 // Increment the ref count. 74 // Increment the ref count.
65 kern_return_t kr = mach_port_mod_refs(mach_task_self(), memory_object_, 75 kern_return_t kr = mach_port_mod_refs(mach_task_self(), memory_object_,
66 MACH_PORT_RIGHT_SEND, 1); 76 MACH_PORT_RIGHT_SEND, 1);
67 DCHECK_EQ(kr, KERN_SUCCESS); 77 if (kr != KERN_SUCCESS) {
78 MACH_LOG(ERROR, kr) << "mach_port_mod_refs";
79 CHECK(false);
Robert Sesek 2016/12/07 16:39:42 There's MACH_CHECK, but this could maybe do the re
lawrencewu 2016/12/07 19:44:26 Done.
80 }
81
68 SharedMemoryHandle handle(*this); 82 SharedMemoryHandle handle(*this);
69 handle.SetOwnershipPassesToIPC(true); 83 handle.SetOwnershipPassesToIPC(true);
70 return handle; 84 return handle;
71 } 85 }
72 86
73 bool SharedMemoryHandle::operator==(const SharedMemoryHandle& handle) const { 87 bool SharedMemoryHandle::operator==(const SharedMemoryHandle& handle) const {
74 if (!IsValid() && !handle.IsValid()) 88 if (!IsValid() && !handle.IsValid())
75 return true; 89 return true;
76 90
77 return memory_object_ == handle.memory_object_ && size_ == handle.size_ && 91 if (type_ != handle.type_)
78 pid_ == handle.pid_; 92 return false;
93
94 switch (type_) {
95 case POSIX:
96 return file_descriptor_ == handle.file_descriptor_;
97 case MACH:
98 return memory_object_ == handle.memory_object_ && size_ == handle.size_ &&
99 pid_ == handle.pid_;
100 }
79 } 101 }
80 102
81 bool SharedMemoryHandle::operator!=(const SharedMemoryHandle& handle) const { 103 bool SharedMemoryHandle::operator!=(const SharedMemoryHandle& handle) const {
82 return !(*this == handle); 104 return !(*this == handle);
83 } 105 }
84 106
85 bool SharedMemoryHandle::IsValid() const { 107 bool SharedMemoryHandle::IsValid() const {
86 return memory_object_ != MACH_PORT_NULL; 108 switch (type_) {
109 case POSIX:
110 return file_descriptor_.fd >= 0;
111 case MACH:
112 return memory_object_ != MACH_PORT_NULL;
113 }
87 } 114 }
88 115
89 mach_port_t SharedMemoryHandle::GetMemoryObject() const { 116 mach_port_t SharedMemoryHandle::GetMemoryObject() const {
117 DCHECK_EQ(type_, MACH);
90 return memory_object_; 118 return memory_object_;
91 } 119 }
92 120
93 bool SharedMemoryHandle::GetSize(size_t* size) const { 121 bool SharedMemoryHandle::GetSize(size_t* size) const {
94 if (!IsValid()) { 122 if (!IsValid()) {
95 *size = 0; 123 *size = 0;
96 return true; 124 return true;
97 } 125 }
98 126
99 *size = size_; 127 switch (type_) {
100 return true; 128 case SharedMemoryHandle::POSIX:
129 struct stat st;
130 if (fstat(file_descriptor_.fd, &st) != 0)
131 return false;
132 if (st.st_size < 0)
133 return false;
134 *size = st.st_size;
135 return true;
136 case SharedMemoryHandle::MACH:
137 *size = size_;
138 return true;
139 }
101 } 140 }
102 141
103 bool SharedMemoryHandle::MapAt(off_t offset, 142 bool SharedMemoryHandle::MapAt(off_t offset,
104 size_t bytes, 143 size_t bytes,
105 void** memory, 144 void** memory,
106 bool read_only) { 145 bool read_only) {
107 DCHECK(IsValid()); 146 DCHECK(IsValid());
108 DCHECK_EQ(pid_, GetCurrentProcId()); 147 switch (type_) {
109 kern_return_t kr = mach_vm_map( 148 case SharedMemoryHandle::POSIX:
110 mach_task_self(), 149 *memory = mmap(nullptr, bytes, PROT_READ | (read_only ? 0 : PROT_WRITE),
111 reinterpret_cast<mach_vm_address_t*>(memory), // Output parameter 150 MAP_SHARED, file_descriptor_.fd, offset);
112 bytes, 151
113 0, // Alignment mask 152 return *memory && *memory != reinterpret_cast<void*>(-1);
114 VM_FLAGS_ANYWHERE, memory_object_, offset, 153 case SharedMemoryHandle::MACH:
115 FALSE, // Copy 154 DCHECK_EQ(pid_, GetCurrentProcId());
116 VM_PROT_READ | (read_only ? 0 : VM_PROT_WRITE), // Current protection 155 kern_return_t kr = mach_vm_map(
117 VM_PROT_WRITE | VM_PROT_READ | VM_PROT_IS_MASK, // Maximum protection 156 mach_task_self(),
118 VM_INHERIT_NONE); 157 reinterpret_cast<mach_vm_address_t*>(memory), // Output parameter
119 return kr == KERN_SUCCESS; 158 bytes,
159 0, // Alignment mask
160 VM_FLAGS_ANYWHERE,
161 memory_object_,
162 offset,
163 FALSE, // Copy
164 VM_PROT_READ | (read_only ? 0 : VM_PROT_WRITE), // Current protection
165 VM_PROT_WRITE | VM_PROT_READ | VM_PROT_IS_MASK, // Maximum protection
166 VM_INHERIT_NONE);
167 return kr == KERN_SUCCESS;
168 }
120 } 169 }
121 170
122 void SharedMemoryHandle::Close() const { 171 void SharedMemoryHandle::Close() const {
123 if (!IsValid()) 172 if (!IsValid())
124 return; 173 return;
125 174
126 kern_return_t kr = mach_port_deallocate(mach_task_self(), memory_object_); 175 switch (type_) {
127 if (kr != KERN_SUCCESS) 176 case POSIX:
128 DPLOG(ERROR) << "Error deallocating mach port: " << kr; 177 if (IGNORE_EINTR(close(file_descriptor_.fd)) < 0)
178 DPLOG(ERROR) << "Error closing fd.";
179 break;
180 case MACH:
181 kern_return_t kr = mach_port_deallocate(mach_task_self(), memory_object_);
182 if (kr != KERN_SUCCESS)
183 MACH_LOG(ERROR, kr) << "Error deallocating mach port";
184 break;
185 }
129 } 186 }
130 187
131 void SharedMemoryHandle::SetOwnershipPassesToIPC(bool ownership_passes) { 188 void SharedMemoryHandle::SetOwnershipPassesToIPC(bool ownership_passes) {
189 DCHECK_EQ(type_, MACH);
132 ownership_passes_to_ipc_ = ownership_passes; 190 ownership_passes_to_ipc_ = ownership_passes;
133 } 191 }
134 192
135 bool SharedMemoryHandle::OwnershipPassesToIPC() const { 193 bool SharedMemoryHandle::OwnershipPassesToIPC() const {
194 DCHECK_EQ(type_, MACH);
136 return ownership_passes_to_ipc_; 195 return ownership_passes_to_ipc_;
137 } 196 }
138 197
139 void SharedMemoryHandle::CopyRelevantData(const SharedMemoryHandle& handle) { 198 void SharedMemoryHandle::CopyRelevantData(const SharedMemoryHandle& handle) {
140 memory_object_ = handle.memory_object_; 199 switch (type_) {
141 size_ = handle.size_; 200 case POSIX:
142 pid_ = handle.pid_; 201 file_descriptor_ = handle.file_descriptor_;
143 ownership_passes_to_ipc_ = handle.ownership_passes_to_ipc_; 202 break;
203 case MACH:
204 memory_object_ = handle.memory_object_;
205 size_ = handle.size_;
206 pid_ = handle.pid_;
207 ownership_passes_to_ipc_ = handle.ownership_passes_to_ipc_;
208 break;
209 }
144 } 210 }
145 211
146 } // namespace base 212 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698