15c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Copyright 2014 The Chromium Authors. All rights reserved.
25c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Use of this source code is governed by a BSD-style license that can be
35c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// found in the LICENSE file.
45c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
55c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#ifndef BASE_MEMORY_DISCARDABLE_MEMORY_ASHMEM_ALLOCATOR_H_
65c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#define BASE_MEMORY_DISCARDABLE_MEMORY_ASHMEM_ALLOCATOR_H_
75c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
85c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include <string>
95c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/base_export.h"
115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/basictypes.h"
125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/memory/scoped_ptr.h"
135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/memory/scoped_vector.h"
145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/synchronization/lock.h"
155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liunamespace base {
175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liunamespace internal {
185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuclass AshmemRegion;
205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Internal class, whose instances are returned to the client of the allocator
225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// (e.g. DiscardableMemoryAshmem), that mimicks the DiscardableMemory interface.
235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuclass BASE_EXPORT_PRIVATE DiscardableAshmemChunk {
245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu public:
255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ~DiscardableAshmemChunk();
265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Returns whether the memory is still resident.
285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  bool Lock();
295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void Unlock();
315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void* Memory() const;
335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu private:
355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  friend class AshmemRegion;
365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DiscardableAshmemChunk(AshmemRegion* ashmem_region,
385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                         int fd,
395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                         void* address,
405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                         size_t offset,
415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                         size_t size);
425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  AshmemRegion* const ashmem_region_;
445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const int fd_;
455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void* const address_;
465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const size_t offset_;
475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const size_t size_;
485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  bool locked_;
495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DISALLOW_COPY_AND_ASSIGN(DiscardableAshmemChunk);
515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu};
525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Ashmem regions are backed by a file (descriptor) therefore they are a limited
545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// resource. This allocator minimizes the problem by allocating large ashmem
555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// regions internally and returning smaller chunks to the client.
565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Allocated chunks are systematically aligned on a page boundary therefore this
575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// allocator should not be used for small allocations.
585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuclass BASE_EXPORT_PRIVATE DiscardableMemoryAshmemAllocator {
595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu public:
605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Note that |name| is only used for debugging/measurement purposes.
615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // |ashmem_region_size| is the size that will be used to create the underlying
625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // ashmem regions and is expected to be greater or equal than 32 MBytes.
635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DiscardableMemoryAshmemAllocator(const std::string& name,
645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                   size_t ashmem_region_size);
655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ~DiscardableMemoryAshmemAllocator();
675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Note that the allocator must outlive the returned DiscardableAshmemChunk
695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // instance.
705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<DiscardableAshmemChunk> Allocate(size_t size);
715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Returns the size of the last ashmem region which was created. This is used
735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // for testing only.
745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  size_t last_ashmem_region_size() const;
755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu private:
775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  friend class AshmemRegion;
785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void DeleteAshmemRegion_Locked(AshmemRegion* region);
805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const std::string name_;
825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const size_t ashmem_region_size_;
835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  mutable Lock lock_;
845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  size_t last_ashmem_region_size_;
855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ScopedVector<AshmemRegion> ashmem_regions_;
865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryAshmemAllocator);
885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu};
895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}  // namespace internal
915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}  // namespace base
925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#endif  // BASE_MEMORY_DISCARDABLE_MEMORY_ASHMEM_ALLOCATOR_H_
94