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

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

Issue 2550723002: Resurrect POSIX shared memory support on mac (Closed)
Patch Set: git cl format 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/posix/eintr_wrapper.h" 13 #include "base/posix/eintr_wrapper.h"
14 14
15 namespace base { 15 namespace base {
16 16
17 SharedMemoryHandle::SharedMemoryHandle() {} 17 static_assert(sizeof(SharedMemoryHandle::Type) <=
18 sizeof(SharedMemoryHandle::TypeWireFormat),
19 "Size of enum SharedMemoryHandle::Type exceeds size of type "
20 "transmitted over wire.");
21
22 SharedMemoryHandle::SharedMemoryHandle()
23 : type_(MACH), memory_object_(MACH_PORT_NULL) {}
24
25 SharedMemoryHandle::SharedMemoryHandle(
26 const base::FileDescriptor& file_descriptor)
27 : type_(POSIX), file_descriptor_(file_descriptor) {}
28
29 SharedMemoryHandle::SharedMemoryHandle(int fd, bool auto_close)
30 : type_(POSIX), file_descriptor_(fd, auto_close) {}
18 31
19 SharedMemoryHandle::SharedMemoryHandle(mach_vm_size_t size) { 32 SharedMemoryHandle::SharedMemoryHandle(mach_vm_size_t size) {
33 type_ = MACH;
20 mach_port_t named_right; 34 mach_port_t named_right;
21 kern_return_t kr = mach_make_memory_entry_64( 35 kern_return_t kr = mach_make_memory_entry_64(
22 mach_task_self(), 36 mach_task_self(),
23 &size, 37 &size,
24 0, // Address. 38 0, // Address.
25 MAP_MEM_NAMED_CREATE | VM_PROT_READ | VM_PROT_WRITE, 39 MAP_MEM_NAMED_CREATE | VM_PROT_READ | VM_PROT_WRITE,
26 &named_right, 40 &named_right,
27 MACH_PORT_NULL); // Parent handle. 41 MACH_PORT_NULL); // Parent handle.
28 if (kr != KERN_SUCCESS) { 42 if (kr != KERN_SUCCESS) {
29 memory_object_ = MACH_PORT_NULL; 43 memory_object_ = MACH_PORT_NULL;
30 return; 44 return;
31 } 45 }
32 46
33 memory_object_ = named_right; 47 memory_object_ = named_right;
34 size_ = size; 48 size_ = size;
35 pid_ = GetCurrentProcId(); 49 pid_ = GetCurrentProcId();
36 ownership_passes_to_ipc_ = false; 50 ownership_passes_to_ipc_ = false;
37 } 51 }
38 52
39 SharedMemoryHandle::SharedMemoryHandle(mach_port_t memory_object, 53 SharedMemoryHandle::SharedMemoryHandle(mach_port_t memory_object,
40 mach_vm_size_t size, 54 mach_vm_size_t size,
41 base::ProcessId pid) 55 base::ProcessId pid)
42 : memory_object_(memory_object), 56 : type_(MACH),
57 memory_object_(memory_object),
43 size_(size), 58 size_(size),
44 pid_(pid), 59 pid_(pid),
45 ownership_passes_to_ipc_(false) {} 60 ownership_passes_to_ipc_(false) {}
46 61
47 SharedMemoryHandle::SharedMemoryHandle(const SharedMemoryHandle& handle) { 62 SharedMemoryHandle::SharedMemoryHandle(const SharedMemoryHandle& handle)
63 : type_(handle.type_) {
48 CopyRelevantData(handle); 64 CopyRelevantData(handle);
49 } 65 }
50 66
51 SharedMemoryHandle& SharedMemoryHandle::operator=( 67 SharedMemoryHandle& SharedMemoryHandle::operator=(
52 const SharedMemoryHandle& handle) { 68 const SharedMemoryHandle& handle) {
53 if (this == &handle) 69 if (this == &handle)
54 return *this; 70 return *this;
55 71
72 type_ = handle.type_;
56 CopyRelevantData(handle); 73 CopyRelevantData(handle);
57 return *this; 74 return *this;
58 } 75 }
59 76
60 SharedMemoryHandle SharedMemoryHandle::Duplicate() const { 77 SharedMemoryHandle SharedMemoryHandle::Duplicate() const {
61 if (!IsValid()) 78 switch (type_) {
62 return SharedMemoryHandle(MACH_PORT_NULL, 0, 0); 79 case POSIX: {
80 if (!IsValid())
81 return SharedMemoryHandle();
63 82
64 // Increment the ref count. 83 int duped_fd = HANDLE_EINTR(dup(file_descriptor_.fd));
65 kern_return_t kr = mach_port_mod_refs(mach_task_self(), memory_object_, 84 if (duped_fd < 0)
66 MACH_PORT_RIGHT_SEND, 1); 85 return SharedMemoryHandle();
67 DCHECK_EQ(kr, KERN_SUCCESS); 86 return SharedMemoryHandle(duped_fd, true);
68 SharedMemoryHandle handle(*this); 87 }
69 handle.SetOwnershipPassesToIPC(true); 88 case MACH: {
70 return handle; 89 if (!IsValid())
90 return SharedMemoryHandle(MACH_PORT_NULL, 0, 0);
91
92 // Increment the ref count.
93 kern_return_t kr = mach_port_mod_refs(mach_task_self(), memory_object_,
94 MACH_PORT_RIGHT_SEND, 1);
95 DCHECK_EQ(kr, KERN_SUCCESS);
96 SharedMemoryHandle handle(*this);
97 handle.SetOwnershipPassesToIPC(true);
98 return handle;
99 }
100 }
71 } 101 }
72 102
73 bool SharedMemoryHandle::operator==(const SharedMemoryHandle& handle) const { 103 bool SharedMemoryHandle::operator==(const SharedMemoryHandle& handle) const {
74 if (!IsValid() && !handle.IsValid()) 104 if (!IsValid() && !handle.IsValid())
75 return true; 105 return true;
76 106
77 return memory_object_ == handle.memory_object_ && size_ == handle.size_ && 107 if (type_ != handle.type_)
78 pid_ == handle.pid_; 108 return false;
109
110 switch (type_) {
111 case POSIX:
112 return file_descriptor_ == handle.file_descriptor_;
113 case MACH:
114 return memory_object_ == handle.memory_object_ && size_ == handle.size_ &&
115 pid_ == handle.pid_;
116 }
79 } 117 }
80 118
81 bool SharedMemoryHandle::operator!=(const SharedMemoryHandle& handle) const { 119 bool SharedMemoryHandle::operator!=(const SharedMemoryHandle& handle) const {
82 return !(*this == handle); 120 return !(*this == handle);
83 } 121 }
84 122
123 SharedMemoryHandle::Type SharedMemoryHandle::GetType() const {
124 return type_;
125 }
126
85 bool SharedMemoryHandle::IsValid() const { 127 bool SharedMemoryHandle::IsValid() const {
86 return memory_object_ != MACH_PORT_NULL; 128 switch (type_) {
129 case POSIX:
130 return file_descriptor_.fd >= 0;
131 case MACH:
132 return memory_object_ != MACH_PORT_NULL;
133 }
134 }
135
136 void SharedMemoryHandle::SetFileHandle(int fd, bool auto_close) {
137 DCHECK(!IsValid());
138 file_descriptor_.fd = fd;
139 file_descriptor_.auto_close = auto_close;
140 type_ = POSIX;
141 }
142
143 const FileDescriptor SharedMemoryHandle::GetFileDescriptor() const {
144 DCHECK_EQ(type_, POSIX);
145 return file_descriptor_;
87 } 146 }
88 147
89 mach_port_t SharedMemoryHandle::GetMemoryObject() const { 148 mach_port_t SharedMemoryHandle::GetMemoryObject() const {
149 DCHECK_EQ(type_, MACH);
90 return memory_object_; 150 return memory_object_;
91 } 151 }
92 152
93 bool SharedMemoryHandle::GetSize(size_t* size) const { 153 bool SharedMemoryHandle::GetSize(size_t* size) const {
94 if (!IsValid()) { 154 if (!IsValid()) {
95 *size = 0; 155 *size = 0;
96 return true; 156 return true;
97 } 157 }
98 158
99 *size = size_; 159 switch (type_) {
100 return true; 160 case SharedMemoryHandle::POSIX:
161 struct stat st;
162 if (fstat(file_descriptor_.fd, &st) != 0)
163 return false;
164 if (st.st_size < 0)
165 return false;
166 *size = st.st_size;
167 return true;
168 case SharedMemoryHandle::MACH:
169 *size = size_;
170 return true;
171 }
101 } 172 }
102 173
103 bool SharedMemoryHandle::MapAt(off_t offset, 174 bool SharedMemoryHandle::MapAt(off_t offset,
104 size_t bytes, 175 size_t bytes,
105 void** memory, 176 void** memory,
106 bool read_only) { 177 bool read_only) {
107 DCHECK(IsValid()); 178 DCHECK(IsValid());
108 DCHECK_EQ(pid_, GetCurrentProcId()); 179 switch (type_) {
109 kern_return_t kr = mach_vm_map( 180 case SharedMemoryHandle::POSIX:
110 mach_task_self(), 181 *memory = mmap(nullptr, bytes, PROT_READ | (read_only ? 0 : PROT_WRITE),
111 reinterpret_cast<mach_vm_address_t*>(memory), // Output parameter 182 MAP_SHARED, file_descriptor_.fd, offset);
112 bytes, 183
113 0, // Alignment mask 184 return *memory && *memory != reinterpret_cast<void*>(-1);
114 VM_FLAGS_ANYWHERE, memory_object_, offset, 185 case SharedMemoryHandle::MACH:
115 FALSE, // Copy 186 DCHECK_EQ(pid_, GetCurrentProcId());
116 VM_PROT_READ | (read_only ? 0 : VM_PROT_WRITE), // Current protection 187 kern_return_t kr = mach_vm_map(
117 VM_PROT_WRITE | VM_PROT_READ | VM_PROT_IS_MASK, // Maximum protection 188 mach_task_self(),
118 VM_INHERIT_NONE); 189 reinterpret_cast<mach_vm_address_t*>(memory), // Output parameter
119 return kr == KERN_SUCCESS; 190 bytes,
191 0, // Alignment mask
192 VM_FLAGS_ANYWHERE, memory_object_, offset,
193 FALSE, // Copy
194 VM_PROT_READ | (read_only ? 0 : VM_PROT_WRITE), // Current protection
195 VM_PROT_WRITE | VM_PROT_READ | VM_PROT_IS_MASK, // Maximum protection
196 VM_INHERIT_NONE);
197 return kr == KERN_SUCCESS;
198 }
120 } 199 }
121 200
122 void SharedMemoryHandle::Close() const { 201 void SharedMemoryHandle::Close() const {
123 if (!IsValid()) 202 if (!IsValid())
124 return; 203 return;
125 204
126 kern_return_t kr = mach_port_deallocate(mach_task_self(), memory_object_); 205 switch (type_) {
127 if (kr != KERN_SUCCESS) 206 case POSIX:
128 DPLOG(ERROR) << "Error deallocating mach port: " << kr; 207 if (IGNORE_EINTR(close(file_descriptor_.fd)) < 0)
208 DPLOG(ERROR) << "Error closing fd.";
209 break;
210 case MACH:
211 kern_return_t kr = mach_port_deallocate(mach_task_self(), memory_object_);
212 if (kr != KERN_SUCCESS)
213 DPLOG(ERROR) << "Error deallocating mach port: " << kr;
214 break;
215 }
129 } 216 }
130 217
131 void SharedMemoryHandle::SetOwnershipPassesToIPC(bool ownership_passes) { 218 void SharedMemoryHandle::SetOwnershipPassesToIPC(bool ownership_passes) {
219 DCHECK_EQ(type_, MACH);
132 ownership_passes_to_ipc_ = ownership_passes; 220 ownership_passes_to_ipc_ = ownership_passes;
133 } 221 }
134 222
135 bool SharedMemoryHandle::OwnershipPassesToIPC() const { 223 bool SharedMemoryHandle::OwnershipPassesToIPC() const {
224 DCHECK_EQ(type_, MACH);
136 return ownership_passes_to_ipc_; 225 return ownership_passes_to_ipc_;
137 } 226 }
138 227
139 void SharedMemoryHandle::CopyRelevantData(const SharedMemoryHandle& handle) { 228 void SharedMemoryHandle::CopyRelevantData(const SharedMemoryHandle& handle) {
140 memory_object_ = handle.memory_object_; 229 switch (type_) {
141 size_ = handle.size_; 230 case POSIX:
142 pid_ = handle.pid_; 231 file_descriptor_ = handle.file_descriptor_;
143 ownership_passes_to_ipc_ = handle.ownership_passes_to_ipc_; 232 break;
233 case MACH:
234 memory_object_ = handle.memory_object_;
235 size_ = handle.size_;
236 pid_ = handle.pid_;
237 ownership_passes_to_ipc_ = handle.ownership_passes_to_ipc_;
238 break;
239 }
144 } 240 }
145 241
146 } // namespace base 242 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698