summaryrefslogtreecommitdiff
path: root/procrank
diff options
context:
space:
mode:
authorColin Cross <ccross@android.com>2016-05-23 16:50:59 -0700
committerColin Cross <ccross@android.com>2016-05-24 12:29:28 -0700
commitbaa84a2d783c3555c9df58ba3493e4d3d392b080 (patch)
tree8583a5f70941dfce1c1028f461aedafbb681106d /procrank
parentb5769be9cd537023d632e622d879d17c277b2f1a (diff)
downloadextras-baa84a2d783c3555c9df58ba3493e4d3d392b080.tar.gz
C++-ify procrank
Change-Id: I1b006d2af04f21c0c02ac2d7629340d91b876886
Diffstat (limited to 'procrank')
-rw-r--r--procrank/Android.mk4
-rw-r--r--procrank/procrank.cpp (renamed from procrank/procrank.c)207
2 files changed, 73 insertions, 138 deletions
diff --git a/procrank/Android.mk b/procrank/Android.mk
index f1eb3b6c..8a235fda 100644
--- a/procrank/Android.mk
+++ b/procrank/Android.mk
@@ -15,9 +15,9 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_SRC_FILES := procrank.c
+LOCAL_SRC_FILES := procrank.cpp
LOCAL_CFLAGS := -Wall -Wextra -Wformat=2 -Werror
-LOCAL_SHARED_LIBRARIES := libpagemap
+LOCAL_SHARED_LIBRARIES := libpagemap libbase
LOCAL_MODULE := procrank
LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
LOCAL_MODULE_TAGS := debug
diff --git a/procrank/procrank.c b/procrank/procrank.cpp
index 881f1108..6f9803fd 100644
--- a/procrank/procrank.c
+++ b/procrank/procrank.cpp
@@ -1,18 +1,18 @@
-/*
- * 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.
- */
+//
+// 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 <dirent.h>
#include <errno.h>
@@ -24,6 +24,10 @@
#include <sys/types.h>
#include <unistd.h>
+#include <vector>
+
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
#include <pagemap/pagemap.h>
struct proc_info {
@@ -33,7 +37,7 @@ struct proc_info {
};
static void usage(char *myname);
-static int getprocname(pid_t pid, char *buf, int len);
+static std::string getprocname(pid_t pid);
static int numcmp(uint64_t a, uint64_t b);
#define declare_sort(field) \
@@ -94,7 +98,7 @@ void get_mem_info(uint64_t mem[]) {
"Slab:",
"SwapTotal:",
"SwapFree:",
- "ZRam:", /* not read from meminfo but from /sys/block/zram0 */
+ "ZRam:", // not read from meminfo but from /sys/block/zram0
"Mapped:",
"VmallocUsed:",
"PageTables:",
@@ -148,7 +152,6 @@ int main(int argc, char *argv[]) {
pm_kernel_t *ker;
pm_process_t *proc;
pid_t *pids;
- struct proc_info **procs;
size_t num_procs;
uint64_t total_pss;
uint64_t total_uss;
@@ -156,19 +159,19 @@ int main(int argc, char *argv[]) {
uint64_t total_pswap;
uint64_t total_uswap;
uint64_t total_zswap;
- char cmdline[256]; // this must be within the range of int
int error;
bool has_swap = false, has_zram = false;
uint64_t required_flags = 0;
uint64_t flags_mask = 0;
- #define WS_OFF 0
- #define WS_ONLY 1
- #define WS_RESET 2
- int ws;
-
int arg;
- size_t i, j;
+ size_t i;
+
+ enum {
+ WS_OFF,
+ WS_ONLY,
+ WS_RESET,
+ } ws;
uint64_t mem[MEMINFO_COUNT] = { };
pm_proportional_swap_t *p_swap;
@@ -215,21 +218,11 @@ int main(int argc, char *argv[]) {
exit(EXIT_FAILURE);
}
- procs = calloc(num_procs, sizeof(struct proc_info*));
- if (procs == NULL) {
- fprintf(stderr, "calloc: %s", strerror(errno));
- exit(EXIT_FAILURE);
- }
-
+ std::vector<proc_info> procs(num_procs);
for (i = 0; i < num_procs; i++) {
- procs[i] = malloc(sizeof(struct proc_info));
- if (procs[i] == NULL) {
- fprintf(stderr, "malloc: %s\n", strerror(errno));
- exit(EXIT_FAILURE);
- }
- procs[i]->pid = pids[i];
- pm_memusage_zero(&procs[i]->usage);
- pm_memusage_pswap_init_handle(&procs[i]->usage, p_swap);
+ procs[i].pid = 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]);
@@ -238,11 +231,11 @@ int main(int argc, char *argv[]) {
switch (ws) {
case WS_OFF:
- error = pm_process_usage_flags(proc, &procs[i]->usage, flags_mask,
+ 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);
+ error = pm_process_workingset(proc, &procs[i].usage, 0);
break;
case WS_RESET:
error = pm_process_workingset(proc, NULL, 1);
@@ -253,7 +246,7 @@ int main(int argc, char *argv[]) {
fprintf(stderr, "warning: could not read usage for %d\n", pids[i]);
}
- if (ws != WS_RESET && procs[i]->usage.swap) {
+ if (ws != WS_RESET && procs[i].usage.swap) {
has_swap = true;
}
@@ -264,17 +257,14 @@ int main(int argc, char *argv[]) {
if (ws == WS_RESET) exit(0);
- j = 0;
- for (i = 0; i < num_procs; i++) {
- if (procs[i]->usage.vss) {
- procs[j++] = procs[i];
- } else {
- free(procs[i]);
- }
- }
- num_procs = j;
+ procs.erase(std::remove_if(procs.begin(),
+ procs.end(),
+ [](auto proc){
+ return proc.usage.vss == 0;
+ }),
+ procs.end());
- qsort(procs, num_procs, sizeof(procs[0]), compfn);
+ qsort(procs.data(), procs.size(), sizeof(procs[0]), compfn);
if (has_swap) {
fd = open("/sys/block/zram0/mem_used_total", O_RDONLY);
@@ -319,47 +309,40 @@ int main(int argc, char *argv[]) {
total_uswap = 0;
total_zswap = 0;
- for (i = 0; i < num_procs; i++) {
- if (getprocname(procs[i]->pid, cmdline, (int)sizeof(cmdline)) < 0) {
- /*
- * Something is probably seriously wrong if writing to the stack
- * failed.
- */
- free(procs[i]);
- continue;
- }
+ for (auto& proc: procs) {
+ std::string cmdline = getprocname(proc.pid);
- total_pss += procs[i]->usage.pss;
- total_uss += procs[i]->usage.uss;
- total_swap += procs[i]->usage.swap;
+ total_pss += proc.usage.pss;
+ total_uss += proc.usage.uss;
+ total_swap += proc.usage.swap;
- printf("%5d ", procs[i]->pid);
+ printf("%5d ", proc.pid);
if (ws) {
printf("%6zuK %6zuK %6zuK ",
- procs[i]->usage.rss / 1024,
- procs[i]->usage.pss / 1024,
- procs[i]->usage.uss / 1024
+ proc.usage.rss / 1024,
+ proc.usage.pss / 1024,
+ proc.usage.uss / 1024
);
} else {
printf("%7zuK %6zuK %6zuK %6zuK ",
- procs[i]->usage.vss / 1024,
- procs[i]->usage.rss / 1024,
- procs[i]->usage.pss / 1024,
- procs[i]->usage.uss / 1024
+ 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(&procs[i]->usage, &su);
- printf("%6zuK ", procs[i]->usage.swap / 1024);
+ 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(&procs[i]->usage);
+ pm_memusage_pswap_free(&proc.usage);
if (has_zram) {
size_t zpswap = su.proportional * zram_cr;
printf("%6zuK ", zpswap / 1024);
@@ -367,15 +350,12 @@ int main(int argc, char *argv[]) {
}
}
- printf("%s\n", cmdline);
-
- free(procs[i]);
+ printf("%s\n", cmdline.c_str());
}
- free(procs);
pm_memusage_pswap_destroy(p_swap);
- /* Print the separator line */
+ // Print the separator line
printf("%5s ", "");
if (ws) {
@@ -393,7 +373,7 @@ int main(int argc, char *argv[]) {
printf("%s\n", "------");
- /* Print the total line */
+ // Print the total line
printf("%5s ", "");
if (ws) {
printf("%7s %6" PRIu64 "K %6" PRIu64 "K ",
@@ -448,63 +428,18 @@ static void usage(char *myname) {
myname);
}
-/*
- * Get the process name for a given PID. Inserts the process name into buffer
- * buf of length len. The size of the buffer must be greater than zero to get
- * any useful output.
- *
- * Note that fgets(3) only declares length as an int, so our buffer size is
- * also declared as an int.
- *
- * Returns 0 on success, a positive value on partial success, and -1 on
- * failure. Other interesting values:
- * 1 on failure to create string to examine proc cmdline entry
- * 2 on failure to open proc cmdline entry
- * 3 on failure to read proc cmdline entry
- */
-static int getprocname(pid_t pid, char *buf, int len) {
- char *filename;
- FILE *f;
- int rc = 0;
- static const char* unknown_cmdline = "<unknown>";
-
- if (len <= 0) {
- return -1;
- }
+// 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);
- if (asprintf(&filename, "/proc/%d/cmdline", pid) < 0) {
- rc = 1;
- goto exit;
- }
+ std::string procname;
- f = fopen(filename, "r");
- if (f == NULL) {
- rc = 2;
- goto releasefilename;
- }
-
- if (fgets(buf, len, f) == NULL) {
- rc = 3;
- goto closefile;
- }
-
-closefile:
- (void) fclose(f);
-releasefilename:
- free(filename);
-exit:
- if (rc != 0) {
- /*
- * The process went away before we could read its process name. Try
- * to give the user "<unknown>" here, but otherwise they get to look
- * at a blank.
- */
- if (strlcpy(buf, unknown_cmdline, (size_t)len) >= (size_t)len) {
- rc = 4;
- }
+ if (!android::base::ReadFileToString(filename, &procname)) {
+ // The process went away before we could read its process name.
+ procname = "<unknown>";
}
- return rc;
+ return procname;
}
static int numcmp(uint64_t a, uint64_t b) {
@@ -516,8 +451,8 @@ static int numcmp(uint64_t a, uint64_t b) {
#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 \
+ ((struct proc_info*)(a))->usage.field, \
+ ((struct proc_info*)(b))->usage.field \
); \
}