1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #pragma once 18 19 #include <sys/types.h> 20 21 #include <string> 22 #include <vector> 23 24 #include "meminfo.h" 25 26 namespace android { 27 namespace meminfo { 28 29 using VmaCallback = std::function<void(const Vma&)>; 30 31 class ProcMemInfo final { 32 // Per-process memory accounting 33 public: 34 // Reset the working set accounting of the process via /proc/<pid>/clear_refs 35 static bool ResetWorkingSet(pid_t pid); 36 37 ProcMemInfo(pid_t pid, bool get_wss = false, uint64_t pgflags = 0, uint64_t pgflags_mask = 0); 38 39 const std::vector<Vma>& Maps(); 40 const MemUsage& Usage(); 41 const MemUsage& Wss(); 42 43 // Same as Maps() except, only valid for reading working set using CONFIG_IDLE_PAGE_TRACKING 44 // support in kernel. If the kernel support doesn't exist, the function will return an empty 45 // vector. 46 const std::vector<Vma>& MapsWithPageIdle(); 47 48 // Same as Maps() except, do not read the usage stats for each map. 49 const std::vector<Vma>& MapsWithoutUsageStats(); 50 51 // If MapsWithoutUsageStats was called, this function will fill in 52 // usage stats for this single vma. 53 bool FillInVmaStats(Vma& vma); 54 55 // Collect all 'vma' or 'maps' from /proc/<pid>/smaps and store them in 'maps_'. Returns a 56 // constant reference to the vma vector after the collection is done. 57 // 58 // Each 'struct Vma' is *fully* populated by this method (unlike SmapsOrRollup). 59 const std::vector<Vma>& Smaps(const std::string& path = ""); 60 61 // If 'use_smaps' is 'true' this method reads /proc/<pid>/smaps and calls the callback() 62 // for each vma or map that it finds, else if 'use_smaps' is false /proc/<pid>/maps is 63 // used instead. Each vma or map found, is converted to 'struct Vma' object which is then 64 // passed to the callback. 65 // Returns 'false' if the file is malformed. 66 bool ForEachVma(const VmaCallback& callback, bool use_smaps = true); 67 68 // Reads all VMAs from /proc/<pid>/maps and calls the callback() for each one of them. 69 // Returns false in case of failure during parsing. 70 bool ForEachVmaFromMaps(const VmaCallback& callback); 71 72 // Used to parse either of /proc/<pid>/{smaps, smaps_rollup} and record the process's 73 // Pss and Private memory usage in 'stats'. In particular, the method only populates the fields 74 // of the MemUsage structure that are intended to be used by Android's periodic Pss collection. 75 // 76 // The method populates the following statistics in order to be fast an efficient. 77 // Pss 78 // Rss 79 // Uss 80 // private_clean 81 // private_dirty 82 // SwapPss 83 // All other fields of MemUsage are zeroed. 84 bool SmapsOrRollup(MemUsage* stats) const; 85 86 // Used to parse either of /proc/<pid>/{smaps, smaps_rollup} and record the process's 87 // Pss. 88 // Returns 'true' on success and the value of Pss in the out parameter. 89 bool SmapsOrRollupPss(uint64_t* pss) const; 90 91 const std::vector<uint64_t>& SwapOffsets(); 92 93 // Reads /proc/<pid>/pagemap for this process for each page within 94 // the 'vma' and stores that in 'pagemap'. It is assumed that the 'vma' 95 // is obtained by calling Maps() or 'ForEachVma' for the same object. No special checks 96 // are made to see if 'vma' is *valid*. 97 // Returns false if anything goes wrong, 'true' otherwise. 98 bool PageMap(const Vma& vma, std::vector<uint64_t>* pagemap); 99 100 ~ProcMemInfo() = default; 101 102 private: 103 bool ReadMaps(bool get_wss, bool use_pageidle = false, bool get_usage_stats = true, 104 bool swap_only = false); 105 bool ReadVmaStats(int pagemap_fd, Vma& vma, bool get_wss, bool use_pageidle, bool swap_only); 106 107 pid_t pid_; 108 bool get_wss_; 109 uint64_t pgflags_; 110 uint64_t pgflags_mask_; 111 112 std::vector<Vma> maps_; 113 114 MemUsage usage_; 115 std::vector<uint64_t> swap_offsets_; 116 }; 117 118 // Makes callback for each 'vma' or 'map' found in file provided. 119 // If 'read_smaps_fields' is 'true', the file is expected to be in the 120 // same format as /proc/<pid>/smaps, else the file is expected to be 121 // formatted as /proc/<pid>/maps. 122 // Returns 'false' if the file is malformed. 123 bool ForEachVmaFromFile(const std::string& path, const VmaCallback& callback, 124 bool read_smaps_fields = true); 125 126 // Returns if the kernel supports /proc/<pid>/smaps_rollup. Assumes that the 127 // calling process has access to the /proc/<pid>/smaps_rollup. 128 // Returns 'false' if the file doesn't exist. 129 bool IsSmapsRollupSupported(); 130 131 // Same as ProcMemInfo::SmapsOrRollup but reads the statistics directly 132 // from a file. The file MUST be in the same format as /proc/<pid>/smaps 133 // or /proc/<pid>/smaps_rollup 134 bool SmapsOrRollupFromFile(const std::string& path, MemUsage* stats); 135 136 // Same as ProcMemInfo::SmapsOrRollupPss but reads the statistics directly 137 // from a file and returns total Pss in kB. The file MUST be in the same format 138 // as /proc/<pid>/smaps or /proc/<pid>/smaps_rollup 139 bool SmapsOrRollupPssFromFile(const std::string& path, uint64_t* pss); 140 141 } // namespace meminfo 142 } // namespace android 143