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 PARTITION_ALLOC_STARSCAN_PCSCAN_INTERNAL_H_ 6 #define PARTITION_ALLOC_STARSCAN_PCSCAN_INTERNAL_H_ 7 8 #include <array> 9 #include <functional> 10 #include <memory> 11 #include <mutex> 12 #include <unordered_map> 13 #include <utility> 14 #include <vector> 15 16 #include "partition_alloc/internal_allocator_forward.h" 17 #include "partition_alloc/partition_alloc_base/memory/scoped_refptr.h" 18 #include "partition_alloc/partition_alloc_base/no_destructor.h" 19 #include "partition_alloc/starscan/pcscan.h" 20 #include "partition_alloc/starscan/starscan_fwd.h" 21 #include "partition_alloc/starscan/write_protector.h" 22 23 namespace partition_alloc::internal { 24 25 class PCScanTask; 26 27 // Internal PCScan singleton. The separation between frontend and backend is 28 // needed to keep access to the hot data (quarantine) in the frontend fast, 29 // whereas the backend can hold cold data. 30 class PCScanInternal final { 31 public: 32 using Root = PCScan::Root; 33 using TaskHandle = scoped_refptr<PCScanTask>; 34 35 using SuperPages = 36 std::vector<uintptr_t, internal::InternalAllocator<uintptr_t>>; 37 using RootsMap = std::unordered_map< 38 Root*, 39 SuperPages, 40 std::hash<Root*>, 41 std::equal_to<>, 42 internal::InternalAllocator<std::pair<Root* const, SuperPages>>>; 43 Instance()44 static PCScanInternal& Instance() { 45 // Since the data that PCScanInternal holds is cold, it's fine to have the 46 // runtime check for thread-safe local static initialization. 47 static internal::base::NoDestructor<PCScanInternal> instance; 48 return *instance; 49 } 50 51 PCScanInternal(const PCScanInternal&) = delete; 52 PCScanInternal& operator=(const PCScanInternal&) = delete; 53 54 ~PCScanInternal(); 55 56 void Initialize(PCScan::InitConfig); is_initialized()57 bool is_initialized() const { return is_initialized_; } 58 59 void PerformScan(PCScan::InvocationMode); 60 void PerformScanIfNeeded(PCScan::InvocationMode); 61 void PerformDelayedScan(base::TimeDelta delay); 62 void JoinScan(); 63 64 TaskHandle CurrentPCScanTask() const; 65 void SetCurrentPCScanTask(TaskHandle task); 66 void ResetCurrentPCScanTask(); 67 68 void RegisterScannableRoot(Root*); 69 void RegisterNonScannableRoot(Root*); 70 scannable_roots()71 RootsMap& scannable_roots() { return scannable_roots_; } scannable_roots()72 const RootsMap& scannable_roots() const { return scannable_roots_; } 73 nonscannable_roots()74 RootsMap& nonscannable_roots() { return nonscannable_roots_; } nonscannable_roots()75 const RootsMap& nonscannable_roots() const { return nonscannable_roots_; } 76 77 void RegisterNewSuperPage(Root* root, uintptr_t super_page_base); 78 79 void SetProcessName(const char* name); process_name()80 const char* process_name() const { return process_name_; } 81 82 // Get size of all committed pages from scannable and nonscannable roots. 83 size_t CalculateTotalHeapSize() const; 84 simd_support()85 SimdSupport simd_support() const { return simd_support_; } 86 87 void EnableStackScanning(); 88 void DisableStackScanning(); 89 bool IsStackScanningEnabled() const; 90 EnableImmediateFreeing()91 void EnableImmediateFreeing() { immediate_freeing_enabled_ = true; } IsImmediateFreeingEnabled()92 bool IsImmediateFreeingEnabled() const { return immediate_freeing_enabled_; } 93 94 bool WriteProtectionEnabled() const; 95 void ProtectPages(uintptr_t begin, size_t size); 96 void UnprotectPages(uintptr_t begin, size_t size); 97 98 void ClearRootsForTesting(); // IN-TEST 99 void ReinitForTesting(PCScan::InitConfig); // IN-TEST 100 void FinishScanForTesting(); // IN-TEST 101 102 void RegisterStatsReporter(partition_alloc::StatsReporter* reporter); 103 partition_alloc::StatsReporter& GetReporter(); 104 105 private: 106 friend internal::base::NoDestructor<PCScanInternal>; 107 friend class StarScanSnapshot; 108 109 PCScanInternal(); 110 111 TaskHandle current_task_; 112 mutable std::mutex current_task_mutex_; 113 114 RootsMap scannable_roots_; 115 RootsMap nonscannable_roots_; 116 mutable std::mutex roots_mutex_; 117 118 bool stack_scanning_enabled_{false}; 119 120 bool immediate_freeing_enabled_{false}; 121 122 const char* process_name_ = nullptr; 123 const SimdSupport simd_support_; 124 125 std::unique_ptr<WriteProtector> write_protector_; 126 partition_alloc::StatsReporter* stats_reporter_ = nullptr; 127 128 bool is_initialized_ = false; 129 }; 130 131 } // namespace partition_alloc::internal 132 133 #endif // PARTITION_ALLOC_STARSCAN_PCSCAN_INTERNAL_H_ 134