OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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.h" | 5 #include "base/memory/shared_memory.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <mach/mach_vm.h> | 8 #include <mach/mach_vm.h> |
9 #include <stddef.h> | 9 #include <stddef.h> |
10 #include <sys/mman.h> | 10 #include <sys/mman.h> |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 bool SharedMemory::GetSizeFromSharedMemoryHandle( | 128 bool SharedMemory::GetSizeFromSharedMemoryHandle( |
129 const SharedMemoryHandle& handle, | 129 const SharedMemoryHandle& handle, |
130 size_t* size) { | 130 size_t* size) { |
131 return handle.GetSize(size); | 131 return handle.GetSize(size); |
132 } | 132 } |
133 | 133 |
134 // Chromium mostly only uses the unique/private shmem as specified by | 134 // Chromium mostly only uses the unique/private shmem as specified by |
135 // "name == L"". The exception is in the StatsTable. | 135 // "name == L"". The exception is in the StatsTable. |
136 bool SharedMemory::Create(const SharedMemoryCreateOptions& options) { | 136 bool SharedMemory::Create(const SharedMemoryCreateOptions& options) { |
137 DCHECK(!shm_.IsValid()); | 137 DCHECK(!shm_.IsValid()); |
138 if (options.size == 0) return false; | 138 if (options.size == 0) { |
| 139 last_error_ = SharedMemoryError::BAD_PARAMS; |
| 140 return false; |
| 141 } |
139 | 142 |
140 if (options.size > static_cast<size_t>(std::numeric_limits<int>::max())) | 143 if (options.size > static_cast<size_t>(std::numeric_limits<int>::max())) { |
| 144 last_error_ = SharedMemoryError::BAD_PARAMS; |
141 return false; | 145 return false; |
| 146 } |
142 | 147 |
143 if (options.type == SharedMemoryHandle::MACH) { | 148 if (options.type == SharedMemoryHandle::MACH) { |
144 shm_ = SharedMemoryHandle(options.size, UnguessableToken::Create()); | 149 shm_ = SharedMemoryHandle(options.size, UnguessableToken::Create()); |
145 requested_size_ = options.size; | 150 requested_size_ = options.size; |
146 return shm_.IsValid(); | 151 return shm_.IsValid(); |
147 } | 152 } |
148 | 153 |
149 // This function theoretically can block on the disk. Both profiling of real | 154 // This function theoretically can block on the disk. Both profiling of real |
150 // users and local instrumentation shows that this is a real problem. | 155 // users and local instrumentation shows that this is a real problem. |
151 // https://code.google.com/p/chromium/issues/detail?id=466437 | 156 // https://code.google.com/p/chromium/issues/detail?id=466437 |
152 base::ThreadRestrictions::ScopedAllowIO allow_io; | 157 base::ThreadRestrictions::ScopedAllowIO allow_io; |
153 | 158 |
154 ScopedFILE fp; | 159 ScopedFILE fp; |
155 ScopedFD readonly_fd; | 160 ScopedFD readonly_fd; |
156 | 161 |
157 FilePath path; | 162 FilePath path; |
158 bool result = CreateAnonymousSharedMemory(options, &fp, &readonly_fd, &path); | 163 bool result = CreateAnonymousSharedMemory(options, &fp, &readonly_fd, &path, |
| 164 &last_error_); |
159 if (!result) | 165 if (!result) |
160 return false; | 166 return false; |
161 | 167 DCHECK(fp); // Should be guaranteed by CreateAnonymousSharedMemory(). |
162 if (!fp) { | |
163 PLOG(ERROR) << "Creating shared memory in " << path.value() << " failed"; | |
164 return false; | |
165 } | |
166 | 168 |
167 // Get current size. | 169 // Get current size. |
168 struct stat stat; | 170 struct stat stat; |
169 if (fstat(fileno(fp.get()), &stat) != 0) | 171 if (fstat(fileno(fp.get()), &stat) != 0) { |
| 172 last_error_ = SharedMemoryError::STAT_FAILED; |
170 return false; | 173 return false; |
| 174 } |
171 const size_t current_size = stat.st_size; | 175 const size_t current_size = stat.st_size; |
172 if (current_size != options.size) { | 176 if (current_size != options.size) { |
173 if (HANDLE_EINTR(ftruncate(fileno(fp.get()), options.size)) != 0) | 177 if (HANDLE_EINTR(ftruncate(fileno(fp.get()), options.size)) != 0) { |
| 178 last_error_ = SharedMemoryError::TRUNCATE_FAILED; |
174 return false; | 179 return false; |
| 180 } |
175 } | 181 } |
176 requested_size_ = options.size; | 182 requested_size_ = options.size; |
177 | 183 |
178 int mapped_file = -1; | 184 int mapped_file = -1; |
179 int readonly_mapped_file = -1; | 185 int readonly_mapped_file = -1; |
180 result = PrepareMapFile(std::move(fp), std::move(readonly_fd), &mapped_file, | 186 result = PrepareMapFile(std::move(fp), std::move(readonly_fd), &mapped_file, |
181 &readonly_mapped_file); | 187 &readonly_mapped_file, &last_error_); |
182 shm_ = SharedMemoryHandle(FileDescriptor(mapped_file, false), | 188 shm_ = SharedMemoryHandle(FileDescriptor(mapped_file, false), |
183 UnguessableToken::Create()); | 189 UnguessableToken::Create()); |
184 readonly_shm_ = SharedMemoryHandle( | 190 readonly_shm_ = SharedMemoryHandle( |
185 FileDescriptor(readonly_mapped_file, false), shm_.GetGUID()); | 191 FileDescriptor(readonly_mapped_file, false), shm_.GetGUID()); |
186 return result; | 192 return result; |
187 } | 193 } |
188 | 194 |
189 bool SharedMemory::MapAt(off_t offset, size_t bytes) { | 195 bool SharedMemory::MapAt(off_t offset, size_t bytes) { |
190 if (!shm_.IsValid()) | 196 if (!shm_.IsValid()) { |
| 197 last_error_ = SharedMemoryError::BAD_PARAMS; |
191 return false; | 198 return false; |
192 if (bytes > static_cast<size_t>(std::numeric_limits<int>::max())) | 199 } |
| 200 if (bytes > static_cast<size_t>(std::numeric_limits<int>::max())) { |
| 201 last_error_ = SharedMemoryError::BAD_PARAMS; |
193 return false; | 202 return false; |
194 if (memory_) | 203 } |
| 204 if (memory_) { |
| 205 last_error_ = SharedMemoryError::BAD_PARAMS; |
195 return false; | 206 return false; |
| 207 } |
196 | 208 |
197 bool success = shm_.MapAt(offset, bytes, &memory_, read_only_); | 209 bool success = shm_.MapAt(offset, bytes, &memory_, read_only_); |
198 if (success) { | 210 if (success) { |
199 mapped_size_ = bytes; | 211 mapped_size_ = bytes; |
200 DCHECK_EQ(0U, reinterpret_cast<uintptr_t>(memory_) & | 212 DCHECK_EQ(0U, reinterpret_cast<uintptr_t>(memory_) & |
201 (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1)); | 213 (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1)); |
202 mapped_memory_mechanism_ = shm_.type_; | 214 mapped_memory_mechanism_ = shm_.type_; |
203 } else { | 215 } else { |
| 216 last_error_ = SharedMemoryError::MMAP_FAILED; |
204 memory_ = NULL; | 217 memory_ = NULL; |
205 } | 218 } |
206 | 219 |
207 return success; | 220 return success; |
208 } | 221 } |
209 | 222 |
210 bool SharedMemory::Unmap() { | 223 bool SharedMemory::Unmap() { |
211 if (memory_ == NULL) | 224 if (memory_ == NULL) |
212 return false; | 225 return false; |
213 | 226 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
264 | 277 |
265 DCHECK(shm_.IsValid()); | 278 DCHECK(shm_.IsValid()); |
266 base::SharedMemoryHandle new_handle; | 279 base::SharedMemoryHandle new_handle; |
267 bool success = MakeMachSharedMemoryHandleReadOnly(&new_handle, shm_, memory_); | 280 bool success = MakeMachSharedMemoryHandleReadOnly(&new_handle, shm_, memory_); |
268 if (success) | 281 if (success) |
269 new_handle.SetOwnershipPassesToIPC(true); | 282 new_handle.SetOwnershipPassesToIPC(true); |
270 return new_handle; | 283 return new_handle; |
271 } | 284 } |
272 | 285 |
273 } // namespace base | 286 } // namespace base |
OLD | NEW |