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" |
19 #include "base/logging.h" | 20 #include "base/logging.h" |
20 #include "base/memory/discardable_memory.h" | 21 #include "base/memory/discardable_memory.h" |
21 #include "base/memory/scoped_vector.h" | 22 #include "base/memory/scoped_vector.h" |
22 #include "base/synchronization/lock.h" | 23 #include "base/synchronization/lock.h" |
23 #include "base/threading/thread_checker.h" | 24 #include "base/threading/thread_checker.h" |
24 #include "third_party/ashmem/ashmem.h" | 25 #include "third_party/ashmem/ashmem.h" |
25 | 26 |
26 // The allocator consists of three parts (classes): | 27 // The allocator consists of three parts (classes): |
27 // - DiscardableMemoryAllocator: entry point of all allocations (through its | 28 // - DiscardableMemoryAllocator: entry point of all allocations (through its |
28 // Allocate() method) that are dispatched to the AshmemRegion instances (which | 29 // Allocate() method) that are dispatched to the AshmemRegion instances (which |
(...skipping 29 matching lines...) Expand all Loading... |
58 if (size > std::numeric_limits<size_t>::max() - kPageSize + 1) | 59 if (size > std::numeric_limits<size_t>::max() - kPageSize + 1) |
59 return 0; | 60 return 0; |
60 const size_t mask = ~(kPageSize - 1); | 61 const size_t mask = ~(kPageSize - 1); |
61 return (size + kPageSize - 1) & mask; | 62 return (size + kPageSize - 1) & mask; |
62 } | 63 } |
63 | 64 |
64 bool CreateAshmemRegion(const char* name, | 65 bool CreateAshmemRegion(const char* name, |
65 size_t size, | 66 size_t size, |
66 int* out_fd, | 67 int* out_fd, |
67 void** out_address) { | 68 void** out_address) { |
68 int fd = ashmem_create_region(name, size); | 69 base::ScopedFD fd(ashmem_create_region(name, size)); |
69 if (fd < 0) { | 70 if (!fd.is_valid()) { |
70 DLOG(ERROR) << "ashmem_create_region() failed"; | 71 DLOG(ERROR) << "ashmem_create_region() failed"; |
71 return false; | 72 return false; |
72 } | 73 } |
73 file_util::ScopedFD fd_closer(&fd); | |
74 | 74 |
75 const int err = ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE); | 75 const int err = ashmem_set_prot_region(fd.get(), 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.get(), 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 ignore_result(fd_closer.release()); | 91 *out_fd = fd.release(); |
92 *out_fd = fd; | |
93 *out_address = address; | 92 *out_address = address; |
94 return true; | 93 return true; |
95 } | 94 } |
96 | 95 |
97 bool CloseAshmemRegion(int fd, size_t size, void* address) { | 96 bool CloseAshmemRegion(int fd, size_t size, void* address) { |
98 if (munmap(address, size) == -1) { | 97 if (munmap(address, size) == -1) { |
99 DPLOG(ERROR) << "Failed to unmap memory."; | 98 DPLOG(ERROR) << "Failed to unmap memory."; |
100 close(fd); | 99 close(fd); |
101 return false; | 100 return false; |
102 } | 101 } |
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
551 DCHECK_LE(ashmem_regions_.size(), 5U); | 550 DCHECK_LE(ashmem_regions_.size(), 5U); |
552 const ScopedVector<AshmemRegion>::iterator it = std::find( | 551 const ScopedVector<AshmemRegion>::iterator it = std::find( |
553 ashmem_regions_.begin(), ashmem_regions_.end(), region); | 552 ashmem_regions_.begin(), ashmem_regions_.end(), region); |
554 DCHECK_NE(ashmem_regions_.end(), it); | 553 DCHECK_NE(ashmem_regions_.end(), it); |
555 std::swap(*it, ashmem_regions_.back()); | 554 std::swap(*it, ashmem_regions_.back()); |
556 ashmem_regions_.pop_back(); | 555 ashmem_regions_.pop_back(); |
557 } | 556 } |
558 | 557 |
559 } // namespace internal | 558 } // namespace internal |
560 } // namespace base | 559 } // namespace base |
OLD | NEW |