1 // Copyright 2019 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 
5 #ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_MEMORY_RECLAIMER_H_
6 #define BASE_ALLOCATOR_PARTITION_ALLOCATOR_MEMORY_RECLAIMER_H_
7 
8 #include <memory>
9 #include <set>
10 
11 #include "base/bind.h"
12 #include "base/callback.h"
13 #include "base/location.h"
14 #include "base/no_destructor.h"
15 #include "base/single_thread_task_runner.h"
16 #include "base/thread_annotations.h"
17 #include "base/time/time.h"
18 #include "base/timer/elapsed_timer.h"
19 #include "base/timer/timer.h"
20 
21 namespace base {
22 
23 namespace internal {
24 
25 struct PartitionRootBase;
26 
27 }  // namespace internal
28 
29 // Posts and handles memory reclaim tasks for PartitionAlloc.
30 //
31 // Thread safety: |RegisterPartition()| and |UnregisterPartition()| can be
32 // called from any thread, concurrently with reclaim. Reclaim itself runs in the
33 // context of the provided |SequencedTaskRunner|, meaning that the caller must
34 // take care of this runner being compatible with the various partitions.
35 //
36 // Singleton as this runs as long as the process is alive, and
37 // having multiple instances would be wasteful.
38 class BASE_EXPORT PartitionAllocMemoryReclaimer {
39  public:
40   static PartitionAllocMemoryReclaimer* Instance();
41 
42   // Internal. Do not use.
43   // Registers a partition to be tracked by the reclaimer.
44   void RegisterPartition(internal::PartitionRootBase* partition);
45   // Internal. Do not use.
46   // Unregisters a partition to be tracked by the reclaimer.
47   void UnregisterPartition(internal::PartitionRootBase* partition);
48   // Starts the periodic reclaim. Should be called once.
49   void Start(scoped_refptr<SequencedTaskRunner> task_runner);
50   // Triggers an explicit reclaim now.
51   void Reclaim();
52 
53   static constexpr TimeDelta kStatsRecordingTimeDelta =
54       TimeDelta::FromMinutes(5);
55 
56  private:
57   PartitionAllocMemoryReclaimer();
58   ~PartitionAllocMemoryReclaimer();
59   void ReclaimAndReschedule();
60   void RecordStatistics();
61   void ResetForTesting();
62 
63   // Total time spent in |Reclaim()|.
64   bool has_called_reclaim_ = false;
65   TimeDelta total_reclaim_thread_time_;
66   // Schedules periodic |Reclaim()|.
67   std::unique_ptr<RepeatingTimer> timer_;
68 
69   Lock lock_;
70   std::set<internal::PartitionRootBase*> partitions_ GUARDED_BY(lock_);
71 
72   friend class NoDestructor<PartitionAllocMemoryReclaimer>;
73   friend class PartitionAllocMemoryReclaimerTest;
74   DISALLOW_COPY_AND_ASSIGN(PartitionAllocMemoryReclaimer);
75 };
76 
77 }  // namespace base
78 
79 #endif  // BASE_ALLOCATOR_PARTITION_ALLOCATOR_MEMORY_RECLAIMER_H_
80