| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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_memory_allocator_android.h" | 5 #include "base/memory/discardable_memory_allocator_android.h" |
| 6 | 6 |
| 7 #include <sys/mman.h> | 7 #include <sys/mman.h> |
| 8 #include <unistd.h> | 8 #include <unistd.h> |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| 11 #include <cmath> | 11 #include <cmath> |
| 12 #include <limits> | 12 #include <limits> |
| 13 #include <set> | 13 #include <set> |
| 14 #include <utility> | 14 #include <utility> |
| 15 | 15 |
| 16 #include "base/basictypes.h" | 16 #include "base/basictypes.h" |
| 17 #include "base/containers/hash_tables.h" | 17 #include "base/containers/hash_tables.h" |
| 18 #include "base/file_util.h" | 18 #include "base/file_util.h" |
| 19 #include "base/files/scoped_file.h" | |
| 20 #include "base/logging.h" | 19 #include "base/logging.h" |
| 21 #include "base/memory/discardable_memory.h" | 20 #include "base/memory/discardable_memory.h" |
| 22 #include "base/memory/scoped_vector.h" | 21 #include "base/memory/scoped_vector.h" |
| 23 #include "base/synchronization/lock.h" | 22 #include "base/synchronization/lock.h" |
| 24 #include "base/threading/thread_checker.h" | 23 #include "base/threading/thread_checker.h" |
| 25 #include "third_party/ashmem/ashmem.h" | 24 #include "third_party/ashmem/ashmem.h" |
| 26 | 25 |
| 27 // The allocator consists of three parts (classes): | 26 // The allocator consists of three parts (classes): |
| 28 // - DiscardableMemoryAllocator: entry point of all allocations (through its | 27 // - DiscardableMemoryAllocator: entry point of all allocations (through its |
| 29 // Allocate() method) that are dispatched to the AshmemRegion instances (which | 28 // Allocate() method) that are dispatched to the AshmemRegion instances (which |
| (...skipping 29 matching lines...) Expand all Loading... |
| 59 if (size > std::numeric_limits<size_t>::max() - kPageSize + 1) | 58 if (size > std::numeric_limits<size_t>::max() - kPageSize + 1) |
| 60 return 0; | 59 return 0; |
| 61 const size_t mask = ~(kPageSize - 1); | 60 const size_t mask = ~(kPageSize - 1); |
| 62 return (size + kPageSize - 1) & mask; | 61 return (size + kPageSize - 1) & mask; |
| 63 } | 62 } |
| 64 | 63 |
| 65 bool CreateAshmemRegion(const char* name, | 64 bool CreateAshmemRegion(const char* name, |
| 66 size_t size, | 65 size_t size, |
| 67 int* out_fd, | 66 int* out_fd, |
| 68 void** out_address) { | 67 void** out_address) { |
| 69 base::ScopedFD fd(ashmem_create_region(name, size)); | 68 int fd = ashmem_create_region(name, size); |
| 70 if (!fd.is_valid()) { | 69 if (fd < 0) { |
| 71 DLOG(ERROR) << "ashmem_create_region() failed"; | 70 DLOG(ERROR) << "ashmem_create_region() failed"; |
| 72 return false; | 71 return false; |
| 73 } | 72 } |
| 73 file_util::ScopedFD fd_closer(&fd); |
| 74 | 74 |
| 75 const int err = ashmem_set_prot_region(fd.get(), PROT_READ | PROT_WRITE); | 75 const int err = ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE); |
| 76 if (err < 0) { | 76 if (err < 0) { |
| 77 DLOG(ERROR) << "Error " << err << " when setting protection of ashmem"; | 77 DLOG(ERROR) << "Error " << err << " when setting protection of ashmem"; |
| 78 return false; | 78 return false; |
| 79 } | 79 } |
| 80 | 80 |
| 81 // There is a problem using MAP_PRIVATE here. As we are constantly calling | 81 // There is a problem using MAP_PRIVATE here. As we are constantly calling |
| 82 // Lock() and Unlock(), data could get lost if they are not written to the | 82 // Lock() and Unlock(), data could get lost if they are not written to the |
| 83 // underlying file when Unlock() gets called. | 83 // underlying file when Unlock() gets called. |
| 84 void* const address = mmap( | 84 void* const address = mmap( |
| 85 NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); | 85 NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); |
| 86 if (address == MAP_FAILED) { | 86 if (address == MAP_FAILED) { |
| 87 DPLOG(ERROR) << "Failed to map memory."; | 87 DPLOG(ERROR) << "Failed to map memory."; |
| 88 return false; | 88 return false; |
| 89 } | 89 } |
| 90 | 90 |
| 91 *out_fd = fd.release(); | 91 ignore_result(fd_closer.release()); |
| 92 *out_fd = fd; |
| 92 *out_address = address; | 93 *out_address = address; |
| 93 return true; | 94 return true; |
| 94 } | 95 } |
| 95 | 96 |
| 96 bool CloseAshmemRegion(int fd, size_t size, void* address) { | 97 bool CloseAshmemRegion(int fd, size_t size, void* address) { |
| 97 if (munmap(address, size) == -1) { | 98 if (munmap(address, size) == -1) { |
| 98 DPLOG(ERROR) << "Failed to unmap memory."; | 99 DPLOG(ERROR) << "Failed to unmap memory."; |
| 99 close(fd); | 100 close(fd); |
| 100 return false; | 101 return false; |
| 101 } | 102 } |
| (...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 550 DCHECK_LE(ashmem_regions_.size(), 5U); | 551 DCHECK_LE(ashmem_regions_.size(), 5U); |
| 551 const ScopedVector<AshmemRegion>::iterator it = std::find( | 552 const ScopedVector<AshmemRegion>::iterator it = std::find( |
| 552 ashmem_regions_.begin(), ashmem_regions_.end(), region); | 553 ashmem_regions_.begin(), ashmem_regions_.end(), region); |
| 553 DCHECK_NE(ashmem_regions_.end(), it); | 554 DCHECK_NE(ashmem_regions_.end(), it); |
| 554 std::swap(*it, ashmem_regions_.back()); | 555 std::swap(*it, ashmem_regions_.back()); |
| 555 ashmem_regions_.pop_back(); | 556 ashmem_regions_.pop_back(); |
| 556 } | 557 } |
| 557 | 558 |
| 558 } // namespace internal | 559 } // namespace internal |
| 559 } // namespace base | 560 } // namespace base |
| OLD | NEW |