/* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include "meminfo.h" namespace android { namespace meminfo { using VmaCallback = std::function; class ProcMemInfo final { // Per-process memory accounting public: // Reset the working set accounting of the process via /proc//clear_refs static bool ResetWorkingSet(pid_t pid); ProcMemInfo(pid_t pid, bool get_wss = false, uint64_t pgflags = 0, uint64_t pgflags_mask = 0); const std::vector& Maps(); const MemUsage& Usage(); const MemUsage& Wss(); // Same as Maps() except, only valid for reading working set using CONFIG_IDLE_PAGE_TRACKING // support in kernel. If the kernel support doesn't exist, the function will return an empty // vector. const std::vector& MapsWithPageIdle(); // Same as Maps() except, do not read the usage stats for each map. const std::vector& MapsWithoutUsageStats(); // If MapsWithoutUsageStats was called, this function will fill in // usage stats for this single vma. bool FillInVmaStats(Vma& vma); // Collect all 'vma' or 'maps' from /proc//smaps and store them in 'maps_'. Returns a // constant reference to the vma vector after the collection is done. // // Each 'struct Vma' is *fully* populated by this method (unlike SmapsOrRollup). const std::vector& Smaps(const std::string& path = ""); // If 'use_smaps' is 'true' this method reads /proc//smaps and calls the callback() // for each vma or map that it finds, else if 'use_smaps' is false /proc//maps is // used instead. Each vma or map found, is converted to 'struct Vma' object which is then // passed to the callback. // Returns 'false' if the file is malformed. bool ForEachVma(const VmaCallback& callback, bool use_smaps = true); // Reads all VMAs from /proc//maps and calls the callback() for each one of them. // Returns false in case of failure during parsing. bool ForEachVmaFromMaps(const VmaCallback& callback); // Used to parse either of /proc//{smaps, smaps_rollup} and record the process's // Pss and Private memory usage in 'stats'. In particular, the method only populates the fields // of the MemUsage structure that are intended to be used by Android's periodic Pss collection. // // The method populates the following statistics in order to be fast an efficient. // Pss // Rss // Uss // private_clean // private_dirty // SwapPss // All other fields of MemUsage are zeroed. bool SmapsOrRollup(MemUsage* stats) const; // Used to parse either of /proc//{smaps, smaps_rollup} and record the process's // Pss. // Returns 'true' on success and the value of Pss in the out parameter. bool SmapsOrRollupPss(uint64_t* pss) const; const std::vector& SwapOffsets(); // Reads /proc//pagemap for this process for each page within // the 'vma' and stores that in 'pagemap'. It is assumed that the 'vma' // is obtained by calling Maps() or 'ForEachVma' for the same object. No special checks // are made to see if 'vma' is *valid*. // Returns false if anything goes wrong, 'true' otherwise. bool PageMap(const Vma& vma, std::vector* pagemap); ~ProcMemInfo() = default; private: bool ReadMaps(bool get_wss, bool use_pageidle = false, bool get_usage_stats = true, bool swap_only = false); bool ReadVmaStats(int pagemap_fd, Vma& vma, bool get_wss, bool use_pageidle, bool swap_only); pid_t pid_; bool get_wss_; uint64_t pgflags_; uint64_t pgflags_mask_; std::vector maps_; MemUsage usage_; std::vector swap_offsets_; }; // Makes callback for each 'vma' or 'map' found in file provided. // If 'read_smaps_fields' is 'true', the file is expected to be in the // same format as /proc//smaps, else the file is expected to be // formatted as /proc//maps. // Returns 'false' if the file is malformed. bool ForEachVmaFromFile(const std::string& path, const VmaCallback& callback, bool read_smaps_fields = true); // Returns if the kernel supports /proc//smaps_rollup. Assumes that the // calling process has access to the /proc//smaps_rollup. // Returns 'false' if the file doesn't exist. bool IsSmapsRollupSupported(); // Same as ProcMemInfo::SmapsOrRollup but reads the statistics directly // from a file. The file MUST be in the same format as /proc//smaps // or /proc//smaps_rollup bool SmapsOrRollupFromFile(const std::string& path, MemUsage* stats); // Same as ProcMemInfo::SmapsOrRollupPss but reads the statistics directly // from a file and returns total Pss in kB. The file MUST be in the same format // as /proc//smaps or /proc//smaps_rollup bool SmapsOrRollupPssFromFile(const std::string& path, uint64_t* pss); } // namespace meminfo } // namespace android