• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 The Chromium Authors
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_ALLOC_SUPPORT_H_
6 #define BASE_ALLOCATOR_PARTITION_ALLOC_SUPPORT_H_
7 
8 #include <map>
9 #include <string>
10 
11 #include "base/base_export.h"
12 #include "base/feature_list.h"
13 #include "base/memory/scoped_refptr.h"
14 #include "base/synchronization/lock.h"
15 #include "base/task/sequenced_task_runner.h"
16 #include "base/thread_annotations.h"
17 #include "partition_alloc/buildflags.h"
18 #include "partition_alloc/partition_alloc_config.h"
19 #include "partition_alloc/thread_cache.h"
20 
21 namespace base::allocator {
22 
23 // Starts a periodic timer on the current thread to purge all thread caches.
24 BASE_EXPORT void StartThreadCachePeriodicPurge();
25 
26 BASE_EXPORT void StartMemoryReclaimer(
27     scoped_refptr<SequencedTaskRunner> task_runner);
28 
29 BASE_EXPORT std::map<std::string, std::string> ProposeSyntheticFinchTrials();
30 
31 // Install handlers for when dangling raw_ptr(s) have been detected. This prints
32 // two StackTraces. One where the memory is freed, one where the last dangling
33 // raw_ptr stopped referencing it.
34 //
35 // This is currently effective, only when compiled with
36 // `enable_dangling_raw_ptr_checks` build flag.
37 BASE_EXPORT void InstallDanglingRawPtrChecks();
38 BASE_EXPORT void InstallUnretainedDanglingRawPtrChecks();
39 
40 // Once called, makes `free()` do nothing. This is done to reduce
41 // shutdown hangs on CrOS.
42 // Does nothing if Dangling Pointer Detector (`docs/dangling_ptr.md`)
43 // is not active.
44 // Does nothing if allocator shim support is not built.
45 BASE_EXPORT void MakeFreeNoOp();
46 
47 // Allows to re-configure PartitionAlloc at run-time.
48 class BASE_EXPORT PartitionAllocSupport {
49  public:
50   struct BrpConfiguration {
51     bool enable_brp = false;
52     bool process_affected_by_brp_flag = false;
53   };
54 
55   // Reconfigure* functions re-configure PartitionAlloc. It is impossible to
56   // configure PartitionAlloc before/at its initialization using information not
57   // known at compile-time (e.g. process type, Finch), because by the time this
58   // information is available memory allocations would have surely happened,
59   // that requiring a functioning allocator.
60   //
61   // *Earlyish() is called as early as it is reasonably possible.
62   // *AfterZygoteFork() is its complement to finish configuring process-specific
63   // stuff that had to be postponed due to *Earlyish() being called with
64   // |process_type==kZygoteProcess|.
65   // *AfterFeatureListInit() is called in addition to the above, once
66   // FeatureList has been initialized and ready to use. It is guaranteed to be
67   // called on non-zygote processes or after the zygote has been forked.
68   // *AfterTaskRunnerInit() is called once it is possible to post tasks, and
69   // after the previous steps.
70   //
71   // *Earlyish() must be called exactly once. *AfterZygoteFork() must be called
72   // once iff *Earlyish() was called before with |process_type==kZygoteProcess|.
73   //
74   // *AfterFeatureListInit() may be called more than once, but will perform its
75   // re-configuration steps exactly once.
76   //
77   // *AfterTaskRunnerInit() may be called more than once.
78   void ReconfigureForTests();
79   void ReconfigureEarlyish(const std::string& process_type);
80   void ReconfigureAfterZygoteFork(const std::string& process_type);
81   void ReconfigureAfterFeatureListInit(
82       const std::string& process_type,
83       bool configure_dangling_pointer_detector = true);
84   void ReconfigureAfterTaskRunnerInit(const std::string& process_type);
85 
86   // |has_main_frame| tells us if the renderer contains a main frame.
87   // The default value is intended for other process types, where the parameter
88   // does not make sense.
89   void OnForegrounded(bool has_main_frame = false);
90   void OnBackgrounded();
91 
92 #if PA_BUILDFLAG(ENABLE_DANGLING_RAW_PTR_CHECKS)
93   static std::string ExtractDanglingPtrSignatureForTests(
94       std::string stacktrace);
95 #endif
96 
97   static PartitionAllocSupport* Get();
98 
99   static BrpConfiguration GetBrpConfiguration(const std::string& process_type);
100 
101   // Returns true if memory tagging should be enabled if available for the given
102   // process type. May be called multiple times per process.
103   static bool ShouldEnableMemoryTagging(const std::string& process_type);
104 
105   // For calling from within third_party/blink/.
106   static bool ShouldEnableMemoryTaggingInRendererProcess();
107 
108   // Returns true if PA advanced checks should be enabled if available for the
109   // given process type. May be called multiple times per process.
110   static bool ShouldEnablePartitionAllocWithAdvancedChecks(
111       const std::string& process_type);
112 
113  private:
114   PartitionAllocSupport();
115 
116   base::Lock lock_;
117   bool called_for_tests_ GUARDED_BY(lock_) = false;
118   bool called_earlyish_ GUARDED_BY(lock_) = false;
119   bool called_after_zygote_fork_ GUARDED_BY(lock_) = false;
120   bool called_after_feature_list_init_ GUARDED_BY(lock_) = false;
121   bool called_after_thread_pool_init_ GUARDED_BY(lock_) = false;
122   std::string established_process_type_ GUARDED_BY(lock_) = "INVALID";
123 
124 #if PA_CONFIG(THREAD_CACHE_SUPPORTED) && \
125     PA_BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
126   size_t largest_cached_size_ =
127       ::partition_alloc::kThreadCacheDefaultSizeThreshold;
128 #endif
129 };
130 
131 BASE_EXPORT BASE_DECLARE_FEATURE(kDisableMemoryReclaimerInBackground);
132 
133 // Visible in header for testing.
134 class BASE_EXPORT MemoryReclaimerSupport {
135  public:
136   static MemoryReclaimerSupport& Instance();
137   MemoryReclaimerSupport();
138   ~MemoryReclaimerSupport();
139   void Start(scoped_refptr<TaskRunner> task_runner);
140   void SetForegrounded(bool in_foreground);
141 
142   void ResetForTesting();
has_pending_task_for_testing()143   bool has_pending_task_for_testing() const { return has_pending_task_; }
144   static TimeDelta GetInterval();
145 
146   // Visible for testing
147   static constexpr base::TimeDelta kFirstPAPurgeOrReclaimDelay =
148       base::Minutes(1);
149 
150  private:
151   void Run();
152   void MaybeScheduleTask(TimeDelta delay = TimeDelta());
153 
154   scoped_refptr<TaskRunner> task_runner_;
155   bool in_foreground_ = true;
156   bool has_pending_task_ = false;
157 };
158 
159 }  // namespace base::allocator
160 
161 #endif  // BASE_ALLOCATOR_PARTITION_ALLOC_SUPPORT_H_
162