summaryrefslogtreecommitdiff
path: root/libpagemap
diff options
context:
space:
mode:
authorSandeep Patil <sspatil@google.com>2019-01-19 12:22:36 -0800
committerSandeep Patil <sspatil@google.com>2019-01-19 12:22:36 -0800
commitc1f064caa86300d98aa856cb961d3e09bed66a40 (patch)
tree26fe3c21e4f0c3ee5c0034e4d08b2e2a10c82a77 /libpagemap
parent48f6b916e9b81d4fee3e3d387c72a3d5ea40cae1 (diff)
downloadextras-c1f064caa86300d98aa856cb961d3e09bed66a40.tar.gz
pagemap/tools: remove all pagemap based tools
Bug: 111694435 Test: builds Test: showmap and procrank exist on userdebug builds. Change-Id: I3fb63d3adeedd7dece843cbc38e1667f4309bfd3 Signed-off-by: Sandeep Patil <sspatil@google.com>
Diffstat (limited to 'libpagemap')
-rw-r--r--libpagemap/Android.bp21
-rw-r--r--libpagemap/librank.cpp480
-rw-r--r--libpagemap/procmem.cpp374
-rw-r--r--libpagemap/procrank.cpp610
4 files changed, 0 insertions, 1485 deletions
diff --git a/libpagemap/Android.bp b/libpagemap/Android.bp
index 6a7ee26b..e89d1d8a 100644
--- a/libpagemap/Android.bp
+++ b/libpagemap/Android.bp
@@ -29,27 +29,6 @@ cc_library {
export_include_dirs: ["include"],
}
-cc_binary {
- name: "librank",
- cflags: ["-Werror"],
- srcs: ["librank.cpp"],
- shared_libs: ["libpagemap"],
-}
-
-cc_binary {
- name: "procmem",
- cflags: ["-Werror"],
- srcs: ["procmem.cpp"],
- shared_libs: ["libpagemap"],
-}
-
-cc_binary {
- name: "procrank",
- cflags: ["-Werror"],
- srcs: ["procrank.cpp"],
- shared_libs: ["libpagemap", "libbase"],
-}
-
cc_test {
name: "pagemap_test",
cflags: ["-Werror"],
diff --git a/libpagemap/librank.cpp b/libpagemap/librank.cpp
deleted file mode 100644
index fbba399b..00000000
--- a/libpagemap/librank.cpp
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- * Copyright (C) 2008 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.
- */
-
-#include <errno.h>
-#include <getopt.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <pagemap/pagemap.h>
-
-#define MAX_CMDLINE 256
-
-struct process_info {
- pid_t pid;
- char cmdline[MAX_CMDLINE];
-};
-
-struct mapping_info {
- process_info* proc;
- pm_memusage_t usage;
-};
-
-struct library_info {
- char* name;
- mapping_info** mappings;
- size_t mappings_count;
- size_t mappings_size;
- pm_memusage_t total_usage;
-};
-
-static void usage(char *myname);
-static int getprocname(pid_t pid, char *buf, size_t len);
-static int numcmp(long long a, long long b);
-static int licmp(const void *a, const void *b);
-
-static const char* library_name_blacklist[] = { "[heap]", "[stack]", "", NULL };
-
-#define declare_sort(field) \
- static int sort_by_ ## field (const void *a, const void *b)
-
-declare_sort(vss);
-declare_sort(rss);
-declare_sort(pss);
-declare_sort(uss);
-declare_sort(swap);
-
-#define INIT_LIBRARIES 16
-#define INIT_MAPPINGS 4
-
-static int order;
-
-library_info** libraries;
-size_t libraries_count;
-size_t libraries_size;
-
-library_info* get_library(const char *name, bool all) {
- if (!all) {
- for (size_t i = 0; library_name_blacklist[i]; i++)
- if (!strcmp(name, library_name_blacklist[i]))
- return NULL;
- } else {
- if (name[0] == 0) {
- name = "[anon]";
- }
- }
-
- for (size_t i = 0; i < libraries_count; i++) {
- if (!strcmp(libraries[i]->name, name))
- return libraries[i];
- }
-
- if (libraries_size && libraries_count >= libraries_size) {
- libraries =
- reinterpret_cast<library_info**>(realloc(libraries,
- 2 * libraries_size * sizeof(library_info*)));
- if (!libraries) {
- fprintf(stderr, "Couldn't resize libraries array: %s\n", strerror(errno));
- exit(EXIT_FAILURE);
- }
- libraries_size = 2 * libraries_size;
- }
-
- library_info* library = reinterpret_cast<library_info*>(calloc(1, sizeof(*library)));
- if (!library) {
- fprintf(stderr, "Couldn't allocate space for library struct: %s\n", strerror(errno));
- exit(EXIT_FAILURE);
- }
- library->name = strdup(name);
- if (!library->name) {
- fprintf(stderr, "Couldn't allocate space for library name: %s\n", strerror(errno));
- exit(EXIT_FAILURE);
- }
- library->mappings = reinterpret_cast<mapping_info**>(malloc(INIT_MAPPINGS * sizeof(mapping_info*)));
- if (!library->mappings) {
- fprintf(stderr, "Couldn't allocate space for library mappings array: %s\n", strerror(errno));
- exit(EXIT_FAILURE);
- }
- library->mappings_count = 0; library->mappings_size = INIT_MAPPINGS;
- pm_memusage_zero(&library->total_usage);
-
- libraries[libraries_count++] = library;
-
- return library;
-}
-
-mapping_info* get_mapping(library_info* library, process_info* proc) {
- mapping_info* mapping;
- size_t i;
-
- for (i = 0; i < library->mappings_count; i++) {
- if (library->mappings[i]->proc == proc)
- return library->mappings[i];
- }
-
- if (library->mappings_size && library->mappings_count >= library->mappings_size) {
- library->mappings =
- reinterpret_cast<mapping_info**>(realloc(library->mappings,
- 2 * library->mappings_size * sizeof(mapping_info*)));
- if (!library->mappings) {
- fprintf(stderr, "Couldn't resize mappings array: %s\n", strerror(errno));
- exit(EXIT_FAILURE);
- }
- library->mappings_size = 2 * library->mappings_size;
- }
-
- mapping = reinterpret_cast<mapping_info*>(calloc(1, sizeof(*mapping)));
- if (!mapping) {
- fprintf(stderr, "Couldn't allocate space for mapping struct: %s\n", strerror(errno));
- exit(EXIT_FAILURE);
- }
- mapping->proc = proc;
- pm_memusage_zero(&mapping->usage);
-
- library->mappings[library->mappings_count++] = mapping;
-
- return mapping;
-}
-
-process_info* get_process(pid_t pid) {
- process_info* process = reinterpret_cast<process_info*>(calloc(1, sizeof(*process)));
- if (!process) {
- fprintf(stderr, "Couldn't allocate space for process struct: %s\n", strerror(errno));
- exit(EXIT_FAILURE);
- }
-
- process->pid = pid;
- getprocname(pid, process->cmdline, sizeof(process->cmdline));
-
- return process;
-}
-
-static int parse_perm(const char *perm)
-{
- int ret = 0;
-
- while (*perm) {
- switch(*perm) {
- case 'r':
- ret |= PM_MAP_READ;
- break;
- case 'w':
- ret |= PM_MAP_WRITE;
- break;
- case 'x':
- ret |= PM_MAP_EXEC;
- break;
- default:
- fprintf(stderr, "Unknown permission '%c'\n", *perm);
- exit(EXIT_FAILURE);
- }
- perm++;
- }
- return ret;
-}
-
-int main(int argc, char *argv[]) {
- char *prefix;
- size_t prefix_len;
- int (*compfn)(const void *a, const void *b);
-
- pm_kernel_t *ker;
- pm_process_t *proc;
-
- pid_t *pids;
- size_t num_procs;
-
- pm_map_t **maps;
- size_t num_maps;
- pm_memusage_t map_usage;
-
- library_info* li;
- mapping_info* mi;
- process_info* pi;
-
- size_t i, j;
- int error;
- int perm;
- bool all;
- uint64_t required_flags;
- uint64_t flags_mask;
-
- bool has_swap = false;
-
- signal(SIGPIPE, SIG_IGN);
- compfn = &sort_by_pss;
- order = -1;
- prefix = NULL;
- prefix_len = 0;
- opterr = 0;
- perm = 0;
- all = false;
- required_flags = 0;
- flags_mask = 0;
-
- while (1) {
- int c;
- const option longopts[] = {
- {"all", 0, 0, 'a'},
- {"cached", 0, 0, 'c'},
- {"nocached", 0, 0, 'C'},
- {"ksm", 0, 0, 'k'},
- {"help", 0, 0, 'h'},
- {"pss", 0, 0, 'p'},
- {"uss", 0, 0, 'u'},
- {"vss", 0, 0, 'v'},
- {"rss", 0, 0, 'r'},
- {"swap", 0, 0, 's'},
- {"reverse", 0, 0, 'R'},
- {"path", required_argument, 0, 'P'},
- {"perm", required_argument, 0, 'm'},
- {0, 0, 0, 0}
- };
- c = getopt_long(argc, argv, "acChkm:pP:uvrsR", longopts, NULL);
- if (c < 0) {
- break;
- }
- /* Alphabetical cases */
- switch (c) {
- case 'a':
- all = true;
- break;
- case 'c':
- required_flags = 0;
- flags_mask = (1 << KPF_SWAPBACKED);
- break;
- case 'C':
- required_flags = flags_mask = (1 << KPF_SWAPBACKED);
- break;
- case 'k':
- required_flags = flags_mask = (1 << KPF_KSM);
- break;
- case 'h':
- usage(argv[0]);
- exit(EXIT_SUCCESS);
- case 'm':
- perm = parse_perm(optarg);
- break;
- case 'p':
- compfn = &sort_by_pss;
- break;
- case 'P':
- prefix = optarg;
- prefix_len = strlen(prefix);
- break;
- case 'u':
- compfn = &sort_by_uss;
- break;
- case 'v':
- compfn = &sort_by_vss;
- break;
- case 'r':
- compfn = &sort_by_rss;
- break;
- case 's':
- compfn = &sort_by_swap;
- break;
- case 'R':
- order *= -1;
- break;
- case '?':
- fprintf(stderr, "Invalid argument \"%s\".\n", argv[optind - 1]);
- usage(argv[0]);
- exit(EXIT_FAILURE);
- default:
- abort();
- }
- }
-
- argc -= optind;
- argv += optind;
-
- libraries = reinterpret_cast<library_info**>(malloc(INIT_LIBRARIES * sizeof(library_info*)));
- libraries_count = 0; libraries_size = INIT_LIBRARIES;
- pm_memusage_zero(&map_usage);
-
- error = pm_kernel_create(&ker);
- if (error) {
- fprintf(stderr, "Error initializing kernel interface -- "
- "does this kernel have pagemap?\n");
- exit(EXIT_FAILURE);
- }
-
- error = pm_kernel_pids(ker, &pids, &num_procs);
- if (error) {
- fprintf(stderr, "Error listing processes.\n");
- exit(EXIT_FAILURE);
- }
-
- for (i = 0; i < num_procs; i++) {
- error = pm_process_create(ker, pids[i], &proc);
- if (error) {
- fprintf(stderr, "warning: could not create process interface for %d\n", pids[i]);
- continue;
- }
-
- pi = get_process(pids[i]);
-
- error = pm_process_maps(proc, &maps, &num_maps);
- if (error) {
- fprintf(stderr, "Error listing maps for process %d.\n", proc->pid);
- exit(EXIT_FAILURE);
- }
-
- for (j = 0; j < num_maps; j++) {
- if (prefix && (strncmp(pm_map_name(maps[j]), prefix, prefix_len)))
- continue;
-
- if (perm && (pm_map_flags(maps[j]) & PM_MAP_PERMISSIONS) != perm)
- continue;
-
- li = get_library(pm_map_name(maps[j]), all);
- if (!li)
- continue;
-
- mi = get_mapping(li, pi);
-
- error = pm_map_usage_flags(maps[j], &map_usage, flags_mask,
- required_flags);
- if (error) {
- fprintf(stderr, "Error getting map memory usage of "
- "map %s in process %d.\n",
- pm_map_name(maps[j]), proc->pid);
- exit(EXIT_FAILURE);
- }
-
- if (map_usage.swap) {
- has_swap = true;
- }
-
- pm_memusage_add(&mi->usage, &map_usage);
- pm_memusage_add(&li->total_usage, &map_usage);
- }
- }
-
- printf(" %6s %7s %6s %6s %6s ", "RSStot", "VSS", "RSS", "PSS", "USS");
-
- if (has_swap) {
- printf(" %6s ", "Swap");
- }
-
- printf("Name/PID\n");
- fflush(stdout);
-
- qsort(libraries, libraries_count, sizeof(libraries[0]), &licmp);
-
- for (i = 0; i < libraries_count; i++) {
- li = libraries[i];
-
- printf("%6zdK %7s %6s %6s %6s ", li->total_usage.pss / 1024, "", "", "", "");
- if (has_swap) {
- printf(" %6s ", "");
- }
- printf("%s\n", li->name);
- fflush(stdout);
-
- qsort(li->mappings, li->mappings_count, sizeof(li->mappings[0]), compfn);
-
- for (j = 0; j < li->mappings_count; j++) {
- mi = li->mappings[j];
- pi = mi->proc;
- printf( " %6s %7zdK %6zdK %6zdK %6zdK ", "",
- mi->usage.vss / 1024,
- mi->usage.rss / 1024,
- mi->usage.pss / 1024,
- mi->usage.uss / 1024);
- if (has_swap) {
- printf("%6zdK ", mi->usage.swap / 1024);
- }
- printf(" %s [%d]\n",
- pi->cmdline,
- pi->pid);
- }
- printf("\n");
- fflush(stdout);
- }
-
- exit(0);
-}
-
-static void usage(char *myname) {
- fprintf(stderr, "Usage: %s [ -P | -L ] [ -v | -r | -p | -u | -s | -h ]\n"
- "\n"
- "Sort options:\n"
- " -v Sort processes by VSS.\n"
- " -r Sort processes by RSS.\n"
- " -p Sort processes by PSS.\n"
- " -u Sort processes by USS.\n"
- " -s Sort processes by swap.\n"
- " (Default sort order is PSS.)\n"
- " -a Show all mappings, including stack, heap and anon.\n"
- " -P /path Limit libraries displayed to those in path.\n"
- " -R Reverse sort order (default is descending).\n"
- " -m [r][w][x] Only list pages that exactly match permissions\n"
- " -c Only show cached (storage backed) pages\n"
- " -C Only show non-cached (ram/swap backed) pages\n"
- " -k Only show pages collapsed by KSM\n"
- " -h Display this help screen.\n",
- myname);
-}
-
-static int getprocname(pid_t pid, char *buf, size_t len) {
- char filename[32];
- FILE *f;
-
- snprintf(filename, sizeof(filename), "/proc/%d/cmdline", pid);
- f = fopen(filename, "r");
- if (!f) {
- *buf = '\0';
- return 1;
- }
- if (!fgets(buf, len, f)) {
- *buf = '\0';
- fclose(f);
- return 2;
- }
- fclose(f);
- return 0;
-}
-
-static int numcmp(long long a, long long b) {
- if (a < b) return -1;
- if (a > b) return 1;
- return 0;
-}
-
-static int licmp(const void *a, const void *b) {
- return order * numcmp(
- (*((library_info**)a))->total_usage.pss,
- (*((library_info**)b))->total_usage.pss
- );
-}
-
-#define create_sort(field, compfn) \
- static int sort_by_ ## field (const void *a, const void *b) { \
- return order * compfn( \
- (*((mapping_info**)a))->usage.field, \
- (*((mapping_info**)b))->usage.field \
- ); \
- }
-
-create_sort(vss, numcmp)
-create_sort(rss, numcmp)
-create_sort(pss, numcmp)
-create_sort(uss, numcmp)
-create_sort(swap, numcmp)
diff --git a/libpagemap/procmem.cpp b/libpagemap/procmem.cpp
deleted file mode 100644
index e8eb4eda..00000000
--- a/libpagemap/procmem.cpp
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
- * Copyright (C) 2008 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.
- */
-
-#include <errno.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <pagemap/pagemap.h>
-
-/* Information about a single mapping */
-struct map_info {
- pm_map_t *map;
- pm_memusage_t usage;
- /* page counts */
- unsigned long shared_clean;
- unsigned long shared_dirty;
- unsigned long private_clean;
- unsigned long private_dirty;
-};
-
-/* display the help screen */
-static void usage(const char *cmd);
-
-/* qsort compare function to compare maps by PSS */
-int comp_pss(const void *a, const void *b);
-
-/* qsort compare function to compare maps by USS */
-int comp_uss(const void* a, const void* b);
-
-int main(int argc, char *argv[]) {
- pid_t pid;
-
- /* libpagemap context */
- pm_kernel_t *ker;
- int pagesize; /* cached for speed */
- pm_process_t *proc;
-
- /* maps and such */
- pm_map_t **maps; size_t num_maps;
-
- struct map_info **mis = NULL;
- struct map_info *mi;
-
- /* pagemap information */
- uint64_t *pagemap; size_t num_pages;
- uint64_t mapentry;
- uint64_t count, flags;
-
- /* totals */
- unsigned long total_shared_clean, total_shared_dirty, total_private_clean, total_private_dirty;
- pm_memusage_t total_usage;
-
- /* command-line options */
- int ws;
-#define WS_OFF (0)
-#define WS_ONLY (1)
-#define WS_RESET (2)
- int (*compfn)(const void *a, const void *b);
- int hide_zeros;
-
- /* Use kernel's idle page tracking interface for working set determination */
- int use_pageidle;
-
- /* temporary variables */
- size_t i, j;
- char *endptr;
- int error;
-
- if (argc < 2) {
- usage(argv[0]);
- exit(EXIT_FAILURE);
- }
-
- ws = WS_OFF;
- compfn = NULL;
- hide_zeros = 0;
- use_pageidle = 0;
- for (i = 1; i < (size_t)(argc - 1); i++) {
- if (!strcmp(argv[i], "-w")) { ws = WS_ONLY; continue; }
- if (!strcmp(argv[i], "-W")) { ws = WS_RESET; continue; }
- if (!strcmp(argv[i], "-i")) {
- use_pageidle = 1;
- continue;
- }
- if (!strcmp(argv[i], "-m")) { compfn = NULL; continue; }
- if (!strcmp(argv[i], "-p")) { compfn = &comp_pss; continue; }
- if (!strcmp(argv[i], "-u")) {
- compfn = &comp_uss;
- continue;
- }
- if (!strcmp(argv[i], "-h")) { hide_zeros = 1; continue; }
- fprintf(stderr, "Invalid argument \"%s\".\n", argv[i]);
- usage(argv[0]);
- exit(EXIT_FAILURE);
- }
-
- pid = (pid_t)strtol(argv[argc - 1], &endptr, 10);
- if (*endptr != '\0') {
- fprintf(stderr, "Invalid PID \"%s\".\n", argv[argc - 1]);
- exit(EXIT_FAILURE);
- }
-
- error = pm_kernel_create(&ker);
- if (error) {
- fprintf(stderr, "error creating kernel interface -- "
- "does this kernel have pagemap?\n");
- exit(EXIT_FAILURE);
- }
-
- if (ws != WS_OFF && use_pageidle) {
- error = pm_kernel_init_page_idle(ker);
- if (error) {
- fprintf(stderr,
- "error initalizing idle page tracking -- "
- "enable CONFIG_IDLE_PAGE_TRACKING in kernel.\n");
- exit(EXIT_FAILURE);
- }
- }
-
- pagesize = pm_kernel_pagesize(ker);
-
- error = pm_process_create(ker, pid, &proc);
- if (error) {
- fprintf(stderr, "error creating process interface -- "
- "does process %d really exist?\n", pid);
- exit(EXIT_FAILURE);
- }
-
- if (ws != WS_OFF) {
- /*
- * The idle page tracking interface will update the PageIdle flags
- * upon writing. So, even if we are called only to read the *current*
- * working set, we need to reset the bitmap to make sure we get
- * the updated page idle flags. This is not true with the 'clear_refs'
- * implementation.
- */
- if (ws == WS_RESET || use_pageidle) {
- error = pm_process_workingset(proc, NULL, 1);
- if (error) {
- fprintf(stderr, "error resetting working set for process.\n");
- exit(EXIT_FAILURE);
- }
- }
- if (ws == WS_RESET) exit(EXIT_SUCCESS);
- }
-
- /* get maps, and allocate our map_info array */
- error = pm_process_maps(proc, &maps, &num_maps);
- if (error) {
- fprintf(stderr, "error listing maps.\n");
- exit(EXIT_FAILURE);
- }
-
- mis = (struct map_info **)calloc(num_maps, sizeof(struct map_info *));
- if (!mis) {
- fprintf(stderr, "error allocating map_info array: %s\n", strerror(errno));
- exit(EXIT_FAILURE);
- }
-
- /* print header */
- if (ws == WS_ONLY) {
- printf("%7s %7s %7s %7s %7s %7s %7s %s\n",
- "WRss", "WPss", "WUss", "WShCl", "WShDi", "WPrCl", "WPrDi", "Name");
- printf("%7s %7s %7s %7s %7s %7s %7s %s\n",
- "-------", "-------", "-------", "-------", "-------", "-------", "-------", "");
- } else {
- printf("%7s %7s %7s %7s %7s %7s %7s %7s %s\n",
- "Vss", "Rss", "Pss", "Uss", "ShCl", "ShDi", "PrCl", "PrDi", "Name");
- printf("%7s %7s %7s %7s %7s %7s %7s %7s %s\n",
- "-------", "-------", "-------", "-------", "-------", "-------", "-------", "-------", "");
- }
-
- /* zero things */
- pm_memusage_zero(&total_usage);
- total_shared_clean = total_shared_dirty = total_private_clean = total_private_dirty = 0;
-
- for (i = 0; i < num_maps; i++) {
- mi = (struct map_info *)calloc(1, sizeof(struct map_info));
- if (!mi) {
- fprintf(stderr, "error allocating map_info: %s\n", strerror(errno));
- exit(EXIT_FAILURE);
- }
-
- mi->map = maps[i];
-
- /* get, and sum, memory usage */
-
- if (ws == WS_ONLY)
- error = pm_map_workingset(mi->map, &mi->usage);
- else
- error = pm_map_usage(mi->map, &mi->usage);
- if (error) {
- fflush(stdout);
- fprintf(stderr, "error getting usage for map.\n");
- continue;
- }
-
- pm_memusage_add(&total_usage, &mi->usage);
-
- /* get, and sum, individual page counts */
-
- error = pm_map_pagemap(mi->map, &pagemap, &num_pages);
- if (error) {
- fflush(stdout);
- fprintf(stderr, "error getting pagemap for map.\n");
- continue;
- }
-
- mi->shared_clean = mi->shared_dirty = mi->private_clean = mi->private_dirty = 0;
-
- for (j = 0; j < num_pages; j++) {
- mapentry = pagemap[j];
-
- if (PM_PAGEMAP_PRESENT(mapentry) && !PM_PAGEMAP_SWAPPED(mapentry)) {
-
- error = pm_kernel_count(ker, PM_PAGEMAP_PFN(mapentry), &count);
- if (error) {
- fflush(stdout);
- fprintf(stderr, "error getting count for frame.\n");
- }
-
- error = pm_kernel_flags(ker, PM_PAGEMAP_PFN(mapentry), &flags);
- if (error) {
- fflush(stdout);
- fprintf(stderr, "error getting flags for frame.\n");
- }
-
- if ((ws != WS_ONLY) ||
- pm_kernel_page_is_accessed(ker, PM_PAGEMAP_PFN(mapentry), &flags)) {
- if (count > 1) {
- if (flags & (1 << KPF_DIRTY)) {
- mi->shared_dirty++;
- } else {
- mi->shared_clean++;
- }
- } else {
- if (flags & (1 << KPF_DIRTY)) {
- mi->private_dirty++;
- } else {
- mi->private_clean++;
- }
- }
- }
- }
- }
-
- total_shared_clean += mi->shared_clean;
- total_shared_dirty += mi->shared_dirty;
- total_private_clean += mi->private_clean;
- total_private_dirty += mi->private_dirty;
-
- /* add to array */
- mis[i] = mi;
- }
-
- /* sort the array, if requested (compfn == NULL for original order) */
- if (compfn)
- qsort(mis, num_maps, sizeof(mis[0]), compfn);
-
- for (i = 0; i < num_maps; i++) {
- mi = mis[i];
-
- if ((!mi) || (hide_zeros && !mi->usage.rss))
- continue;
-
- if (ws == WS_ONLY) {
- printf("%6ldK %6ldK %6ldK %6ldK %6ldK %6ldK %6ldK %s\n",
- (long)mi->usage.rss / 1024,
- (long)mi->usage.pss / 1024,
- (long)mi->usage.uss / 1024,
- mi->shared_clean * pagesize / 1024,
- mi->shared_dirty * pagesize / 1024,
- mi->private_clean * pagesize / 1024,
- mi->private_dirty * pagesize / 1024,
- pm_map_name(mi->map)
- );
- } else {
- printf("%6ldK %6ldK %6ldK %6ldK %6ldK %6ldK %6ldK %6ldK %s\n",
- (long)mi->usage.vss / 1024,
- (long)mi->usage.rss / 1024,
- (long)mi->usage.pss / 1024,
- (long)mi->usage.uss / 1024,
- mi->shared_clean * pagesize / 1024,
- mi->shared_dirty * pagesize / 1024,
- mi->private_clean * pagesize / 1024,
- mi->private_dirty * pagesize / 1024,
- pm_map_name(mi->map)
- );
- }
- }
-
- /* print totals */
- if (ws == WS_ONLY) {
- printf("%7s %7s %7s %7s %7s %7s %7s %s\n",
- "-------", "-------", "-------", "-------", "-------", "-------", "-------", "");
- printf("%6ldK %6ldK %6ldK %6ldK %6ldK %6ldK %6ldK %s\n",
- (long)total_usage.rss / 1024,
- (long)total_usage.pss / 1024,
- (long)total_usage.uss / 1024,
- total_shared_clean * pagesize / 1024,
- total_shared_dirty * pagesize / 1024,
- total_private_clean * pagesize / 1024,
- total_private_dirty * pagesize / 1024,
- "TOTAL"
- );
- } else {
- printf("%7s %7s %7s %7s %7s %7s %7s %7s %s\n",
- "-------", "-------", "-------", "-------", "-------", "-------", "-------", "-------", "");
- printf("%6ldK %6ldK %6ldK %6ldK %6ldK %6ldK %6ldK %6ldK %s\n",
- (long)total_usage.vss / 1024,
- (long)total_usage.rss / 1024,
- (long)total_usage.pss / 1024,
- (long)total_usage.uss / 1024,
- total_shared_clean * pagesize / 1024,
- total_shared_dirty * pagesize / 1024,
- total_private_clean * pagesize / 1024,
- total_private_dirty * pagesize / 1024,
- "TOTAL"
- );
- }
-
- free(mis);
- return 0;
-}
-
-static void usage(const char* cmd) {
- fprintf(stderr,
- "Usage: %s [-i] [ -w | -W ] [ -p | -m ] [ -h ] pid\n"
- " -i Uses idle page tracking for working set statistics.\n"
- " -w Displays statistics for the working set only.\n"
- " -W Resets the working set of the process.\n"
- " -p Sort by PSS.\n"
- " -u Sort by USS.\n"
- " -m Sort by mapping order (as read from /proc).\n"
- " -h Hide maps with no RSS.\n",
- cmd);
-}
-
-int comp_pss(const void *a, const void *b) {
- struct map_info *ma, *mb;
-
- ma = *((struct map_info **)a);
- mb = *((struct map_info **)b);
-
- if (mb->usage.pss < ma->usage.pss) return -1;
- if (mb->usage.pss > ma->usage.pss) return 1;
- return 0;
-}
-
-int comp_uss(const void* a, const void* b) {
- struct map_info *ma, *mb;
-
- ma = *((struct map_info**)a);
- mb = *((struct map_info**)b);
-
- if (mb->usage.uss < ma->usage.uss) return -1;
- if (mb->usage.uss > ma->usage.uss) return 1;
- return 0;
-}
diff --git a/libpagemap/procrank.cpp b/libpagemap/procrank.cpp
deleted file mode 100644
index 7519e3b8..00000000
--- a/libpagemap/procrank.cpp
+++ /dev/null
@@ -1,610 +0,0 @@
-//
-// Copyright (C) 2008 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.
-//
-
-#include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <vector>
-
-#include <android-base/file.h>
-#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
-#include <pagemap/pagemap.h>
-
-struct proc_info {
- pid_t pid;
- pm_memusage_t usage;
- uint64_t wss;
- int oomadj;
-};
-
-static void usage(char *myname);
-static std::string getprocname(pid_t pid);
-static int getoomadj(pid_t pid);
-static bool getminfree(std::vector<uint64_t>* minfree, std::vector<int>* adj);
-static int numcmp(uint64_t a, uint64_t b);
-
-#define declare_sort(field) \
- static int sort_by_ ## field (const void *a, const void *b)
-
-declare_sort(vss);
-declare_sort(rss);
-declare_sort(pss);
-declare_sort(uss);
-declare_sort(swap);
-declare_sort(oomadj);
-
-int (*compfn)(const void *a, const void *b);
-static int order;
-
-enum {
- MEMINFO_TOTAL,
- MEMINFO_FREE,
- MEMINFO_BUFFERS,
- MEMINFO_CACHED,
- MEMINFO_SHMEM,
- MEMINFO_SLAB,
- MEMINFO_SWAP_TOTAL,
- MEMINFO_SWAP_FREE,
- MEMINFO_ZRAM_TOTAL,
- MEMINFO_MAPPED,
- MEMINFO_VMALLOC_USED,
- MEMINFO_PAGE_TABLES,
- MEMINFO_KERNEL_STACK,
- MEMINFO_COUNT
-};
-
-void get_mem_info(uint64_t mem[]) {
- char buffer[1024];
- unsigned int numFound = 0;
-
- int fd = open("/proc/meminfo", O_RDONLY);
-
- if (fd < 0) {
- printf("Unable to open /proc/meminfo: %s\n", strerror(errno));
- return;
- }
-
- const int len = read(fd, buffer, sizeof(buffer)-1);
- close(fd);
-
- if (len < 0) {
- printf("Empty /proc/meminfo");
- return;
- }
- buffer[len] = 0;
-
- static const char* const tags[] = {
- "MemTotal:",
- "MemFree:",
- "Buffers:",
- "Cached:",
- "Shmem:",
- "Slab:",
- "SwapTotal:",
- "SwapFree:",
- "ZRam:", // not read from meminfo but from /sys/block/zram0
- "Mapped:",
- "VmallocUsed:",
- "PageTables:",
- "KernelStack:",
- NULL
- };
- static const int tagsLen[] = {
- 9,
- 8,
- 8,
- 7,
- 6,
- 5,
- 10,
- 9,
- 5,
- 7,
- 12,
- 11,
- 12,
- 0
- };
-
- char* p = buffer;
- while (*p && (numFound < (sizeof(tagsLen) / sizeof(tagsLen[0])))) {
- int i = 0;
- while (tags[i]) {
- if (strncmp(p, tags[i], tagsLen[i]) == 0) {
- p += tagsLen[i];
- while (*p == ' ') p++;
- char* num = p;
- while (*p >= '0' && *p <= '9') p++;
- if (*p != 0) {
- *p = 0;
- p++;
- }
- mem[i] = atoll(num);
- numFound++;
- break;
- }
- i++;
- }
- while (*p && *p != '\n') {
- p++;
- }
- if (*p) p++;
- }
-}
-
-static uint64_t get_zram_mem_used() {
-#define ZRAM_SYSFS "/sys/block/zram0/"
- FILE *f = fopen(ZRAM_SYSFS "mm_stat", "r");
- if (f) {
- uint64_t mem_used_total = 0;
-
- int matched = fscanf(f, "%*d %*d %" SCNu64 " %*d %*d %*d %*d", &mem_used_total);
- if (matched != 1)
- fprintf(stderr, "warning: failed to parse " ZRAM_SYSFS "mm_stat\n");
-
- fclose(f);
- return mem_used_total;
- }
-
- f = fopen(ZRAM_SYSFS "mem_used_total", "r");
- if (f) {
- uint64_t mem_used_total = 0;
-
- int matched = fscanf(f, "%" SCNu64, &mem_used_total);
- if (matched != 1)
- fprintf(stderr, "warning: failed to parse " ZRAM_SYSFS "mem_used_total\n");
-
- fclose(f);
- return mem_used_total;
- }
-
- return 0;
-}
-
-int main(int argc, char *argv[]) {
- pm_kernel_t *ker;
- pm_process_t *proc;
- pid_t *pids;
- size_t num_procs;
- uint64_t total_pss;
- uint64_t total_uss;
- uint64_t total_swap;
- uint64_t total_pswap;
- uint64_t total_uswap;
- uint64_t total_zswap;
- int error;
- bool has_swap = false, has_zram = false;
- uint64_t required_flags = 0;
- uint64_t flags_mask = 0;
-
- int arg;
- size_t i;
-
- enum {
- WS_OFF,
- WS_ONLY,
- WS_RESET,
- } ws;
-
- uint64_t mem[MEMINFO_COUNT] = { };
- pm_proportional_swap_t *p_swap;
- float zram_cr = 0.0;
-
- signal(SIGPIPE, SIG_IGN);
- compfn = &sort_by_pss;
- order = -1;
- ws = WS_OFF;
- bool oomadj = false;
-
- for (arg = 1; arg < argc; arg++) {
- if (!strcmp(argv[arg], "-v")) { compfn = &sort_by_vss; continue; }
- if (!strcmp(argv[arg], "-r")) { compfn = &sort_by_rss; continue; }
- if (!strcmp(argv[arg], "-p")) { compfn = &sort_by_pss; continue; }
- if (!strcmp(argv[arg], "-u")) { compfn = &sort_by_uss; continue; }
- if (!strcmp(argv[arg], "-s")) { compfn = &sort_by_swap; continue; }
- if (!strcmp(argv[arg], "-o")) { compfn = &sort_by_oomadj; oomadj = true; continue; }
- if (!strcmp(argv[arg], "-c")) { required_flags = 0; flags_mask = (1 << KPF_SWAPBACKED); continue; }
- if (!strcmp(argv[arg], "-C")) { required_flags = flags_mask = (1 << KPF_SWAPBACKED); continue; }
- if (!strcmp(argv[arg], "-k")) { required_flags = flags_mask = (1 << KPF_KSM); continue; }
- if (!strcmp(argv[arg], "-w")) { ws = WS_ONLY; continue; }
- if (!strcmp(argv[arg], "-W")) { ws = WS_RESET; continue; }
- if (!strcmp(argv[arg], "-R")) { order *= -1; continue; }
- if (!strcmp(argv[arg], "-h")) { usage(argv[0]); exit(0); }
- fprintf(stderr, "Invalid argument \"%s\".\n", argv[arg]);
- usage(argv[0]);
- exit(EXIT_FAILURE);
- }
-
- get_mem_info(mem);
- p_swap = pm_memusage_pswap_create(mem[MEMINFO_SWAP_TOTAL] * 1024);
-
- error = pm_kernel_create(&ker);
- if (error) {
- fprintf(stderr, "Error creating kernel interface -- "
- "does this kernel have pagemap?\n");
- exit(EXIT_FAILURE);
- }
-
- error = pm_kernel_pids(ker, &pids, &num_procs);
- if (error) {
- fprintf(stderr, "Error listing processes.\n");
- exit(EXIT_FAILURE);
- }
-
- std::vector<proc_info> procs(num_procs);
- for (i = 0; i < num_procs; i++) {
- procs[i].pid = pids[i];
- procs[i].oomadj = getoomadj(pids[i]);
- pm_memusage_zero(&procs[i].usage);
- pm_memusage_pswap_init_handle(&procs[i].usage, p_swap);
- error = pm_process_create(ker, pids[i], &proc);
- if (error) {
- fprintf(stderr, "warning: could not create process interface for %d\n", pids[i]);
- continue;
- }
-
- switch (ws) {
- case WS_OFF:
- error = pm_process_usage_flags(proc, &procs[i].usage, flags_mask,
- required_flags);
- break;
- case WS_ONLY:
- error = pm_process_workingset(proc, &procs[i].usage, 0);
- break;
- case WS_RESET:
- error = pm_process_workingset(proc, NULL, 1);
- break;
- }
-
- if (error) {
- fprintf(stderr, "warning: could not read usage for %d\n", pids[i]);
- }
-
- if (ws != WS_RESET && procs[i].usage.swap) {
- has_swap = true;
- }
-
- pm_process_destroy(proc);
- }
-
- free(pids);
-
- if (ws == WS_RESET) exit(0);
-
- procs.erase(std::remove_if(procs.begin(),
- procs.end(),
- [](auto proc){
- return proc.usage.vss == 0;
- }),
- procs.end());
-
- qsort(procs.data(), procs.size(), sizeof(procs[0]), compfn);
-
- if (has_swap) {
- uint64_t zram_mem_used = get_zram_mem_used();
- if (zram_mem_used) {
- mem[MEMINFO_ZRAM_TOTAL] = zram_mem_used/1024;
- zram_cr = (float) mem[MEMINFO_ZRAM_TOTAL] /
- (mem[MEMINFO_SWAP_TOTAL] - mem[MEMINFO_SWAP_FREE]);
- has_zram = true;
- }
- }
-
- printf("%5s ", "PID");
- if (oomadj) {
- printf("%5s ", "oom");
- }
- if (ws) {
- printf("%7s %7s %7s ", "WRss", "WPss", "WUss");
- if (has_swap) {
- printf("%7s %7s %7s ", "WSwap", "WPSwap", "WUSwap");
- if (has_zram) {
- printf("%7s ", "WZSwap");
- }
- }
- } else {
- printf("%8s %7s %7s %7s ", "Vss", "Rss", "Pss", "Uss");
- if (has_swap) {
- printf("%7s %7s %7s ", "Swap", "PSwap", "USwap");
- if (has_zram) {
- printf("%7s ", "ZSwap");
- }
- }
- }
-
- printf("%s\n", "cmdline");
-
- total_pss = 0;
- total_uss = 0;
- total_swap = 0;
- total_pswap = 0;
- total_uswap = 0;
- total_zswap = 0;
-
- std::vector<uint64_t> lmk_minfree;
- std::vector<int> lmk_adj;
- if (oomadj) {
- getminfree(&lmk_minfree, &lmk_adj);
- }
- auto lmk_minfree_it = lmk_minfree.cbegin();
- auto lmk_adj_it = lmk_adj.cbegin();
-
- auto print_oomadj_totals = [&](int adj){
- for (; lmk_adj_it != lmk_adj.cend() && lmk_minfree_it != lmk_minfree.cend() &&
- adj > *lmk_adj_it; lmk_adj_it++, lmk_minfree_it++) {
- // Print the cumulative total line
- printf("%5s ", ""); // pid
-
- printf("%5s ", ""); // oomadj
-
- if (ws) {
- printf("%7s %6" PRIu64 "K %6" PRIu64 "K ",
- "", total_pss / 1024, total_uss / 1024);
- } else {
- printf("%8s %7s %6" PRIu64 "K %6" PRIu64 "K ",
- "", "", total_pss / 1024, total_uss / 1024);
- }
-
- if (has_swap) {
- printf("%6" PRIu64 "K ", total_swap / 1024);
- printf("%6" PRIu64 "K ", total_pswap / 1024);
- printf("%6" PRIu64 "K ", total_uswap / 1024);
- if (has_zram) {
- printf("%6" PRIu64 "K ", total_zswap / 1024);
- }
- }
-
- printf("TOTAL for oomadj < %d (%6" PRIu64 "K)\n", *lmk_adj_it, *lmk_minfree_it / 1024);
- }
- };
-
- for (auto& proc: procs) {
- if (oomadj) {
- print_oomadj_totals(proc.oomadj);
- }
-
- std::string cmdline = getprocname(proc.pid);
-
- total_pss += proc.usage.pss;
- total_uss += proc.usage.uss;
- total_swap += proc.usage.swap;
-
- printf("%5d ", proc.pid);
-
- if (oomadj) {
- printf("%5d ", proc.oomadj);
- }
-
- if (ws) {
- printf("%6zuK %6zuK %6zuK ",
- proc.usage.rss / 1024,
- proc.usage.pss / 1024,
- proc.usage.uss / 1024
- );
- } else {
- printf("%7zuK %6zuK %6zuK %6zuK ",
- proc.usage.vss / 1024,
- proc.usage.rss / 1024,
- proc.usage.pss / 1024,
- proc.usage.uss / 1024
- );
- }
-
- if (has_swap) {
- pm_swapusage_t su;
-
- pm_memusage_pswap_get_usage(&proc.usage, &su);
- printf("%6zuK ", proc.usage.swap / 1024);
- printf("%6zuK ", su.proportional / 1024);
- printf("%6zuK ", su.unique / 1024);
- total_pswap += su.proportional;
- total_uswap += su.unique;
- pm_memusage_pswap_free(&proc.usage);
- if (has_zram) {
- size_t zpswap = su.proportional * zram_cr;
- printf("%6zuK ", zpswap / 1024);
- total_zswap += zpswap;
- }
- }
-
- printf("%s\n", cmdline.c_str());
- }
-
- pm_memusage_pswap_destroy(p_swap);
-
- if (oomadj) {
- print_oomadj_totals(INT_MAX);
- }
-
- // Print the separator line
- printf("%5s ", "");
-
- if (oomadj) {
- printf("%5s ", "");
- }
-
- if (ws) {
- printf("%7s %7s %7s ", "", "------", "------");
- } else {
- printf("%8s %7s %7s %7s ", "", "", "------", "------");
- }
-
- if (has_swap) {
- printf("%7s %7s %7s ", "------", "------", "------");
- if (has_zram) {
- printf("%7s ", "------");
- }
- }
-
- printf("%s\n", "------");
-
- // Print the total line
- printf("%5s ", "");
-
- if (oomadj) {
- printf("%5s ", "");
- }
-
- if (ws) {
- printf("%7s %6" PRIu64 "K %6" PRIu64 "K ",
- "", total_pss / 1024, total_uss / 1024);
- } else {
- printf("%8s %7s %6" PRIu64 "K %6" PRIu64 "K ",
- "", "", total_pss / 1024, total_uss / 1024);
- }
-
- if (has_swap) {
- printf("%6" PRIu64 "K ", total_swap / 1024);
- printf("%6" PRIu64 "K ", total_pswap / 1024);
- printf("%6" PRIu64 "K ", total_uswap / 1024);
- if (has_zram) {
- printf("%6" PRIu64 "K ", total_zswap / 1024);
- }
- }
-
- printf("TOTAL\n");
-
- printf("\n");
-
- if (has_swap) {
- printf("ZRAM: %" PRIu64 "K physical used for %" PRIu64 "K in swap "
- "(%" PRIu64 "K total swap)\n",
- mem[MEMINFO_ZRAM_TOTAL], (mem[MEMINFO_SWAP_TOTAL] - mem[MEMINFO_SWAP_FREE]),
- mem[MEMINFO_SWAP_TOTAL]);
- }
- printf(" RAM: %" PRIu64 "K total, %" PRIu64 "K free, %" PRIu64 "K buffers, "
- "%" PRIu64 "K cached, %" PRIu64 "K shmem, %" PRIu64 "K slab\n",
- mem[MEMINFO_TOTAL], mem[MEMINFO_FREE], mem[MEMINFO_BUFFERS],
- mem[MEMINFO_CACHED], mem[MEMINFO_SHMEM], mem[MEMINFO_SLAB]);
-
- return 0;
-}
-
-static void usage(char *myname) {
- fprintf(stderr, "Usage: %s [ -W ] [ -v | -r | -p | -u | -s | -h ]\n"
- " -v Sort by VSS.\n"
- " -r Sort by RSS.\n"
- " -p Sort by PSS.\n"
- " -u Sort by USS.\n"
- " -s Sort by swap.\n"
- " (Default sort order is PSS.)\n"
- " -R Reverse sort order (default is descending).\n"
- " -c Only show cached (storage backed) pages\n"
- " -C Only show non-cached (ram/swap backed) pages\n"
- " -k Only show pages collapsed by KSM\n"
- " -w Display statistics for working set only.\n"
- " -W Reset working set of all processes.\n"
- " -o Show and sort by oom score against lowmemorykiller thresholds.\n"
- " -h Display this help screen.\n",
- myname);
-}
-
-// Get the process name for a given PID.
-static std::string getprocname(pid_t pid) {
- std::string filename = android::base::StringPrintf("/proc/%d/cmdline", pid);
-
- std::string procname;
- if (!android::base::ReadFileToString(filename, &procname)) {
- // The process went away before we could read its process name.
- procname = "<unknown>";
- }
-
- return procname;
-}
-
-static int getoomadj(pid_t pid) {
- std::string filename = android::base::StringPrintf("/proc/%d/oom_score_adj", pid);
- std::string oomadj;
-
- if (!android::base::ReadFileToString(filename, &oomadj)) {
- return -1001;
- }
-
- return strtol(oomadj.c_str(), NULL, 10);
-}
-
-static bool getminfree(std::vector<uint64_t>* minfree, std::vector<int>* adj) {
- std::string minfree_str;
- std::string adj_str;
-
- if (!android::base::ReadFileToString("/sys/module/lowmemorykiller/parameters/minfree", &minfree_str)) {
- return false;
- }
-
- if (!android::base::ReadFileToString("/sys/module/lowmemorykiller/parameters/adj", &adj_str)) {
- return false;
- }
-
- std::vector<std::string> minfree_vec = android::base::Split(minfree_str, ",");
- std::vector<std::string> adj_vec = android::base::Split(adj_str, ",");
-
- minfree->clear();
- minfree->resize(minfree_vec.size());
- adj->clear();
- adj->resize(adj_vec.size());
-
- std::transform(minfree_vec.begin(), minfree_vec.end(), minfree->begin(),
- [](const std::string& s) -> uint64_t {
- return strtoull(s.c_str(), NULL, 10) * PAGE_SIZE;
- });
-
- std::transform(adj_vec.begin(), adj_vec.end(), adj->begin(),
- [](const std::string& s) -> int {
- return strtol(s.c_str(), NULL, 10);
- });
-
- return true;
-}
-
-static int numcmp(uint64_t a, uint64_t b) {
- if (a < b) return -1;
- if (a > b) return 1;
- return 0;
-}
-
-static int snumcmp(int64_t a, int64_t b) {
- if (a < b) return -1;
- if (a > b) return 1;
- return 0;
-}
-
-#define create_sort(field, compfn) \
- static int sort_by_ ## field (const void *a, const void *b) { \
- return order * compfn( \
- ((struct proc_info*)(a))->usage.field, \
- ((struct proc_info*)(b))->usage.field \
- ); \
- }
-
-create_sort(vss, numcmp)
-create_sort(rss, numcmp)
-create_sort(pss, numcmp)
-create_sort(uss, numcmp)
-create_sort(swap, numcmp)
-
-static int sort_by_oomadj (const void *a, const void *b) {
- // Negative oomadj is higher priority, reverse the sort order
- return -1 * order * snumcmp(
- ((struct proc_info*)a)->oomadj,
- ((struct proc_info*)b)->oomadj
- );
-}