procrank.c revision 83b0b0a57a0c20984e207e4d6987faeba736140c
1e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project/*
2e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project *
4e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * you may not use this file except in compliance with the License.
6e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * You may obtain a copy of the License at
7e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project *
8e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project *
10e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * See the License for the specific language governing permissions and
14e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project * limitations under the License.
15e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project */
16e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
17e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <dirent.h>
18e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <errno.h>
19e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <stdlib.h>
20e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <sys/types.h>
21e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <unistd.h>
22b56034796a7cadee89c4cd5e3c0f0730193231deOlivier Bailly#include <string.h>
23e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn#include <fcntl.h>
24e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
25e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#include <pagemap/pagemap.h>
26e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
27e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstruct proc_info {
28e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    pid_t pid;
29e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    pm_memusage_t usage;
30e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    unsigned long wss;
31e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project};
32e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
33e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic void usage(char *myname);
3416abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Rootstatic int getprocname(pid_t pid, char *buf, int len);
35e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic int numcmp(long long a, long long b);
36e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
37e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#define declare_sort(field) \
38e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    static int sort_by_ ## field (const void *a, const void *b)
39e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
40e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectdeclare_sort(vss);
41e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectdeclare_sort(rss);
42e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectdeclare_sort(pss);
43e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectdeclare_sort(uss);
44e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
45e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectint (*compfn)(const void *a, const void *b);
46e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic int order;
47e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
48e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackbornvoid print_mem_info() {
4983b0b0a57a0c20984e207e4d6987faeba736140cDianne Hackborn    char buffer[1024];
50e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn    int numFound = 0;
51e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn
52e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn    int fd = open("/proc/meminfo", O_RDONLY);
53e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn
54e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn    if (fd < 0) {
55e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn        printf("Unable to open /proc/meminfo: %s\n", strerror(errno));
56e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn        return;
57e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn    }
58e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn
59e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn    const int len = read(fd, buffer, sizeof(buffer)-1);
60e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn    close(fd);
61e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn
62e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn    if (len < 0) {
63e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn        printf("Empty /proc/meminfo");
64e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn        return;
65e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn    }
66e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn    buffer[len] = 0;
67e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn
68e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn    static const char* const tags[] = {
69e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn            "MemTotal:",
70e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn            "MemFree:",
71e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn            "Buffers:",
72e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn            "Cached:",
7383b0b0a57a0c20984e207e4d6987faeba736140cDianne Hackborn            "Shmem:",
7483b0b0a57a0c20984e207e4d6987faeba736140cDianne Hackborn            "Slab:",
75e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn            NULL
76e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn    };
77e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn    static const int tagsLen[] = {
78e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn            9,
79e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn            8,
80e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn            8,
81e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn            7,
8283b0b0a57a0c20984e207e4d6987faeba736140cDianne Hackborn            6,
8383b0b0a57a0c20984e207e4d6987faeba736140cDianne Hackborn            5,
84e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn            0
85e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn    };
8683b0b0a57a0c20984e207e4d6987faeba736140cDianne Hackborn    long mem[] = { 0, 0, 0, 0, 0, 0 };
87e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn
88e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn    char* p = buffer;
8983b0b0a57a0c20984e207e4d6987faeba736140cDianne Hackborn    while (*p && numFound < 6) {
90e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn        int i = 0;
91e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn        while (tags[i]) {
92e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn            if (strncmp(p, tags[i], tagsLen[i]) == 0) {
93e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn                p += tagsLen[i];
94e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn                while (*p == ' ') p++;
95e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn                char* num = p;
96e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn                while (*p >= '0' && *p <= '9') p++;
97e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn                if (*p != 0) {
98e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn                    *p = 0;
99e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn                    p++;
100e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn                }
101e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn                mem[i] = atoll(num);
102e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn                numFound++;
103e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn                break;
104e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn            }
105e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn            i++;
106e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn        }
10783b0b0a57a0c20984e207e4d6987faeba736140cDianne Hackborn        while (*p && *p != '\n') {
10883b0b0a57a0c20984e207e4d6987faeba736140cDianne Hackborn            p++;
10983b0b0a57a0c20984e207e4d6987faeba736140cDianne Hackborn        }
11083b0b0a57a0c20984e207e4d6987faeba736140cDianne Hackborn        if (*p) p++;
111e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn    }
112e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn
11383b0b0a57a0c20984e207e4d6987faeba736140cDianne Hackborn    printf("RAM: %ldK total, %ldK free, %ldK buffers, %ldK cached, %ldK shmem, %ldK slab\n",
11483b0b0a57a0c20984e207e4d6987faeba736140cDianne Hackborn            mem[0], mem[1], mem[2], mem[3], mem[4], mem[5]);
115e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn}
116e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn
117e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectint main(int argc, char *argv[]) {
118e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    pm_kernel_t *ker;
119e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    pm_process_t *proc;
120e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    pid_t *pids;
12116abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root    struct proc_info **procs;
122e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    size_t num_procs;
123e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn    unsigned long total_pss;
124e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn    unsigned long total_uss;
12516abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root    char cmdline[256]; // this must be within the range of int
126e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int error;
127e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
128e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    #define WS_OFF   0
129e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    #define WS_ONLY  1
130e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    #define WS_RESET 2
131e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    int ws;
132e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
13316abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root    int arg;
13416abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root    size_t i, j;
135e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
136e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    compfn = &sort_by_pss;
137e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    order = -1;
138e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    ws = WS_OFF;
139e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
14016abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root    for (arg = 1; arg < argc; arg++) {
14116abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root        if (!strcmp(argv[arg], "-v")) { compfn = &sort_by_vss; continue; }
14216abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root        if (!strcmp(argv[arg], "-r")) { compfn = &sort_by_rss; continue; }
14316abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root        if (!strcmp(argv[arg], "-p")) { compfn = &sort_by_pss; continue; }
14416abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root        if (!strcmp(argv[arg], "-u")) { compfn = &sort_by_uss; continue; }
14516abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root        if (!strcmp(argv[arg], "-w")) { ws = WS_ONLY; continue; }
14616abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root        if (!strcmp(argv[arg], "-W")) { ws = WS_RESET; continue; }
14716abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root        if (!strcmp(argv[arg], "-R")) { order *= -1; continue; }
14816abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root        if (!strcmp(argv[arg], "-h")) { usage(argv[0]); exit(0); }
14916abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root        fprintf(stderr, "Invalid argument \"%s\".\n", argv[arg]);
150e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        usage(argv[0]);
151e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        exit(EXIT_FAILURE);
152e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
153e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
154e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    error = pm_kernel_create(&ker);
155e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (error) {
156e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        fprintf(stderr, "Error creating kernel interface -- "
157e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                        "does this kernel have pagemap?\n");
158e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        exit(EXIT_FAILURE);
159e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
160e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
161e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    error = pm_kernel_pids(ker, &pids, &num_procs);
162e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (error) {
163e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        fprintf(stderr, "Error listing processes.\n");
164e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        exit(EXIT_FAILURE);
165e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
166e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
16716abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root    procs = calloc(num_procs, sizeof(struct proc_info*));
16816abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root    if (procs == NULL) {
16916abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root        fprintf(stderr, "calloc: %s", strerror(errno));
17016abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root        exit(EXIT_FAILURE);
17116abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root    }
17216abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root
173e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    for (i = 0; i < num_procs; i++) {
174e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        procs[i] = malloc(sizeof(struct proc_info));
17516abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root        if (procs[i] == NULL) {
176e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            fprintf(stderr, "malloc: %s\n", strerror(errno));
177e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            exit(EXIT_FAILURE);
178e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        }
179e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        procs[i]->pid = pids[i];
180eff788820689e7c2bfd456934e8132a381b31235Colin Cross        pm_memusage_zero(&procs[i]->usage);
181e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        error = pm_process_create(ker, pids[i], &proc);
182eff788820689e7c2bfd456934e8132a381b31235Colin Cross        if (error) {
183e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            fprintf(stderr, "warning: could not create process interface for %d\n", pids[i]);
184eff788820689e7c2bfd456934e8132a381b31235Colin Cross            continue;
185eff788820689e7c2bfd456934e8132a381b31235Colin Cross        }
186eff788820689e7c2bfd456934e8132a381b31235Colin Cross
187eff788820689e7c2bfd456934e8132a381b31235Colin Cross        switch (ws) {
188eff788820689e7c2bfd456934e8132a381b31235Colin Cross        case WS_OFF:
189eff788820689e7c2bfd456934e8132a381b31235Colin Cross            error = pm_process_usage(proc, &procs[i]->usage);
190eff788820689e7c2bfd456934e8132a381b31235Colin Cross            break;
191eff788820689e7c2bfd456934e8132a381b31235Colin Cross        case WS_ONLY:
192eff788820689e7c2bfd456934e8132a381b31235Colin Cross            error = pm_process_workingset(proc, &procs[i]->usage, 0);
193eff788820689e7c2bfd456934e8132a381b31235Colin Cross            break;
194eff788820689e7c2bfd456934e8132a381b31235Colin Cross        case WS_RESET:
195eff788820689e7c2bfd456934e8132a381b31235Colin Cross            error = pm_process_workingset(proc, NULL, 1);
196eff788820689e7c2bfd456934e8132a381b31235Colin Cross            break;
197e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        }
198eff788820689e7c2bfd456934e8132a381b31235Colin Cross
199eff788820689e7c2bfd456934e8132a381b31235Colin Cross        if (error) {
200eff788820689e7c2bfd456934e8132a381b31235Colin Cross            fprintf(stderr, "warning: could not read usage for %d\n", pids[i]);
201eff788820689e7c2bfd456934e8132a381b31235Colin Cross        }
202eff788820689e7c2bfd456934e8132a381b31235Colin Cross
203eff788820689e7c2bfd456934e8132a381b31235Colin Cross        pm_process_destroy(proc);
204e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
205e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
206e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    free(pids);
207e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
208e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (ws == WS_RESET) exit(0);
209e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
210e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    j = 0;
211e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    for (i = 0; i < num_procs; i++) {
21216abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root        if (procs[i]->usage.vss) {
213e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            procs[j++] = procs[i];
21416abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root        } else {
21516abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root            free(procs[i]);
21616abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root        }
217e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
218e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    num_procs = j;
219e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
220e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    qsort(procs, num_procs, sizeof(procs[0]), compfn);
221e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
222e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (ws)
223e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        printf("%5s  %7s  %7s  %7s  %s\n", "PID", "WRss", "WPss", "WUss", "cmdline");
224e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    else
225e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        printf("%5s  %7s  %7s  %7s  %7s  %s\n", "PID", "Vss", "Rss", "Pss", "Uss", "cmdline");
22616abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root
227e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn    total_pss = 0;
228e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn    total_uss = 0;
229e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn
230e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    for (i = 0; i < num_procs; i++) {
23116abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root        if (getprocname(procs[i]->pid, cmdline, (int)sizeof(cmdline)) < 0) {
23216abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root            /*
23316abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root             * Something is probably seriously wrong if writing to the stack
23416abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root             * failed.
23516abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root             */
23616abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root            free(procs[i]);
23716abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root            continue;
23816abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root        }
23916abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root
240e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn        total_pss += procs[i]->usage.pss;
241e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn        total_uss += procs[i]->usage.uss;
242e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn
243e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        if (ws)
244e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            printf("%5d  %6dK  %6dK  %6dK  %s\n",
245e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                procs[i]->pid,
246e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                procs[i]->usage.rss / 1024,
247e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                procs[i]->usage.pss / 1024,
248e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                procs[i]->usage.uss / 1024,
249e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                cmdline
250e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            );
251e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        else
252e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            printf("%5d  %6dK  %6dK  %6dK  %6dK  %s\n",
253e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                procs[i]->pid,
254e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                procs[i]->usage.vss / 1024,
255e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                procs[i]->usage.rss / 1024,
256e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                procs[i]->usage.pss / 1024,
257e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                procs[i]->usage.uss / 1024,
258e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                cmdline
259e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            );
26016abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root
26116abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root        free(procs[i]);
262e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
263e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
26416abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root    free(procs);
265e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn
266e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn    if (ws) {
267e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn        printf("%5s  %7s  %7s  %7s  %s\n",
268e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn            "", "", "------", "------", "------");
269e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn        printf("%5s  %7s  %6ldK  %6ldK  %s\n",
270e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn            "", "", total_pss / 1024, total_uss / 1024, "TOTAL");
271e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn    } else {
272e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn        printf("%5s  %7s  %7s  %7s  %7s  %s\n",
273e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn            "", "", "", "------", "------", "------");
274e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn        printf("%5s  %7s  %7s  %6ldK  %6ldK  %s\n",
275e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn            "", "", "", total_pss / 1024, total_uss / 1024, "TOTAL");
276e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn    }
277e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn
278e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn    printf("\n");
279e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn    print_mem_info();
280e9eeec84408d01bf56b9297125a2ebc2638344c8Dianne Hackborn
281e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    return 0;
282e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
283e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
284e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic void usage(char *myname) {
285e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    fprintf(stderr, "Usage: %s [ -W ] [ -v | -r | -p | -u | -h ]\n"
286e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                    "    -v  Sort by VSS.\n"
287e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                    "    -r  Sort by RSS.\n"
288e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                    "    -p  Sort by PSS.\n"
289e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                    "    -u  Sort by USS.\n"
290e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                    "        (Default sort order is PSS.)\n"
291e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                    "    -R  Reverse sort order (default is descending).\n"
292e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                    "    -w  Display statistics for working set only.\n"
293e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                    "    -W  Reset working set of all processes.\n"
294e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project                    "    -h  Display this help screen.\n",
295e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    myname);
296e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
297e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
29816abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root/*
29916abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root * Get the process name for a given PID. Inserts the process name into buffer
30016abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root * buf of length len. The size of the buffer must be greater than zero to get
30116abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root * any useful output.
30216abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root *
30316abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root * Note that fgets(3) only declares length as an int, so our buffer size is
30416abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root * also declared as an int.
30516abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root *
30616abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root * Returns 0 on success, a positive value on partial success, and -1 on
30716abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root * failure. Other interesting values:
30816abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root *   1 on failure to create string to examine proc cmdline entry
30916abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root *   2 on failure to open proc cmdline entry
31016abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root *   3 on failure to read proc cmdline entry
31116abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root */
31216abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Rootstatic int getprocname(pid_t pid, char *buf, int len) {
31316abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root    char *filename;
314e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    FILE *f;
31516abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root    int rc = 0;
31616abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root    static const char* unknown_cmdline = "<unknown>";
31716abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root
31816abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root    if (len <= 0) {
31916abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root        return -1;
32016abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root    }
32116abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root
32216abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root    if (asprintf(&filename, "/proc/%zd/cmdline", pid) < 0) {
32316abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root        rc = 1;
32416abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root        goto exit;
32516abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root    }
326e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
327e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    f = fopen(filename, "r");
32816abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root    if (f == NULL) {
32916abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root        rc = 2;
33016abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root        goto releasefilename;
33116abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root    }
33216abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root
33316abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root    if (fgets(buf, len, f) == NULL) {
33416abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root        rc = 3;
33516abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root        goto closefile;
33616abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root    }
33716abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root
33816abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Rootclosefile:
33916abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root    (void) fclose(f);
34016abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Rootreleasefilename:
34116abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root    free(filename);
34216abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Rootexit:
34316abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root    if (rc != 0) {
34416abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root        /*
34516abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root         * The process went away before we could read its process name. Try
34616abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root         * to give the user "<unknown>" here, but otherwise they get to look
34716abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root         * at a blank.
34816abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root         */
34916abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root        if (strlcpy(buf, unknown_cmdline, (size_t)len) >= (size_t)len) {
35016abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root            rc = 4;
35116abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root        }
35216abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root    }
35316abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root
35416abe7acb8f1dbeb8b9b1dc41061a53dcbfea851Kenny Root    return rc;
355e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
356e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
357e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectstatic int numcmp(long long a, long long b) {
358e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (a < b) return -1;
359e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    if (a > b) return 1;
360e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    return 0;
361e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project}
362e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
363e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project#define create_sort(field, compfn) \
364e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    static int sort_by_ ## field (const void *a, const void *b) { \
365e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        return order * compfn( \
366e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            (*((struct proc_info**)a))->usage.field, \
367e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project            (*((struct proc_info**)b))->usage.field \
368e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project        ); \
369e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project    }
370e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Project
371e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectcreate_sort(vss, numcmp)
372e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectcreate_sort(rss, numcmp)
373e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectcreate_sort(pss, numcmp)
374e16cb84e2324f05334d18dcf5956f20f44262b62The Android Open Source Projectcreate_sort(uss, numcmp)
375