diff options
-rw-r--r-- | adb/client/commandline.cpp | 18 | ||||
-rw-r--r-- | libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h | 6 | ||||
-rw-r--r-- | libmeminfo/libdmabufinfo/tools/dmabuf_dump.cpp | 275 | ||||
-rw-r--r-- | libmeminfo/pageacct.cpp | 8 | ||||
-rw-r--r-- | libmeminfo/procmeminfo.cpp | 88 | ||||
-rw-r--r-- | libmeminfo/tools/procrank.cpp | 2 | ||||
-rw-r--r-- | rootdir/etc/ld.config.txt | 22 | ||||
-rw-r--r-- | rootdir/etc/ld.config.vndk_lite.txt | 1 | ||||
-rw-r--r-- | rootdir/init.rc | 1 |
9 files changed, 279 insertions, 142 deletions
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp index e2a17c553..8dd85d7b0 100644 --- a/adb/client/commandline.cpp +++ b/adb/client/commandline.cpp @@ -1668,17 +1668,29 @@ int adb_commandline(int argc, const char** argv) { return 0; } } else if (!strcmp(argv[0], "rescue")) { + // adb rescue getprop // adb rescue getprop <prop> // adb rescue install <filename> // adb rescue wipe userdata - if (argc != 3) error_exit("rescue requires two arguments"); + if (argc < 2) error_exit("rescue requires at least one argument"); if (!strcmp(argv[1], "getprop")) { - return adb_connect_command(android::base::StringPrintf("rescue-getprop:%s", argv[2])); + if (argc == 2) { + return adb_connect_command("rescue-getprop:"); + } + if (argc == 3) { + return adb_connect_command( + android::base::StringPrintf("rescue-getprop:%s", argv[2])); + } + error_exit("invalid rescue getprop arguments"); } else if (!strcmp(argv[1], "install")) { + if (argc != 3) error_exit("rescue install requires two arguments"); if (adb_sideload_install(argv[2], true /* rescue_mode */) != 0) { return 1; } - } else if (!strcmp(argv[1], "wipe") && !strcmp(argv[2], "userdata")) { + } else if (!strcmp(argv[1], "wipe")) { + if (argc != 3 || strcmp(argv[2], "userdata") != 0) { + error_exit("invalid rescue wipe arguments"); + } return adb_wipe_devices(); } else { error_exit("invalid rescue argument"); diff --git a/libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h b/libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h index a16c3fdaf..a6e7f6907 100644 --- a/libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h +++ b/libmeminfo/libdmabufinfo/include/dmabufinfo/dmabufinfo.h @@ -19,6 +19,7 @@ #include <sys/types.h> #include <unistd.h> +#include <set> #include <string> #include <vector> #include <unordered_map> @@ -33,6 +34,7 @@ struct DmaBuffer { : inode_(inode), size_(size), count_(count), exporter_(exporter), name_(name) { total_refs_ = 0; } + DmaBuffer() = default; ~DmaBuffer() = default; // Adds one file descriptor reference for the given pid @@ -54,11 +56,13 @@ struct DmaBuffer { ino_t inode() const { return inode_; } uint64_t total_refs() const { return total_refs_; } uint64_t count() const { return count_; }; + const std::set<pid_t>& pids() const { return pids_; } const std::string& name() const { return name_; } const std::string& exporter() const { return exporter_; } void SetName(const std::string& name) { name_ = name; } void SetExporter(const std::string& exporter) { exporter_ = exporter; } void SetCount(uint64_t count) { count_ = count; } + uint64_t Pss() const { return size_ / pids_.size(); } bool operator==(const DmaBuffer& rhs) { return (inode_ == rhs.inode()) && (size_ == rhs.size()) && (name_ == rhs.name()) && @@ -70,6 +74,7 @@ struct DmaBuffer { uint64_t size_; uint64_t count_; uint64_t total_refs_; + std::set<pid_t> pids_; std::string exporter_; std::string name_; std::unordered_map<pid_t, int> fdrefs_; @@ -80,6 +85,7 @@ struct DmaBuffer { auto [it, inserted] = map->insert(std::make_pair(pid, 1)); if (!inserted) it->second++; + pids_.insert(pid); } }; diff --git a/libmeminfo/libdmabufinfo/tools/dmabuf_dump.cpp b/libmeminfo/libdmabufinfo/tools/dmabuf_dump.cpp index 0851fb33c..48901b1da 100644 --- a/libmeminfo/libdmabufinfo/tools/dmabuf_dump.cpp +++ b/libmeminfo/libdmabufinfo/tools/dmabuf_dump.cpp @@ -16,17 +16,19 @@ #include <dirent.h> #include <errno.h> +#include <getopt.h> #include <inttypes.h> +#include <stdio.h> #include <stdlib.h> #include <unistd.h> -#include <iostream> #include <fstream> +#include <iostream> +#include <map> +#include <set> #include <sstream> #include <string> #include <vector> -#include <map> -#include <set> #include <android-base/stringprintf.h> #include <dmabufinfo/dmabufinfo.h> @@ -35,15 +37,16 @@ using DmaBuffer = ::android::dmabufinfo::DmaBuffer; [[noreturn]] static void usage(int exit_status) { fprintf(stderr, - "Usage: %s [PID] \n" - "\t If PID is supplied, the dmabuf information for this process is shown.\n" - "\t Otherwise, shows the information for all processes.\n", + "Usage: %s [-ah] [PID] \n" + "-a\t show all dma buffers (ion) in big table, [buffer x process] grid \n" + "-h\t show this help\n" + " \t If PID is supplied, the dmabuf information for that process is shown.\n", getprogname()); exit(exit_status); } -static std::string GetProcessBaseName(pid_t pid) { +static std::string GetProcessComm(const pid_t pid) { std::string pid_path = android::base::StringPrintf("/proc/%d/comm", pid); std::ifstream in{pid_path}; if (!in) return std::string("N/A"); @@ -53,133 +56,211 @@ static std::string GetProcessBaseName(pid_t pid) { return line; } -static void AddPidsToSet(const std::unordered_map<pid_t, int>& map, std::set<pid_t>* set) -{ - for (auto it = map.begin(); it != map.end(); ++it) - set->insert(it->first); -} - -static void PrintDmaBufInfo(const std::vector<DmaBuffer>& bufs) { - std::set<pid_t> pid_set; - std::map<pid_t, int> pid_column; - +static void PrintDmaBufTable(const std::vector<DmaBuffer>& bufs) { if (bufs.empty()) { - std::cout << "dmabuf info not found ¯\\_(ツ)_/¯" << std::endl; + printf("dmabuf info not found ¯\\_(ツ)_/¯\n"); return; } // Find all unique pids in the input vector, create a set - for (int i = 0; i < bufs.size(); i++) { - AddPidsToSet(bufs[i].fdrefs(), &pid_set); - AddPidsToSet(bufs[i].maprefs(), &pid_set); + std::set<pid_t> pid_set; + for (auto& buf : bufs) { + pid_set.insert(buf.pids().begin(), buf.pids().end()); } - int pid_count = 0; + // Format the header string spaced and separated with '|' + printf(" Dmabuf Inode | Size | Ref Counts |"); + for (auto pid : pid_set) { + printf("%16s:%-5d |", GetProcessComm(pid).c_str(), pid); + } + printf("\n"); + + // holds per-process dmabuf size in kB + std::map<pid_t, uint64_t> per_pid_size = {}; + uint64_t dmabuf_total_size = 0; + + // Iterate through all dmabufs and collect per-process sizes, refs + for (auto& buf : bufs) { + printf("%16ju |%13" PRIu64 " kB |%16" PRIu64 " |", static_cast<uintmax_t>(buf.inode()), + buf.size() / 1024, buf.total_refs()); + // Iterate through each process to find out per-process references for each buffer, + // gather total size used by each process etc. + for (pid_t pid : pid_set) { + int pid_refs = 0; + if (buf.fdrefs().count(pid) == 1) { + // Get the total number of ref counts the process is holding + // on this buffer. We don't differentiate between mmap or fd. + pid_refs += buf.fdrefs().at(pid); + if (buf.maprefs().count(pid) == 1) { + pid_refs += buf.maprefs().at(pid); + } + } - std::cout << "\t\t\t\t\t\t"; + if (pid_refs) { + // Add up the per-pid total size. Note that if a buffer is mapped + // in 2 different processes, the size will be shown as mapped or opened + // in both processes. This is intended for visibility. + // + // If one wants to get the total *unique* dma buffers, they can simply + // sum the size of all dma bufs shown by the tool + per_pid_size[pid] += buf.size() / 1024; + printf("%17d refs |", pid_refs); + } else { + printf("%22s |", "--"); + } + } + dmabuf_total_size += buf.size() / 1024; + printf("\n"); + } - // Create a map to convert each unique pid into a column number - for (auto it = pid_set.begin(); it != pid_set.end(); ++it, ++pid_count) { - pid_column.insert(std::make_pair(*it, pid_count)); - std::cout << ::android::base::StringPrintf("[pid: % 4d]\t", *it); + printf("------------------------------------\n"); + printf("%-16s %13" PRIu64 " kB |%16s |", "TOTALS", dmabuf_total_size, "n/a"); + for (auto pid : pid_set) { + printf("%19" PRIu64 " kB |", per_pid_size[pid]); } + printf("\n"); - std::cout << std::endl << "\t\t\t\t\t\t"; + return; +} - for (auto it = pid_set.begin(); it != pid_set.end(); ++it) { - std::cout << ::android::base::StringPrintf("%16s", - GetProcessBaseName(*it).c_str()); +static void PrintDmaBufPerProcess(const std::vector<DmaBuffer>& bufs) { + if (bufs.empty()) { + printf("dmabuf info not found ¯\\_(ツ)_/¯\n"); + return; } - std::cout << std::endl << "\tinode\t\tsize\t\tcount\t"; - for (int i = 0; i < pid_count; i++) { - std::cout << "fd\tmap\t"; + // Create a reverse map from pid to dmabufs + std::unordered_map<pid_t, std::set<ino_t>> pid_to_inodes = {}; + uint64_t total_size = 0; // Total size of dmabufs in the system + uint64_t kernel_rss = 0; // Total size of dmabufs NOT mapped or opened by a process + for (auto& buf : bufs) { + for (auto pid : buf.pids()) { + pid_to_inodes[pid].insert(buf.inode()); + } + total_size += buf.size(); + if (buf.fdrefs().empty() && buf.maprefs().empty()) { + kernel_rss += buf.size(); + } + } + // Create an inode to dmabuf map. We know inodes are unique.. + std::unordered_map<ino_t, DmaBuffer> inode_to_dmabuf; + for (auto buf : bufs) { + inode_to_dmabuf[buf.inode()] = buf; } - std::cout << std::endl; - - auto fds = std::make_unique<int[]>(pid_count); - auto maps = std::make_unique<int[]>(pid_count); - auto pss = std::make_unique<long[]>(pid_count); - memset(pss.get(), 0, sizeof(long) * pid_count); + uint64_t total_rss = 0, total_pss = 0; + for (auto& [pid, inodes] : pid_to_inodes) { + uint64_t pss = 0; + uint64_t rss = 0; + + printf("%16s:%-5d\n", GetProcessComm(pid).c_str(), pid); + printf("%22s %16s %16s %16s %16s\n", "Name", "Rss", "Pss", "nr_procs", "Inode"); + for (auto& inode : inodes) { + DmaBuffer& buf = inode_to_dmabuf[inode]; + printf("%22s %13" PRIu64 " kB %13" PRIu64 " kB %16zu %16" PRIuMAX "\n", + buf.name().empty() ? "<unknown>" : buf.name().c_str(), buf.size() / 1024, + buf.Pss() / 1024, buf.pids().size(), static_cast<uintmax_t>(buf.inode())); + rss += buf.size(); + pss += buf.Pss(); + } + printf("%22s %13" PRIu64 " kB %13" PRIu64 " kB %16s\n", "PROCESS TOTAL", rss / 1024, + pss / 1024, ""); + printf("----------------------\n"); + total_rss += rss; + total_pss += pss; + } + printf("dmabuf total: %" PRIu64 " kB kernel_rss: %" PRIu64 " kB userspace_rss: %" PRIu64 + " kB userspace_pss: %" PRIu64 " kB\n ", + total_size / 1024, kernel_rss / 1024, total_rss / 1024, total_pss / 1024); +} - for (auto buf = bufs.begin(); buf != bufs.end(); ++buf) { +static bool ReadDmaBufs(std::vector<DmaBuffer>* bufs) { + bufs->clear(); - std::cout << ::android::base::StringPrintf("%16lu\t%10" PRIu64 "\t%" PRIu64 "\t", - buf->inode(),buf->size(), buf->count()); + if (!ReadDmaBufInfo(bufs)) { + fprintf(stderr, "debugfs entry for dmabuf not available, skipping\n"); + return false; + } - memset(fds.get(), 0, sizeof(int) * pid_count); - memset(maps.get(), 0, sizeof(int) * pid_count); + std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir("/proc"), closedir); + if (!dir) { + fprintf(stderr, "Failed to open /proc directory\n"); + bufs->clear(); + return false; + } - for (auto it = buf->fdrefs().begin(); it != buf->fdrefs().end(); ++it) { - fds[pid_column[it->first]] = it->second; - pss[pid_column[it->first]] += buf->size() * it->second / buf->count(); - } + struct dirent* dent; + while ((dent = readdir(dir.get()))) { + if (dent->d_type != DT_DIR) continue; - for (auto it = buf->maprefs().begin(); it != buf->maprefs().end(); ++it) { - maps[pid_column[it->first]] = it->second; - pss[pid_column[it->first]] += buf->size() * it->second / buf->count(); + int pid = atoi(dent->d_name); + if (pid == 0) { + continue; } - for (int i = 0; i < pid_count; i++) { - std::cout << ::android::base::StringPrintf("%d\t%d\t", fds[i], maps[i]); + if (!AppendDmaBufInfo(pid, bufs)) { + fprintf(stderr, "Unable to read dmabuf info for pid %d\n", pid); + bufs->clear(); + return false; } - std::cout << std::endl; - } - std::cout << "-----------------------------------------" << std::endl; - std::cout << "PSS "; - for (int i = 0; i < pid_count; i++) { - std::cout << ::android::base::StringPrintf("%15ldK", pss[i] / 1024); } - std::cout << std::endl; + + return true; } int main(int argc, char* argv[]) { - pid_t pid = -1; - std::vector<DmaBuffer> bufs; - bool show_all = true; - - if (argc > 1) { - if (sscanf(argv[1], "%d", &pid) == 1) { - show_all = false; - } - else { - usage(EXIT_FAILURE); + struct option longopts[] = {{"all", no_argument, nullptr, 'a'}, + {"help", no_argument, nullptr, 'h'}, + {0, 0, nullptr, 0}}; + + int opt; + bool show_table = false; + while ((opt = getopt_long(argc, argv, "ah", longopts, nullptr)) != -1) { + switch (opt) { + case 'a': + show_table = true; + break; + case 'h': + usage(EXIT_SUCCESS); + default: + usage(EXIT_FAILURE); } } - if (show_all) { - if (!ReadDmaBufInfo(&bufs)) { - std::cerr << "debugfs entry for dmabuf not available, skipping" << std::endl; - bufs.clear(); + pid_t pid = -1; + if (optind < argc) { + if (show_table) { + fprintf(stderr, "Invalid arguments: -a does not need arguments\n"); + usage(EXIT_FAILURE); } - std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir("/proc"), closedir); - if (!dir) { - std::cerr << "Failed to open /proc directory" << std::endl; - exit(EXIT_FAILURE); + if (optind != (argc - 1)) { + fprintf(stderr, "Invalid arguments - only one [PID] argument is allowed\n"); + usage(EXIT_FAILURE); } - struct dirent* dent; - while ((dent = readdir(dir.get()))) { - if (dent->d_type != DT_DIR) continue; - - int matched = sscanf(dent->d_name, "%d", &pid); - if (matched != 1) { - continue; - } - - if (!AppendDmaBufInfo(pid, &bufs)) { - std::cerr << "Unable to read dmabuf info for pid " << pid << std::endl; - exit(EXIT_FAILURE); - } + pid = atoi(argv[optind]); + if (pid == 0) { + fprintf(stderr, "Invalid process id %s\n", argv[optind]); + usage(EXIT_FAILURE); } - } else { + } + + std::vector<DmaBuffer> bufs; + if (pid != -1) { if (!ReadDmaBufInfo(pid, &bufs)) { - std::cerr << "Unable to read dmabuf info" << std::endl; + fprintf(stderr, "Unable to read dmabuf info for %d\n", pid); exit(EXIT_FAILURE); } + } else { + if (!ReadDmaBufs(&bufs)) exit(EXIT_FAILURE); } - PrintDmaBufInfo(bufs); - return 0; -} + // Show the old dmabuf table, inode x process + if (show_table) { + PrintDmaBufTable(bufs); + return 0; + } + PrintDmaBufPerProcess(bufs); + + return 0; +} diff --git a/libmeminfo/pageacct.cpp b/libmeminfo/pageacct.cpp index 0a26c0818..cb17af8ab 100644 --- a/libmeminfo/pageacct.cpp +++ b/libmeminfo/pageacct.cpp @@ -81,7 +81,8 @@ bool PageAcct::PageFlags(uint64_t pfn, uint64_t* flags) { if (!InitPageAcct()) return false; } - if (pread64(kpageflags_fd_, flags, sizeof(uint64_t), pfn * sizeof(uint64_t)) < 0) { + if (pread64(kpageflags_fd_, flags, sizeof(uint64_t), pfn * sizeof(uint64_t)) != + sizeof(uint64_t)) { PLOG(ERROR) << "Failed to read page flags for page " << pfn; return false; } @@ -95,7 +96,8 @@ bool PageAcct::PageMapCount(uint64_t pfn, uint64_t* mapcount) { if (!InitPageAcct()) return false; } - if (pread64(kpagecount_fd_, mapcount, sizeof(uint64_t), pfn * sizeof(uint64_t)) < 0) { + if (pread64(kpagecount_fd_, mapcount, sizeof(uint64_t), pfn * sizeof(uint64_t)) != + sizeof(uint64_t)) { PLOG(ERROR) << "Failed to read map count for page " << pfn; return false; } @@ -130,7 +132,7 @@ int PageAcct::GetPageIdle(uint64_t pfn) const { off64_t offset = pfn_to_idle_bitmap_offset(pfn); uint64_t idle_bits; - if (pread64(pageidle_fd_, &idle_bits, sizeof(uint64_t), offset) < 0) { + if (pread64(pageidle_fd_, &idle_bits, sizeof(uint64_t), offset) != sizeof(uint64_t)) { PLOG(ERROR) << "Failed to read page idle bitmap for page " << pfn; return -errno; } diff --git a/libmeminfo/procmeminfo.cpp b/libmeminfo/procmeminfo.cpp index 934d65c9d..a8b43c189 100644 --- a/libmeminfo/procmeminfo.cpp +++ b/libmeminfo/procmeminfo.cpp @@ -27,6 +27,7 @@ #include <memory> #include <string> #include <utility> +#include <vector> #include <android-base/file.h> #include <android-base/logging.h> @@ -278,68 +279,89 @@ bool ProcMemInfo::ReadMaps(bool get_wss, bool use_pageidle) { bool ProcMemInfo::ReadVmaStats(int pagemap_fd, Vma& vma, bool get_wss, bool use_pageidle) { PageAcct& pinfo = PageAcct::Instance(); - uint64_t pagesz = getpagesize(); - uint64_t num_pages = (vma.end - vma.start) / pagesz; - - std::unique_ptr<uint64_t[]> pg_frames(new uint64_t[num_pages]); - uint64_t first = vma.start / pagesz; - if (pread64(pagemap_fd, pg_frames.get(), num_pages * sizeof(uint64_t), - first * sizeof(uint64_t)) < 0) { - PLOG(ERROR) << "Failed to read page frames from page map for pid: " << pid_; + if (get_wss && use_pageidle && !pinfo.InitPageAcct(true)) { + LOG(ERROR) << "Failed to init idle page accounting"; return false; } - if (get_wss && use_pageidle) { - if (!pinfo.InitPageAcct(true)) { - LOG(ERROR) << "Failed to init idle page accounting"; - return false; - } - } - - std::unique_ptr<uint64_t[]> pg_flags(new uint64_t[num_pages]); - std::unique_ptr<uint64_t[]> pg_counts(new uint64_t[num_pages]); - for (uint64_t i = 0; i < num_pages; ++i) { + uint64_t pagesz = getpagesize(); + size_t num_pages = (vma.end - vma.start) / pagesz; + size_t first_page = vma.start / pagesz; + + std::vector<uint64_t> page_cache; + size_t cur_page_cache_index = 0; + size_t num_in_page_cache = 0; + size_t num_leftover_pages = num_pages; + for (size_t cur_page = first_page; cur_page < first_page + num_pages; ++cur_page) { if (!get_wss) { vma.usage.vss += pagesz; } - uint64_t p = pg_frames[i]; - if (!PAGE_PRESENT(p) && !PAGE_SWAPPED(p)) continue; - if (PAGE_SWAPPED(p)) { + // Cache page map data. + if (cur_page_cache_index == num_in_page_cache) { + static constexpr size_t kMaxPages = 2048; + num_leftover_pages -= num_in_page_cache; + if (num_leftover_pages > kMaxPages) { + num_in_page_cache = kMaxPages; + } else { + num_in_page_cache = num_leftover_pages; + } + page_cache.resize(num_in_page_cache); + size_t total_bytes = page_cache.size() * sizeof(uint64_t); + ssize_t bytes = pread64(pagemap_fd, page_cache.data(), total_bytes, + cur_page * sizeof(uint64_t)); + if (bytes != total_bytes) { + if (bytes == -1) { + PLOG(ERROR) << "Failed to read page data at offset 0x" << std::hex + << cur_page * sizeof(uint64_t); + } else { + LOG(ERROR) << "Failed to read page data at offset 0x" << std::hex + << cur_page * sizeof(uint64_t) << std::dec << " read bytes " << bytes + << " expected bytes " << total_bytes; + } + return false; + } + cur_page_cache_index = 0; + } + + uint64_t page_info = page_cache[cur_page_cache_index++]; + if (!PAGE_PRESENT(page_info) && !PAGE_SWAPPED(page_info)) continue; + + if (PAGE_SWAPPED(page_info)) { vma.usage.swap += pagesz; - swap_offsets_.emplace_back(PAGE_SWAP_OFFSET(p)); + swap_offsets_.emplace_back(PAGE_SWAP_OFFSET(page_info)); continue; } - uint64_t page_frame = PAGE_PFN(p); - if (!pinfo.PageFlags(page_frame, &pg_flags[i])) { + uint64_t page_frame = PAGE_PFN(page_info); + uint64_t cur_page_flags; + if (!pinfo.PageFlags(page_frame, &cur_page_flags)) { LOG(ERROR) << "Failed to get page flags for " << page_frame << " in process " << pid_; swap_offsets_.clear(); return false; } // skip unwanted pages from the count - if ((pg_flags[i] & pgflags_mask_) != pgflags_) continue; + if ((cur_page_flags & pgflags_mask_) != pgflags_) continue; - if (!pinfo.PageMapCount(page_frame, &pg_counts[i])) { + uint64_t cur_page_counts; + if (!pinfo.PageMapCount(page_frame, &cur_page_counts)) { LOG(ERROR) << "Failed to get page count for " << page_frame << " in process " << pid_; swap_offsets_.clear(); return false; } // Page was unmapped between the presence check at the beginning of the loop and here. - if (pg_counts[i] == 0) { - pg_frames[i] = 0; - pg_flags[i] = 0; + if (cur_page_counts == 0) { continue; } - bool is_dirty = !!(pg_flags[i] & (1 << KPF_DIRTY)); - bool is_private = (pg_counts[i] == 1); + bool is_dirty = !!(cur_page_flags & (1 << KPF_DIRTY)); + bool is_private = (cur_page_counts == 1); // Working set if (get_wss) { bool is_referenced = use_pageidle ? (pinfo.IsPageIdle(page_frame) == 1) - : !!(pg_flags[i] & (1 << KPF_REFERENCED)); + : !!(cur_page_flags & (1 << KPF_REFERENCED)); if (!is_referenced) { continue; } @@ -351,7 +373,7 @@ bool ProcMemInfo::ReadVmaStats(int pagemap_fd, Vma& vma, bool get_wss, bool use_ vma.usage.rss += pagesz; vma.usage.uss += is_private ? pagesz : 0; - vma.usage.pss += pagesz / pg_counts[i]; + vma.usage.pss += pagesz / cur_page_counts; if (is_private) { vma.usage.private_dirty += is_dirty ? pagesz : 0; vma.usage.private_clean += is_dirty ? 0 : pagesz; diff --git a/libmeminfo/tools/procrank.cpp b/libmeminfo/tools/procrank.cpp index cb3757dba..1e44ff9bd 100644 --- a/libmeminfo/tools/procrank.cpp +++ b/libmeminfo/tools/procrank.cpp @@ -348,7 +348,7 @@ int main(int argc, char* argv[]) { auto rss_sort = [](ProcessRecord& a, ProcessRecord& b) { MemUsage stats_a = show_wss ? a.Wss() : a.Usage(); MemUsage stats_b = show_wss ? b.Wss() : b.Usage(); - return reverse_sort ? stats_a.rss < stats_b.pss : stats_a.pss > stats_b.pss; + return reverse_sort ? stats_a.rss < stats_b.rss : stats_a.rss > stats_b.rss; }; auto vss_sort = [](ProcessRecord& a, ProcessRecord& b) { diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt index 84b308d0e..c95f60fb0 100644 --- a/rootdir/etc/ld.config.txt +++ b/rootdir/etc/ld.config.txt @@ -143,6 +143,7 @@ namespace.default.link.runtime.shared_libs += libandroidicu.so # TODO(b/122876336): Remove libpac.so once it's migrated to Webview namespace.default.link.runtime.shared_libs += libpac.so +namespace.default.link.runtime.shared_libs += %SANITIZER_RUNTIME_LIBRARIES% # When libnetd_resolv.so can't be found in the default namespace, search for it # in the resolv namespace. Don't allow any other libraries from the resolv namespace @@ -363,7 +364,7 @@ namespace.vndk.asan.permitted.paths += /system/${LIB}/vndk-sp%VNDK_VER # The "vndk" namespace links to "default" namespace for LLNDK libs and links to # "sphal" namespace for vendor libs. The ordering matters. The "default" # namespace has higher priority than the "sphal" namespace. -namespace.vndk.links = default,sphal +namespace.vndk.links = default,sphal,runtime # When these NDK libs are required inside this namespace, then it is redirected # to the default namespace. This is possible since their ABI is stable across @@ -371,6 +372,8 @@ namespace.vndk.links = default,sphal namespace.vndk.link.default.shared_libs = %LLNDK_LIBRARIES% namespace.vndk.link.default.shared_libs += %SANITIZER_RUNTIME_LIBRARIES% +namespace.vndk.link.runtime.shared_libs = %SANITIZER_RUNTIME_LIBRARIES% + # Allow VNDK-SP extensions to use vendor libraries namespace.vndk.link.sphal.allow_all_shared_libs = true @@ -423,8 +426,10 @@ namespace.default.asan.permitted.paths += /odm namespace.default.asan.permitted.paths += /data/asan/vendor namespace.default.asan.permitted.paths += /vendor -namespace.default.links = system,vndk%VNDK_IN_SYSTEM_NS% -namespace.default.link.system.shared_libs = %LLNDK_LIBRARIES% +namespace.default.links = system,vndk%VNDK_IN_SYSTEM_NS%,runtime +namespace.default.link.runtime.shared_libs = %SANITIZER_RUNTIME_LIBRARIES% +namespace.default.link.system.shared_libs = %LLNDK_LIBRARIES% +namespace.default.link.system.shared_libs += %SANITIZER_RUNTIME_LIBRARIES% namespace.default.link.vndk_in_system.shared_libs = %VNDK_USING_CORE_VARIANT_LIBRARIES% namespace.default.link.vndk.shared_libs = %VNDK_SAMEPROCESS_LIBRARIES% namespace.default.link.vndk.shared_libs += %VNDK_CORE_LIBRARIES% @@ -477,13 +482,15 @@ namespace.vndk.asan.search.paths += /system/${LIB}/vndk%VNDK_VER% # Android releases. The links here should be identical to that of the # 'vndk_in_system' namespace, except for the link between 'vndk' and # 'vndk_in_system'. -namespace.vndk.links = system,default%VNDK_IN_SYSTEM_NS% +namespace.vndk.links = system,default%VNDK_IN_SYSTEM_NS%,runtime namespace.vndk.link.system.shared_libs = %LLNDK_LIBRARIES% namespace.vndk.link.system.shared_libs += %SANITIZER_RUNTIME_LIBRARIES% namespace.vndk.link.default.allow_all_shared_libs = true +namespace.vndk.link.runtime.shared_libs = %SANITIZER_RUNTIME_LIBRARIES% + namespace.vndk.link.vndk_in_system.shared_libs = %VNDK_USING_CORE_VARIANT_LIBRARIES% ############################################################################### @@ -515,6 +522,7 @@ namespace.system.link.runtime.shared_libs += libnativehelper.so namespace.system.link.runtime.shared_libs += libnativeloader.so # Workaround for b/124772622 namespace.system.link.runtime.shared_libs += libandroidicu.so +namespace.system.link.runtime.shared_libs += %SANITIZER_RUNTIME_LIBRARIES% ############################################################################### # "vndk_in_system" namespace @@ -553,7 +561,8 @@ namespace.vndk_in_system.whitelisted = %VNDK_USING_CORE_VARIANT_LIBRARIES% # 1. 'vndk_in_system' needs to be freely linked back to 'vndk'. # 2. 'vndk_in_system' does not need to link to 'default', as any library that # requires anything vendor would not be a vndk_in_system library. -namespace.vndk_in_system.links = vndk,system +namespace.vndk_in_system.links = vndk,system,runtime +namespace.vndk_in_system.link.runtime.shared_libs = %SANITIZER_RUNTIME_LIBRARIES% namespace.vndk_in_system.link.system.shared_libs = %LLNDK_LIBRARIES% namespace.vndk_in_system.link.system.shared_libs += %SANITIZER_RUNTIME_LIBRARIES% @@ -596,6 +605,7 @@ namespace.default.link.runtime.shared_libs += libandroidicu.so # TODO(b/122876336): Remove libpac.so once it's migrated to Webview namespace.default.link.runtime.shared_libs += libpac.so +namespace.default.link.runtime.shared_libs += %SANITIZER_RUNTIME_LIBRARIES% namespace.default.link.resolv.shared_libs = libnetd_resolv.so @@ -684,3 +694,5 @@ namespace.default.isolated = false namespace.default.search.paths = /system/${LIB} namespace.default.search.paths += /%PRODUCT%/${LIB} namespace.default.search.paths += /%PRODUCT_SERVICES%/${LIB} + +namespace.default.link.runtime.shared_libs = %SANITIZER_RUNTIME_LIBRARIES% diff --git a/rootdir/etc/ld.config.vndk_lite.txt b/rootdir/etc/ld.config.vndk_lite.txt index 5db7698f4..564255926 100644 --- a/rootdir/etc/ld.config.vndk_lite.txt +++ b/rootdir/etc/ld.config.vndk_lite.txt @@ -417,6 +417,7 @@ namespace.default.link.runtime.shared_libs += libandroidicu.so # TODO(b/122876336): Remove libpac.so once it's migrated to Webview namespace.default.link.runtime.shared_libs += libpac.so +namespace.default.link.runtime.shared_libs += %SANITIZER_RUNTIME_LIBRARIES% namespace.default.link.resolv.shared_libs = libnetd_resolv.so diff --git a/rootdir/init.rc b/rootdir/init.rc index c042c4897..2f4ab10c9 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -679,6 +679,7 @@ on boot # to make it too large, since it may bring userdata loss, if they # are not aware of using fsync()/sync() to prepare sudden power-cut. write /sys/fs/f2fs/${dev.mnt.blk.data}/cp_interval 200 + write /sys/fs/f2fs/${dev.mnt.blk.data}/gc_urgent_sleep_time 50 # Permissions for System Server and daemons. chown radio system /sys/android_power/state |