Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2490)

Unified Diff: base/memory/discardable_memory_android.cc

Issue 25293002: Add DiscardableMemoryAllocator to work around FD limit issue. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address reviewers' comments Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: base/memory/discardable_memory_android.cc
diff --git a/base/memory/discardable_memory_android.cc b/base/memory/discardable_memory_android.cc
index b88a13611b9c7a0488a4fd6a76751201e4b1bdf5..b2ec9bf69855f7522682cc3d8b76c887650348d1 100644
--- a/base/memory/discardable_memory_android.cc
+++ b/base/memory/discardable_memory_android.cc
@@ -2,9 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/memory/discardable_memory.h"
+#include "base/memory/discardable_memory_android.h"
#include <sys/mman.h>
+#include <sys/resource.h>
+#include <sys/time.h>
#include <unistd.h>
#include "base/basictypes.h"
@@ -12,6 +14,7 @@
#include "base/file_util.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
+#include "base/memory/discardable_memory.h"
#include "base/posix/eintr_wrapper.h"
#include "base/synchronization/lock.h"
#include "third_party/ashmem/ashmem.h"
@@ -19,23 +22,96 @@
namespace base {
namespace {
-// Protects |g_num_discardable_memory| below.
-base::LazyInstance<base::Lock>::Leaky g_discardable_memory_lock =
- LAZY_INSTANCE_INITIALIZER;
+struct GlobalContext {
+ GlobalContext() : ashmem_fd_limit(GetSoftFDLimit()), ashmem_fd_count_(0) {}
+
+ const int ashmem_fd_limit;
+ base::Lock lock;
+
+ int ashmem_fd_count() const {
+ lock.AssertAcquired();
+ return ashmem_fd_count_;
+ }
+
+ void decrement_ahmem_fd_count() {
+ lock.AssertAcquired();
+ --ashmem_fd_count_;
+ }
+
+ void increment_ahmem_fd_count() {
+ lock.AssertAcquired();
+ ++ashmem_fd_count_;
+ }
-// Total number of discardable memory in the process.
-int g_num_discardable_memory = 0;
+ private:
+ static int GetSoftFDLimit() {
+ struct rlimit limit_info;
+ if (getrlimit(RLIMIT_NOFILE, &limit_info) != 0)
+ return 128;
+ // Allow 25% of file descriptor capacity for ashmem.
+ return limit_info.rlim_cur / 4;
+ }
-// Upper limit on the number of discardable memory to avoid hitting file
-// descriptor limit.
-const int kDiscardableMemoryNumLimit = 128;
+ int ashmem_fd_count_;
+};
+
+base::LazyInstance<GlobalContext>::Leaky g_context = LAZY_INSTANCE_INITIALIZER;
+
+class DiscardableMemoryAndroid : public DiscardableMemory {
+ public:
+ DiscardableMemoryAndroid(int fd, void* address, size_t size)
+ : fd_(fd),
+ memory_(address),
+ size_(size) {
+ DCHECK_GE(fd_, 0);
+ DCHECK(memory_);
+ }
+
+ virtual ~DiscardableMemoryAndroid() {
+ internal::DeleteAshmemRegion(fd_, size_, memory_);
+ }
+
+ // DiscardableMemory:
+ virtual size_t Size() const OVERRIDE {
+ return size_;
+ }
+
+ virtual LockDiscardableMemoryStatus Lock() OVERRIDE {
+ return internal::LockAshmemRegion(fd_, 0, size_, memory_);
+ }
+
+ virtual void Unlock() OVERRIDE {
+ internal::UnlockAshmemRegion(fd_, 0, size_, memory_);
+ }
+
+ virtual void* Memory() const OVERRIDE {
+ return memory_;
+ }
+
+ private:
+ const int fd_;
+ void* const memory_;
+ const size_t size_;
+
+ DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryAndroid);
+};
+
+} // namespace
+
+namespace internal {
+
+size_t PageAlign(size_t size) {
pasko 2013/10/22 20:14:29 nit: naming: this is not just aligning to page bou
+ const size_t kPageSize = 4096;
+ const size_t mask = ~(kPageSize - 1);
+ return (size + kPageSize - 1) & mask;
+}
bool CreateAshmemRegion(const char* name,
size_t size,
int* out_fd,
void** out_address) {
- base::AutoLock lock(g_discardable_memory_lock.Get());
- if (g_num_discardable_memory + 1 > kDiscardableMemoryNumLimit)
+ base::AutoLock lock(g_context.Get().lock);
+ if (g_context.Get().ashmem_fd_count() + 1 > g_context.Get().ashmem_fd_limit)
return false;
int fd = ashmem_create_region(name, size);
if (fd < 0) {
@@ -61,15 +137,15 @@ bool CreateAshmemRegion(const char* name,
}
ignore_result(fd_closer.release());
- ++g_num_discardable_memory;
+ g_context.Get().increment_ahmem_fd_count();
*out_fd = fd;
*out_address = address;
return true;
}
bool DeleteAshmemRegion(int fd, size_t size, void* address) {
- base::AutoLock lock(g_discardable_memory_lock.Get());
- --g_num_discardable_memory;
+ base::AutoLock lock(g_context.Get().lock);
+ g_context.Get().decrement_ahmem_fd_count();
if (munmap(address, size) == -1) {
DPLOG(ERROR) << "Failed to unmap memory.";
close(fd);
@@ -97,42 +173,16 @@ bool UnlockAshmemRegion(int fd, size_t off, size_t size, const void* address) {
return !failed;
}
-class DiscardableMemoryAndroid : public DiscardableMemory {
- public:
- DiscardableMemoryAndroid(int fd, void* address, size_t size)
- : fd_(fd),
- memory_(address),
- size_(size) {
- DCHECK_GE(fd_, 0);
- DCHECK(memory_);
- }
-
- virtual ~DiscardableMemoryAndroid() {
- DeleteAshmemRegion(fd_, size_, memory_);
- }
-
- // DiscardableMemory:
- virtual LockDiscardableMemoryStatus Lock() OVERRIDE {
- return LockAshmemRegion(fd_, 0, size_, memory_);
- }
-
- virtual void Unlock() OVERRIDE {
- UnlockAshmemRegion(fd_, 0, size_, memory_);
- }
-
- virtual void* Memory() const OVERRIDE {
- return memory_;
- }
-
- private:
- const int fd_;
- void* const memory_;
- const size_t size_;
+int GetAshmemFDLimit() {
+ return g_context.Get().ashmem_fd_limit;
+}
- DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryAndroid);
-};
+int GetCurrentNumberOfAshmemFDs() {
+ base::AutoLock lock(g_context.Get().lock);
+ return g_context.Get().ashmem_fd_count();
+}
-} // namespace
+} // namespace internal
// static
bool DiscardableMemory::Supported() {
@@ -144,12 +194,10 @@ scoped_ptr<DiscardableMemory> DiscardableMemory::CreateLockedMemory(
size_t size) {
// Pinning & unpinning works with page granularity therefore align the size
// upfront.
- const size_t kPageSize = 4096;
- const size_t mask = ~(kPageSize - 1);
- size = (size + kPageSize - 1) & mask;
+ size = internal::PageAlign(size);
int fd;
void* address;
- if (!CreateAshmemRegion("", size, &fd, &address))
+ if (!internal::CreateAshmemRegion("", size, &fd, &address))
return scoped_ptr<DiscardableMemory>();
return scoped_ptr<DiscardableMemory>(
new DiscardableMemoryAndroid(fd, address, size));

Powered by Google App Engine
This is Rietveld 408576698