| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/discardable_shared_memory.h" | 5 #include "base/memory/discardable_shared_memory.h" |
| 6 | 6 |
| 7 #if defined(OS_POSIX) | 7 #if defined(OS_POSIX) |
| 8 #include <unistd.h> | 8 #include <unistd.h> |
| 9 #endif | 9 #endif |
| 10 | 10 |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 | 150 |
| 151 locked_page_count_ = AlignToPageSize(mapped_size_) / base::GetPageSize(); | 151 locked_page_count_ = AlignToPageSize(mapped_size_) / base::GetPageSize(); |
| 152 #if DCHECK_IS_ON() | 152 #if DCHECK_IS_ON() |
| 153 for (size_t page = 0; page < locked_page_count_; ++page) | 153 for (size_t page = 0; page < locked_page_count_; ++page) |
| 154 locked_pages_.insert(page); | 154 locked_pages_.insert(page); |
| 155 #endif | 155 #endif |
| 156 | 156 |
| 157 return true; | 157 return true; |
| 158 } | 158 } |
| 159 | 159 |
| 160 bool DiscardableSharedMemory::Lock(size_t offset, size_t length) { | 160 DiscardableSharedMemory::LockResult DiscardableSharedMemory::Lock( |
| 161 size_t offset, size_t length) { |
| 161 DCHECK_EQ(AlignToPageSize(offset), offset); | 162 DCHECK_EQ(AlignToPageSize(offset), offset); |
| 162 DCHECK_EQ(AlignToPageSize(length), length); | 163 DCHECK_EQ(AlignToPageSize(length), length); |
| 163 | 164 |
| 164 // Calls to this function must synchronized properly. | 165 // Calls to this function must synchronized properly. |
| 165 DFAKE_SCOPED_LOCK(thread_collision_warner_); | 166 DFAKE_SCOPED_LOCK(thread_collision_warner_); |
| 166 | 167 |
| 167 // Return false when instance has been purged or not initialized properly by | 168 // Return false when instance has been purged or not initialized properly by |
| 168 // checking if |last_known_usage_| is NULL. | 169 // checking if |last_known_usage_| is NULL. |
| 169 if (last_known_usage_.is_null()) | 170 if (last_known_usage_.is_null()) |
| 170 return false; | 171 return FAILED; |
| 171 | 172 |
| 172 DCHECK(shared_memory_.memory()); | 173 DCHECK(shared_memory_.memory()); |
| 173 | 174 |
| 174 // We need to successfully acquire the platform independent lock before | 175 // We need to successfully acquire the platform independent lock before |
| 175 // individual pages can be locked. | 176 // individual pages can be locked. |
| 176 if (!locked_page_count_) { | 177 if (!locked_page_count_) { |
| 177 SharedState old_state(SharedState::UNLOCKED, last_known_usage_); | 178 SharedState old_state(SharedState::UNLOCKED, last_known_usage_); |
| 178 SharedState new_state(SharedState::LOCKED, Time()); | 179 SharedState new_state(SharedState::LOCKED, Time()); |
| 179 SharedState result(subtle::Acquire_CompareAndSwap( | 180 SharedState result(subtle::Acquire_CompareAndSwap( |
| 180 &SharedStateFromSharedMemory(shared_memory_)->value.i, | 181 &SharedStateFromSharedMemory(shared_memory_)->value.i, |
| 181 old_state.value.i, | 182 old_state.value.i, |
| 182 new_state.value.i)); | 183 new_state.value.i)); |
| 183 if (result.value.u != old_state.value.u) { | 184 if (result.value.u != old_state.value.u) { |
| 184 // Update |last_known_usage_| in case the above CAS failed because of | 185 // Update |last_known_usage_| in case the above CAS failed because of |
| 185 // an incorrect timestamp. | 186 // an incorrect timestamp. |
| 186 last_known_usage_ = result.GetTimestamp(); | 187 last_known_usage_ = result.GetTimestamp(); |
| 187 return false; | 188 return FAILED; |
| 188 } | 189 } |
| 189 } | 190 } |
| 190 | 191 |
| 191 // Zero for length means "everything onward". | 192 // Zero for length means "everything onward". |
| 192 if (!length) | 193 if (!length) |
| 193 length = AlignToPageSize(mapped_size_) - offset; | 194 length = AlignToPageSize(mapped_size_) - offset; |
| 194 | 195 |
| 195 size_t start = offset / base::GetPageSize(); | 196 size_t start = offset / base::GetPageSize(); |
| 196 size_t end = start + length / base::GetPageSize(); | 197 size_t end = start + length / base::GetPageSize(); |
| 197 DCHECK_LT(start, end); | 198 DCHECK_LT(start, end); |
| 198 DCHECK_LE(end, AlignToPageSize(mapped_size_) / base::GetPageSize()); | 199 DCHECK_LE(end, AlignToPageSize(mapped_size_) / base::GetPageSize()); |
| 199 | 200 |
| 200 // Add pages to |locked_page_count_|. | 201 // Add pages to |locked_page_count_|. |
| 201 // Note: Locking a page that is already locked is an error. | 202 // Note: Locking a page that is already locked is an error. |
| 202 locked_page_count_ += end - start; | 203 locked_page_count_ += end - start; |
| 203 #if DCHECK_IS_ON() | 204 #if DCHECK_IS_ON() |
| 204 // Detect incorrect usage by keeping track of exactly what pages are locked. | 205 // Detect incorrect usage by keeping track of exactly what pages are locked. |
| 205 for (auto page = start; page < end; ++page) { | 206 for (auto page = start; page < end; ++page) { |
| 206 auto result = locked_pages_.insert(page); | 207 auto result = locked_pages_.insert(page); |
| 207 DCHECK(result.second); | 208 DCHECK(result.second); |
| 208 } | 209 } |
| 209 DCHECK_EQ(locked_pages_.size(), locked_page_count_); | 210 DCHECK_EQ(locked_pages_.size(), locked_page_count_); |
| 210 #endif | 211 #endif |
| 211 | 212 |
| 212 #if defined(OS_ANDROID) | 213 #if defined(OS_ANDROID) |
| 213 SharedMemoryHandle handle = shared_memory_.handle(); | 214 SharedMemoryHandle handle = shared_memory_.handle(); |
| 214 DCHECK(SharedMemory::IsHandleValid(handle)); | 215 DCHECK(SharedMemory::IsHandleValid(handle)); |
| 215 if (ashmem_pin_region( | 216 if (ashmem_pin_region( |
| 216 handle.fd, AlignToPageSize(sizeof(SharedState)) + offset, length)) { | 217 handle.fd, AlignToPageSize(sizeof(SharedState)) + offset, length)) { |
| 217 return false; | 218 return PURGED; |
| 218 } | 219 } |
| 219 #endif | 220 #endif |
| 220 | 221 |
| 221 return true; | 222 return SUCCESS; |
| 222 } | 223 } |
| 223 | 224 |
| 224 void DiscardableSharedMemory::Unlock(size_t offset, size_t length) { | 225 void DiscardableSharedMemory::Unlock(size_t offset, size_t length) { |
| 225 DCHECK_EQ(AlignToPageSize(offset), offset); | 226 DCHECK_EQ(AlignToPageSize(offset), offset); |
| 226 DCHECK_EQ(AlignToPageSize(length), length); | 227 DCHECK_EQ(AlignToPageSize(length), length); |
| 227 | 228 |
| 228 // Calls to this function must synchronized properly. | 229 // Calls to this function must synchronized properly. |
| 229 DFAKE_SCOPED_LOCK(thread_collision_warner_); | 230 DFAKE_SCOPED_LOCK(thread_collision_warner_); |
| 230 | 231 |
| 231 // Zero for length means "everything onward". | 232 // Zero for length means "everything onward". |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 354 shared_memory_.Unmap(); | 355 shared_memory_.Unmap(); |
| 355 shared_memory_.Close(); | 356 shared_memory_.Close(); |
| 356 mapped_size_ = 0; | 357 mapped_size_ = 0; |
| 357 } | 358 } |
| 358 | 359 |
| 359 Time DiscardableSharedMemory::Now() const { | 360 Time DiscardableSharedMemory::Now() const { |
| 360 return Time::Now(); | 361 return Time::Now(); |
| 361 } | 362 } |
| 362 | 363 |
| 363 } // namespace base | 364 } // namespace base |
| OLD | NEW |