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 |