| 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 |