1 // Copyright 2014 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 CHROME_BROWSER_CHROMEOS_POWER_CPU_DATA_COLLECTOR_H_ 6 #define CHROME_BROWSER_CHROMEOS_POWER_CPU_DATA_COLLECTOR_H_ 7 8 #include <stdint.h> 9 10 #include <map> 11 #include <string> 12 #include <vector> 13 14 #include "base/containers/circular_deque.h" 15 #include "base/files/file_util.h" 16 #include "base/macros.h" 17 #include "base/memory/weak_ptr.h" 18 #include "base/time/time.h" 19 #include "base/timer/timer.h" 20 21 namespace chromeos { 22 23 // A class to sample CPU idle state occupancy and freq state occupancy. 24 // Collects raw data from sysfs and does not convert it to percentage 25 // occupancy. As CPUs can be offline at times, or the system can be suspended at 26 // other times, it is best for the consumer of this data to calculate percentage 27 // occupancy information using suspend time data from 28 // PowerDataCollector::system_resumed_data. 29 class CpuDataCollector { 30 public: 31 struct StateOccupancySample { 32 StateOccupancySample(); 33 StateOccupancySample(const StateOccupancySample& other); 34 ~StateOccupancySample(); 35 36 // The time when the data was sampled. 37 base::Time time; 38 39 // Indicates whether the CPU is online. 40 bool cpu_online; 41 42 // A mapping from a CPU state to time spent in that state. For idle state 43 // samples, the name of the state at index i in this vector is the name at 44 // index i in the vector returned by cpu_idle_state_names(). Similarly, for 45 // freq state occupancy, similar information is in the vector returned by 46 // cpu_freq_state_names(). 47 std::vector<base::TimeDelta> time_in_state; 48 }; 49 50 using StateOccupancySampleDeque = base::circular_deque<StateOccupancySample>; 51 cpu_idle_state_names()52 const std::vector<std::string>& cpu_idle_state_names() const { 53 return cpu_idle_state_names_; 54 } 55 cpu_idle_state_data()56 const std::vector<StateOccupancySampleDeque>& cpu_idle_state_data() const { 57 return cpu_idle_state_data_; 58 } 59 cpu_freq_state_names()60 const std::vector<std::string>& cpu_freq_state_names() const { 61 return cpu_freq_state_names_; 62 } 63 cpu_freq_state_data()64 const std::vector<StateOccupancySampleDeque>& cpu_freq_state_data() const { 65 return cpu_freq_state_data_; 66 } 67 68 CpuDataCollector(); 69 ~CpuDataCollector(); 70 71 // Starts a repeating timer which periodically runs a callback to collect 72 // CPU state occupancy samples. 73 void Start(); 74 75 // Read CPU frequency data of a specific CPU from the file in |path| and fill 76 // |cpu_freq_state_names| and |freq_sample| with the data. 77 // Sample file looks like: 78 // 126000 223344 79 // 216000 93495 80 // ... 81 // 1800000 321907 82 static bool ReadCpuFreqTimeInState( 83 const base::FilePath& path, 84 std::vector<std::string>* cpu_freq_state_names, 85 CpuDataCollector::StateOccupancySample* freq_sample); 86 87 // Read CPU frequency data of all CPUs from the file in |path| and fill 88 // |cpu_freq_state_names| and |freq_samples| with the data. |cpu_count| is the 89 // number of possible CPUs on the system. Note that |freq_samples| is not 90 // empty and sample at index i in |freq_samples| corresponds to the freq state 91 // information of the i-th CPU. |cpu_online| of each sample must be set before 92 // calling this function. 93 // Sample file looks like: 94 // freq cpu0 cpu1 95 // 126000 223344 223311 96 // 216000 93495 93450 97 // ... 98 // 1800000 321907 331897 99 static bool ReadCpuFreqAllTimeInState( 100 int cpu_count, 101 const base::FilePath& path, 102 std::vector<std::string>* cpu_freq_state_names, 103 std::vector<CpuDataCollector::StateOccupancySample>* freq_samples); 104 105 private: 106 // Posts callbacks to the blocking pool which collect CPU state occupancy 107 // samples from the sysfs. 108 void PostSampleCpuState(); 109 110 // This function commits the CPU count and samples read by 111 // SampleCpuStateAsync to |cpu_idle_state_data_| and 112 // |cpu_freq_state_data_|. Since UI is the consumer of CPU idle and freq data, 113 // this function should run on the UI thread. 114 void SaveCpuStateSamplesOnUIThread( 115 const int* cpu_count, 116 const std::vector<std::string>* cpu_idle_state_names, 117 const std::vector<StateOccupancySample>* idle_samples, 118 const std::vector<std::string>* cpu_freq_state_names, 119 const std::vector<StateOccupancySample>* freq_samples); 120 121 base::RepeatingTimer timer_; 122 123 // Names of the idle states. 124 std::vector<std::string> cpu_idle_state_names_; 125 126 // The deque at index <i> in the vector corresponds to the idle state 127 // occupancy data of CPU<i>. 128 std::vector<StateOccupancySampleDeque> cpu_idle_state_data_; 129 130 // Names of the freq states. 131 std::vector<std::string> cpu_freq_state_names_; 132 133 // The deque at index <i> in the vector corresponds to the frequency state 134 // occupancy data of CPU<i>. 135 std::vector<StateOccupancySampleDeque> cpu_freq_state_data_; 136 137 // The number of CPUs on the system. This value is read from the sysfs, and 138 // hence should be read/written to only from the blocking pool. 139 int cpu_count_; 140 141 base::WeakPtrFactory<CpuDataCollector> weak_ptr_factory_{this}; 142 DISALLOW_COPY_AND_ASSIGN(CpuDataCollector); 143 }; 144 145 } // namespace chromeos 146 147 #endif // CHROME_BROWSER_CHROMEOS_POWER_CPU_DATA_COLLECTOR_H_ 148