client_discardable_shared_memory_manager.h 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef COMPONENTS_DISCARDABLE_MEMORY_CLIENT_CLIENT_DISCARDABLE_SHARED_MEMORY_MANAGER_H_
  5. #define COMPONENTS_DISCARDABLE_MEMORY_CLIENT_CLIENT_DISCARDABLE_SHARED_MEMORY_MANAGER_H_
  6. #include <stddef.h>
  7. #include <memory>
  8. #include <set>
  9. #include "base/callback_helpers.h"
  10. #include "base/memory/discardable_memory_allocator.h"
  11. #include "base/memory/ref_counted_delete_on_sequence.h"
  12. #include "base/memory/unsafe_shared_memory_region.h"
  13. #include "base/synchronization/lock.h"
  14. #include "base/threading/thread_checker.h"
  15. #include "base/trace_event/memory_dump_provider.h"
  16. #include "components/discardable_memory/common/discardable_memory_export.h"
  17. #include "components/discardable_memory/common/discardable_shared_memory_heap.h"
  18. #include "components/discardable_memory/public/mojom/discardable_shared_memory_manager.mojom.h"
  19. #include "mojo/public/cpp/bindings/pending_remote.h"
  20. #include "mojo/public/cpp/bindings/remote.h"
  21. namespace base {
  22. class SingleThreadTaskRunner;
  23. }
  24. namespace discardable_memory {
  25. // Implementation of DiscardableMemoryAllocator that allocates
  26. // discardable memory segments through the browser process.
  27. class DISCARDABLE_MEMORY_EXPORT ClientDiscardableSharedMemoryManager
  28. : public base::DiscardableMemoryAllocator,
  29. public base::trace_event::MemoryDumpProvider,
  30. public base::RefCountedDeleteOnSequence<
  31. ClientDiscardableSharedMemoryManager> {
  32. public:
  33. ClientDiscardableSharedMemoryManager(
  34. mojo::PendingRemote<mojom::DiscardableSharedMemoryManager> manager,
  35. scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
  36. ClientDiscardableSharedMemoryManager(
  37. const ClientDiscardableSharedMemoryManager&) = delete;
  38. ClientDiscardableSharedMemoryManager& operator=(
  39. const ClientDiscardableSharedMemoryManager&) = delete;
  40. // Overridden from base::DiscardableMemoryAllocator:
  41. std::unique_ptr<base::DiscardableMemory> AllocateLockedDiscardableMemory(
  42. size_t size) override LOCKS_EXCLUDED(lock_);
  43. // Overridden from base::DiscardableMemoryAllocator:
  44. size_t GetBytesAllocated() const override LOCKS_EXCLUDED(lock_);
  45. // Overridden from base::DiscardableMemoryAllocator:
  46. // Release memory and associated resources that have been purged.
  47. void ReleaseFreeMemory() override LOCKS_EXCLUDED(lock_);
  48. // Overridden from base::trace_event::MemoryDumpProvider:
  49. bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
  50. base::trace_event::ProcessMemoryDump* pmd) override
  51. LOCKS_EXCLUDED(lock_);
  52. // Purge all unlocked memory that was allocated by this manager.
  53. void BackgroundPurge();
  54. // Change the state of this to either backgrounded or foregrounded. These
  55. // states should match the state that is found in |RenderThreadImpl|. We
  56. // initially set the state to backgrounded, since we may not know the state we
  57. // are in when we construct this. This avoids accidentally collecting data
  58. // from this while we are in the background, at the cost of potentially losing
  59. // some data near the time this is created.
  60. void OnForegrounded();
  61. void OnBackgrounded();
  62. void SetBytesAllocatedLimitForTesting(size_t limit) {
  63. bytes_allocated_limit_for_testing_ = limit;
  64. }
  65. // Anything younger than |kMinAgeForScheduledPurge| is not discarded when we
  66. // do our periodic purge.
  67. static constexpr base::TimeDelta kMinAgeForScheduledPurge = base::Minutes(5);
  68. // The expected cost of purging should be very small (< 1ms), so it can be
  69. // scheduled frequently. However, we don't purge memory that has been touched
  70. // recently (see: |BackgroundPurge()| and |kMinAgeForScheduledPurge|), so
  71. // there is no benefit to scheduling this more than once per minute.
  72. static constexpr base::TimeDelta kScheduledPurgeInterval = base::Minutes(1);
  73. // These fields are only protected for testing, they would otherwise be
  74. // private. Everything else should be either public or private.
  75. protected:
  76. friend class base::RefCountedDeleteOnSequence<
  77. ClientDiscardableSharedMemoryManager>;
  78. friend class base::DeleteHelper<ClientDiscardableSharedMemoryManager>;
  79. ~ClientDiscardableSharedMemoryManager() override;
  80. explicit ClientDiscardableSharedMemoryManager(
  81. scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
  82. scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
  83. mutable base::Lock lock_;
  84. std::unique_ptr<DiscardableSharedMemoryHeap> heap_ GUARDED_BY(lock_);
  85. bool is_purge_scheduled_ GUARDED_BY(lock_) = false;
  86. private:
  87. friend class TestClientDiscardableSharedMemoryManager;
  88. class DiscardableMemoryImpl : public base::DiscardableMemory {
  89. public:
  90. DiscardableMemoryImpl(
  91. ClientDiscardableSharedMemoryManager* manager,
  92. std::unique_ptr<DiscardableSharedMemoryHeap::Span> span);
  93. ~DiscardableMemoryImpl() override;
  94. DiscardableMemoryImpl(const DiscardableMemoryImpl&) = delete;
  95. DiscardableMemoryImpl& operator=(const DiscardableMemoryImpl&) = delete;
  96. // Overridden from base::DiscardableMemory:
  97. bool Lock() override LOCKS_EXCLUDED(manager_->lock_);
  98. void Unlock() override LOCKS_EXCLUDED(manager_->lock_);
  99. void* data() const override LOCKS_EXCLUDED(manager_->lock_);
  100. void DiscardForTesting() override LOCKS_EXCLUDED(manager_->lock_);
  101. base::trace_event::MemoryAllocatorDump* CreateMemoryAllocatorDump(
  102. const char* name,
  103. base::trace_event::ProcessMemoryDump* pmd) const override;
  104. // Returns |span_| if it has been unlocked since at least |min_ticks|,
  105. // otherwise nullptr.
  106. std::unique_ptr<DiscardableSharedMemoryHeap::Span> Purge(
  107. base::TimeTicks min_ticks) EXCLUSIVE_LOCKS_REQUIRED(manager_->lock_);
  108. private:
  109. bool is_locked() const EXCLUSIVE_LOCKS_REQUIRED(manager_->lock_);
  110. friend class ClientDiscardableSharedMemoryManager;
  111. // We need to ensure that |manager_| outlives |this|, to avoid a
  112. // use-after-free.
  113. scoped_refptr<ClientDiscardableSharedMemoryManager> const manager_;
  114. std::unique_ptr<DiscardableSharedMemoryHeap::Span> span_;
  115. // Set to an invalid base::TimeTicks when |this| is Lock()-ed, and to
  116. // |TimeTicks::Now()| each time |this| is Unlock()-ed.
  117. base::TimeTicks last_locked_ GUARDED_BY(manager_->lock_);
  118. };
  119. struct Statistics {
  120. size_t total_size;
  121. size_t freelist_size;
  122. };
  123. base::trace_event::MemoryAllocatorDump* CreateMemoryAllocatorDump(
  124. DiscardableSharedMemoryHeap::Span* span,
  125. const char* name,
  126. base::trace_event::ProcessMemoryDump* pmd) const
  127. EXCLUSIVE_LOCKS_REQUIRED(lock_);
  128. // Purge any unlocked memory from foreground that hasn't been touched in a
  129. // while.
  130. void ScheduledPurge() LOCKS_EXCLUDED(lock_);
  131. // This is only virtual for testing.
  132. virtual std::unique_ptr<base::DiscardableSharedMemory>
  133. AllocateLockedDiscardableSharedMemory(size_t size, int32_t id);
  134. void AllocateOnIO(size_t size,
  135. int32_t id,
  136. base::UnsafeSharedMemoryRegion* region,
  137. base::ScopedClosureRunner closure_runner);
  138. void AllocateCompletedOnIO(base::UnsafeSharedMemoryRegion* region,
  139. base::ScopedClosureRunner closure_runner,
  140. base::UnsafeSharedMemoryRegion ret_region);
  141. // This is only virtual for testing.
  142. virtual void DeletedDiscardableSharedMemory(int32_t id);
  143. void MemoryUsageChanged(size_t new_bytes_allocated,
  144. size_t new_bytes_free) const;
  145. // Releases all unlocked memory that was last locked at least |min_age| ago.
  146. void PurgeUnlockedMemory(base::TimeDelta min_age) LOCKS_EXCLUDED(lock_);
  147. bool LockSpan(DiscardableSharedMemoryHeap::Span* span)
  148. EXCLUSIVE_LOCKS_REQUIRED(lock_);
  149. void UnlockSpan(DiscardableSharedMemoryHeap::Span* span)
  150. EXCLUSIVE_LOCKS_REQUIRED(lock_);
  151. void UnlockAndReleaseMemory(
  152. DiscardableMemoryImpl* memory,
  153. std::unique_ptr<DiscardableSharedMemoryHeap::Span> span)
  154. EXCLUSIVE_LOCKS_REQUIRED(lock_);
  155. void ReleaseSpan(std::unique_ptr<DiscardableSharedMemoryHeap::Span> span)
  156. EXCLUSIVE_LOCKS_REQUIRED(lock_);
  157. size_t GetBytesAllocatedLocked() const EXCLUSIVE_LOCKS_REQUIRED(lock_);
  158. scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
  159. // TODO(penghuang): Switch to SharedRemote when it starts supporting
  160. // sync method call.
  161. std::unique_ptr<mojo::Remote<mojom::DiscardableSharedMemoryManager>>
  162. manager_mojo_;
  163. // Holds all locked and unlocked instances which have not yet been purged.
  164. std::set<DiscardableMemoryImpl*> allocated_memory_ GUARDED_BY(lock_);
  165. size_t bytes_allocated_limit_for_testing_ = 0;
  166. // Used in metrics to distinguish in-use consumers from background ones. We
  167. // initialize this to false to avoid getting any data before we are certain
  168. // we're in the foreground. This is parallel to what we do in
  169. // RenderThreadImpl.
  170. bool foregrounded_ = false;
  171. THREAD_CHECKER(thread_checker_);
  172. };
  173. } // namespace discardable_memory
  174. #endif // COMPONENTS_DISCARDABLE_MEMORY_CLIENT_CLIENT_DISCARDABLE_SHARED_MEMORY_MANAGER_H_