blob: bc50cfa971e9f4021b2468789dea4c6b3fb72681 [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001#include <stdio.h>
2#include <stdlib.h>
3#include <ctype.h>
4#include <fcntl.h>
5
6#include <string.h>
7
8#include <sys/stat.h>
9#include <sys/types.h>
10#include <dirent.h>
11
12#include <pwd.h>
13
San Mehat39274412009-10-27 11:53:22 -070014#include <cutils/sched_policy.h>
15
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080016
17static char *nexttoksep(char **strp, char *sep)
18{
19 char *p = strsep(strp,sep);
20 return (p == 0) ? "" : p;
21}
22static char *nexttok(char **strp)
23{
24 return nexttoksep(strp, " ");
25}
26
27#define SHOW_PRIO 1
28#define SHOW_TIME 2
San Mehat39274412009-10-27 11:53:22 -070029#define SHOW_POLICY 4
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -080030
31static int display_flags = 0;
32
33static int ps_line(int pid, int tid, char *namefilter)
34{
35 char statline[1024];
36 char cmdline[1024];
37 char user[32];
38 struct stat stats;
39 int fd, r;
40 char *ptr, *name, *state;
41 int ppid, tty;
42 unsigned wchan, rss, vss, eip;
43 unsigned utime, stime;
44 int prio, nice, rtprio, sched;
45 struct passwd *pw;
46
47 sprintf(statline, "/proc/%d", pid);
48 stat(statline, &stats);
49
50 if(tid) {
51 sprintf(statline, "/proc/%d/task/%d/stat", pid, tid);
52 cmdline[0] = 0;
53 } else {
54 sprintf(statline, "/proc/%d/stat", pid);
55 sprintf(cmdline, "/proc/%d/cmdline", pid);
56 fd = open(cmdline, O_RDONLY);
57 if(fd == 0) {
58 r = 0;
59 } else {
60 r = read(fd, cmdline, 1023);
61 close(fd);
62 if(r < 0) r = 0;
63 }
64 cmdline[r] = 0;
65 }
66
67 fd = open(statline, O_RDONLY);
68 if(fd == 0) return -1;
69 r = read(fd, statline, 1023);
70 close(fd);
71 if(r < 0) return -1;
72 statline[r] = 0;
73
74 ptr = statline;
75 nexttok(&ptr); // skip pid
76 ptr++; // skip "("
77
78 name = ptr;
79 ptr = strrchr(ptr, ')'); // Skip to *last* occurence of ')',
80 *ptr++ = '\0'; // and null-terminate name.
81
82 ptr++; // skip " "
83 state = nexttok(&ptr);
84 ppid = atoi(nexttok(&ptr));
85 nexttok(&ptr); // pgrp
86 nexttok(&ptr); // sid
87 tty = atoi(nexttok(&ptr));
88
89 nexttok(&ptr); // tpgid
90 nexttok(&ptr); // flags
91 nexttok(&ptr); // minflt
92 nexttok(&ptr); // cminflt
93 nexttok(&ptr); // majflt
94 nexttok(&ptr); // cmajflt
95#if 1
96 utime = atoi(nexttok(&ptr));
97 stime = atoi(nexttok(&ptr));
98#else
99 nexttok(&ptr); // utime
100 nexttok(&ptr); // stime
101#endif
102 nexttok(&ptr); // cutime
103 nexttok(&ptr); // cstime
104 prio = atoi(nexttok(&ptr));
105 nice = atoi(nexttok(&ptr));
106 nexttok(&ptr); // threads
107 nexttok(&ptr); // itrealvalue
108 nexttok(&ptr); // starttime
109 vss = strtoul(nexttok(&ptr), 0, 10); // vsize
110 rss = strtoul(nexttok(&ptr), 0, 10); // rss
111 nexttok(&ptr); // rlim
112 nexttok(&ptr); // startcode
113 nexttok(&ptr); // endcode
114 nexttok(&ptr); // startstack
115 nexttok(&ptr); // kstkesp
116 eip = strtoul(nexttok(&ptr), 0, 10); // kstkeip
117 nexttok(&ptr); // signal
118 nexttok(&ptr); // blocked
119 nexttok(&ptr); // sigignore
120 nexttok(&ptr); // sigcatch
121 wchan = strtoul(nexttok(&ptr), 0, 10); // wchan
122 nexttok(&ptr); // nswap
123 nexttok(&ptr); // cnswap
124 nexttok(&ptr); // exit signal
125 nexttok(&ptr); // processor
126 rtprio = atoi(nexttok(&ptr)); // rt_priority
127 sched = atoi(nexttok(&ptr)); // scheduling policy
128
129 tty = atoi(nexttok(&ptr));
130
131 if(tid != 0) {
132 ppid = pid;
133 pid = tid;
134 }
135
136 pw = getpwuid(stats.st_uid);
137 if(pw == 0) {
138 sprintf(user,"%d",(int)stats.st_uid);
139 } else {
140 strcpy(user,pw->pw_name);
141 }
142
143 if(!namefilter || !strncmp(name, namefilter, strlen(namefilter))) {
San Mehat39274412009-10-27 11:53:22 -0700144 printf("%-9s %-5d %-5d %-6d %-5d", user, pid, ppid, vss / 1024, rss * 4);
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800145 if(display_flags&SHOW_PRIO)
146 printf(" %-5d %-5d %-5d %-5d", prio, nice, rtprio, sched);
San Mehat39274412009-10-27 11:53:22 -0700147 if (display_flags & SHOW_POLICY) {
148 SchedPolicy p;
149 if (get_sched_policy(pid, &p) < 0)
150 printf(" un ");
151 else {
152 if (p == SP_BACKGROUND)
153 printf(" bg ");
154 else if (p == SP_FOREGROUND)
155 printf(" fg ");
156 else
157 printf(" er ");
158 }
159 }
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800160 printf(" %08x %08x %s %s", wchan, eip, state, cmdline[0] ? cmdline : name);
161 if(display_flags&SHOW_TIME)
162 printf(" (u:%d, s:%d)", utime, stime);
San Mehat39274412009-10-27 11:53:22 -0700163
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800164 printf("\n");
165 }
166 return 0;
167}
168
169
170void ps_threads(int pid, char *namefilter)
171{
172 char tmp[128];
173 DIR *d;
174 struct dirent *de;
175
176 sprintf(tmp,"/proc/%d/task",pid);
177 d = opendir(tmp);
178 if(d == 0) return;
179
180 while((de = readdir(d)) != 0){
181 if(isdigit(de->d_name[0])){
182 int tid = atoi(de->d_name);
183 if(tid == pid) continue;
184 ps_line(pid, tid, namefilter);
185 }
186 }
187 closedir(d);
188}
189
190int ps_main(int argc, char **argv)
191{
192 DIR *d;
193 struct dirent *de;
194 char *namefilter = 0;
195 int pidfilter = 0;
196 int threads = 0;
197
198 d = opendir("/proc");
199 if(d == 0) return -1;
200
201 while(argc > 1){
202 if(!strcmp(argv[1],"-t")) {
203 threads = 1;
204 } else if(!strcmp(argv[1],"-x")) {
205 display_flags |= SHOW_TIME;
San Mehat39274412009-10-27 11:53:22 -0700206 } else if(!strcmp(argv[1],"-P")) {
207 display_flags |= SHOW_POLICY;
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800208 } else if(!strcmp(argv[1],"-p")) {
209 display_flags |= SHOW_PRIO;
210 } else if(isdigit(argv[1][0])){
211 pidfilter = atoi(argv[1]);
212 } else {
213 namefilter = argv[1];
214 }
215 argc--;
216 argv++;
217 }
218
San Mehat39274412009-10-27 11:53:22 -0700219 printf("USER PID PPID VSIZE RSS %s %s WCHAN PC NAME\n",
220 (display_flags&SHOW_PRIO)?"PRIO NICE RTPRI SCHED ":"",
221 (display_flags&SHOW_POLICY)?"PCY " : "");
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -0800222 while((de = readdir(d)) != 0){
223 if(isdigit(de->d_name[0])){
224 int pid = atoi(de->d_name);
225 if(!pidfilter || (pidfilter == pid)) {
226 ps_line(pid, 0, namefilter);
227 if(threads) ps_threads(pid, namefilter);
228 }
229 }
230 }
231 closedir(d);
232 return 0;
233}
234