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