1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <stdio.h> 18 #include <stdlib.h> 19 #include <string.h> 20 #include <sys/types.h> 21 22 #include <memtrack/memtrack.h> 23 24 #include <pagemap/pagemap.h> 25 26 #define DIV_ROUND_UP(x,y) (((x) + (y) - 1) / (y)) 27 28 static int getprocname(pid_t pid, char *buf, int len) { 29 char *filename; 30 FILE *f; 31 int rc = 0; 32 static const char* unknown_cmdline = "<unknown>"; 33 34 if (len <= 0) { 35 return -1; 36 } 37 38 if (asprintf(&filename, "/proc/%zd/cmdline", pid) < 0) { 39 rc = 1; 40 goto exit; 41 } 42 43 f = fopen(filename, "r"); 44 if (f == NULL) { 45 rc = 2; 46 goto releasefilename; 47 } 48 49 if (fgets(buf, len, f) == NULL) { 50 rc = 3; 51 goto closefile; 52 } 53 54 closefile: 55 (void) fclose(f); 56 releasefilename: 57 free(filename); 58 exit: 59 if (rc != 0) { 60 /* 61 * The process went away before we could read its process name. Try 62 * to give the user "<unknown>" here, but otherwise they get to look 63 * at a blank. 64 */ 65 if (strlcpy(buf, unknown_cmdline, (size_t)len) >= (size_t)len) { 66 rc = 4; 67 } 68 } 69 70 return rc; 71 } 72 73 int main(int argc, char *argv[]) 74 { 75 int ret; 76 pm_kernel_t *ker; 77 size_t num_procs; 78 pid_t *pids; 79 struct memtrack_proc *p; 80 size_t i; 81 82 (void)argc; 83 (void)argv; 84 85 ret = memtrack_init(); 86 if (ret < 0) { 87 fprintf(stderr, "failed to initialize HAL: %s (%d)\n", strerror(-ret), ret); 88 exit(EXIT_FAILURE); 89 } 90 91 ret = pm_kernel_create(&ker); 92 if (ret) { 93 fprintf(stderr, "Error creating kernel interface -- " 94 "does this kernel have pagemap?\n"); 95 exit(EXIT_FAILURE); 96 } 97 98 ret = pm_kernel_pids(ker, &pids, &num_procs); 99 if (ret) { 100 fprintf(stderr, "Error listing processes.\n"); 101 exit(EXIT_FAILURE); 102 } 103 104 p = memtrack_proc_new(); 105 if (ret) { 106 fprintf(stderr, "failed to create memtrack process handle\n"); 107 exit(EXIT_FAILURE); 108 } 109 110 for (i = 0; i < num_procs; i++) { 111 pid_t pid = pids[i]; 112 char cmdline[256]; 113 size_t v1; 114 size_t v2; 115 size_t v3; 116 size_t v4; 117 size_t v5; 118 size_t v6; 119 120 getprocname(pid, cmdline, (int)sizeof(cmdline)); 121 122 ret = memtrack_proc_get(p, pid); 123 if (ret) { 124 fprintf(stderr, "failed to get memory info for pid %d: %s (%d)\n", 125 pid, strerror(-ret), ret); 126 continue; 127 } 128 129 v1 = DIV_ROUND_UP(memtrack_proc_graphics_total(p), 1024); 130 v2 = DIV_ROUND_UP(memtrack_proc_graphics_pss(p), 1024); 131 v3 = DIV_ROUND_UP(memtrack_proc_gl_total(p), 1024); 132 v4 = DIV_ROUND_UP(memtrack_proc_gl_pss(p), 1024); 133 v5 = DIV_ROUND_UP(memtrack_proc_other_total(p), 1024); 134 v6 = DIV_ROUND_UP(memtrack_proc_other_pss(p), 1024); 135 136 if (v1 | v2 | v3 | v4 | v5 | v6) { 137 printf("%5d %6zu %6zu %6zu %6zu %6zu %6zu %s\n", pid, 138 v1, v2, v3, v4, v5, v6, cmdline); 139 } 140 } 141 142 memtrack_proc_destroy(p); 143 144 return 0; 145 } 146