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 #ifndef BASE_UTIL_MEMORY_PRESSURE_SYSTEM_MEMORY_PRESSURE_EVALUATOR_CHROMEOS_H_ 5 #define BASE_UTIL_MEMORY_PRESSURE_SYSTEM_MEMORY_PRESSURE_EVALUATOR_CHROMEOS_H_ 6 7 #include <vector> 8 9 #include "base/base_export.h" 10 #include "base/feature_list.h" 11 #include "base/files/scoped_file.h" 12 #include "base/macros.h" 13 #include "base/memory/memory_pressure_listener.h" 14 #include "base/memory/weak_ptr.h" 15 #include "base/process/process_metrics.h" 16 #include "base/time/time.h" 17 #include "base/timer/timer.h" 18 #include "base/util/memory_pressure/memory_pressure_voter.h" 19 #include "base/util/memory_pressure/system_memory_pressure_evaluator.h" 20 21 namespace util { 22 namespace chromeos { 23 24 // A feature which controls user space low memory notification. 25 extern const base::Feature kCrOSUserSpaceLowMemoryNotification; 26 27 //////////////////////////////////////////////////////////////////////////////// 28 // SystemMemoryPressureEvaluator 29 // 30 // A class to handle the observation of our free memory. It notifies the 31 // MemoryPressureListener of memory fill level changes, so that it can take 32 // action to reduce memory resources accordingly. 33 class SystemMemoryPressureEvaluator 34 : public util::SystemMemoryPressureEvaluator { 35 public: 36 // The SystemMemoryPressureEvaluator reads the pressure levels from the 37 // /sys/kernel/mm/chromeos-low_mem/margin and does not need to be configured. 38 // 39 // NOTE: You should check that the kernel supports notifications by calling 40 // SupportsKernelNotifications() before constructing a new instance of this 41 // class. 42 explicit SystemMemoryPressureEvaluator( 43 std::unique_ptr<MemoryPressureVoter> voter); 44 ~SystemMemoryPressureEvaluator() override; 45 46 // GetMarginFileParts returns a vector of the configured margin file values. 47 // The margin file contains two or more values, but we're only concerned with 48 // the first two. The first represents critical memory pressure, the second 49 // is moderate memory pressure level. 50 static std::vector<int> GetMarginFileParts(); 51 52 // GetAvailableMemoryKB returns the available memory in KiB. 53 uint64_t GetAvailableMemoryKB(); 54 55 // SupportsKernelNotifications will return true if the kernel supports and is 56 // configured for notifications on memory availability changes. 57 static bool SupportsKernelNotifications(); 58 59 // ScheduleEarlyCheck is used by the ChromeOS tab manager delegate to force it 60 // to quickly recheck pressure levels after a tab discard or some other 61 // action. 62 void ScheduleEarlyCheck(); 63 64 // Returns the moderate pressure threshold as read from the margin file. ModeratePressureThresholdMBForTesting()65 int ModeratePressureThresholdMBForTesting() const { 66 return moderate_pressure_threshold_mb_; 67 } 68 69 // Returns the critical pressure threshold as read from the margin file. CriticalPressureThresholdMBForTesting()70 int CriticalPressureThresholdMBForTesting() const { 71 return critical_pressure_threshold_mb_; 72 } 73 74 // The memory parameters are saved for optimization. If these memory 75 // parameters are changed, call this function to update the saved values. 76 void UpdateMemoryParameters(); 77 78 // Returns the current system memory pressure evaluator. 79 static SystemMemoryPressureEvaluator* Get(); 80 81 protected: 82 // This constructor is only used for testing. 83 SystemMemoryPressureEvaluator( 84 const std::string& margin_file, 85 const std::string& available_file, 86 base::RepeatingCallback<bool(int)> kernel_waiting_callback, 87 bool disable_timer_for_testing, 88 bool is_user_space_notify, 89 std::unique_ptr<MemoryPressureVoter> voter); 90 91 static std::vector<int> GetMarginFileParts(const std::string& margin_file); 92 93 static uint64_t CalculateReservedFreeKB(const std::string& zoneinfo); 94 95 static uint64_t GetReservedMemoryKB(); 96 97 static uint64_t CalculateAvailableMemoryUserSpaceKB( 98 const base::SystemMemoryInfoKB& info, 99 uint64_t reserved_free, 100 uint64_t min_filelist, 101 uint64_t ram_swap_weight); 102 103 void CheckMemoryPressure(); 104 105 private: 106 void HandleKernelNotification(bool result); 107 void ScheduleWaitForKernelNotification(); 108 void CheckMemoryPressureAndRecordStatistics(); 109 int moderate_pressure_threshold_mb_ = 0; 110 int critical_pressure_threshold_mb_ = 0; 111 112 // We keep track of how long it has been since we last notified at the 113 // moderate level. 114 base::TimeTicks last_moderate_notification_; 115 116 // We keep track of how long it's been since we notified on the 117 // Memory.PressureLevel metric. 118 base::TimeTicks last_pressure_level_report_; 119 120 // File descriptor used to read and poll(2) available memory from sysfs, 121 // In /sys/kernel/mm/chromeos-low_mem/available. 122 base::ScopedFD available_mem_file_; 123 124 // A timer to check the memory pressure and to report an UMA metric 125 // periodically. 126 base::RepeatingTimer checking_timer_; 127 128 // Kernel waiting callback which is responsible for blocking on the 129 // available file until it receives a kernel notification, this is 130 // configurable to make testing easier. 131 base::RepeatingCallback<bool()> kernel_waiting_callback_; 132 133 // User space low memory notification mode. 134 const bool is_user_space_notify_; 135 136 // Values saved for user space available memory calculation. The value of 137 // |reserved_free_| should not change unless min_free_kbytes or 138 // lowmem_reserve_ratio change. The value of |min_filelist_| and 139 // |ram_swap_weight_| should not change unless the user sets them manually. 140 uint64_t reserved_free_; 141 uint64_t min_filelist_; 142 uint64_t ram_swap_weight_; 143 144 SEQUENCE_CHECKER(sequence_checker_); 145 146 base::WeakPtrFactory<SystemMemoryPressureEvaluator> weak_ptr_factory_; 147 148 DISALLOW_COPY_AND_ASSIGN(SystemMemoryPressureEvaluator); 149 }; 150 151 } // namespace chromeos 152 } // namespace util 153 #endif // BASE_UTIL_MEMORY_PRESSURE_SYSTEM_MEMORY_PRESSURE_EVALUATOR_CHROMEOS_H_ 154