Merge "dumpstate: dump all threads in show_wchan"

This commit is contained in:
Colin Cross 2012-11-03 10:18:47 -07:00 committed by Android (Google) Code Review
commit 5f7e348746
3 changed files with 81 additions and 9 deletions

View File

@ -102,7 +102,7 @@ static void dumpstate() {
run_command("LIST OF OPEN FILES", 10, SU_PATH, "root", "lsof", NULL); run_command("LIST OF OPEN FILES", 10, SU_PATH, "root", "lsof", NULL);
for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES"); for_each_pid(do_showmap, "SMAPS OF ALL PROCESSES");
for_each_pid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS"); for_each_tid(show_wchan, "BLOCKED PROCESS WAIT-CHANNELS");
// dump_file("EVENT LOG TAGS", "/etc/event-log-tags"); // dump_file("EVENT LOG TAGS", "/etc/event-log-tags");
run_command("SYSTEM LOG", 20, "logcat", "-v", "threadtime", "-d", "*:v", NULL); run_command("SYSTEM LOG", 20, "logcat", "-v", "threadtime", "-d", "*:v", NULL);

View File

@ -19,10 +19,14 @@
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#define SU_PATH "/system/xbin/su" #define SU_PATH "/system/xbin/su"
typedef void (for_each_pid_func)(int, const char *);
typedef void (for_each_tid_func)(int, int, const char *);
/* prints the contents of a file */ /* prints the contents of a file */
int dump_file(const char *title, const char* path); int dump_file(const char *title, const char* path);
@ -42,10 +46,13 @@ pid_t redirect_to_file(FILE *redirect, char *path, int gzip_level);
const char *dump_traces(); const char *dump_traces();
/* for each process in the system, run the specified function */ /* for each process in the system, run the specified function */
void for_each_pid(void (*func)(int, const char *), const char *header); void for_each_pid(for_each_pid_func func, const char *header);
/* for each thread in the system, run the specified function */
void for_each_tid(for_each_tid_func func, const char *header);
/* Displays a blocked processes in-kernel wait channel */ /* Displays a blocked processes in-kernel wait channel */
void show_wchan(int pid, const char *name); void show_wchan(int pid, int tid, const char *name);
/* Runs "showmap" for a process */ /* Runs "showmap" for a process */
void do_showmap(int pid, const char *name); void do_showmap(int pid, const char *name);

View File

@ -48,7 +48,7 @@ static const char* native_processes_to_dump[] = {
NULL, NULL,
}; };
void for_each_pid(void (*func)(int, const char *), const char *header) { static void __for_each_pid(void (*helper)(int, const char *, void *), const char *header, void *arg) {
DIR *d; DIR *d;
struct dirent *de; struct dirent *de;
@ -73,23 +73,85 @@ void for_each_pid(void (*func)(int, const char *), const char *header) {
if ((fd = open(cmdpath, O_RDONLY)) < 0) { if ((fd = open(cmdpath, O_RDONLY)) < 0) {
strcpy(cmdline, "N/A"); strcpy(cmdline, "N/A");
} else { } else {
read(fd, cmdline, sizeof(cmdline)); read(fd, cmdline, sizeof(cmdline) - 1);
close(fd); close(fd);
} }
func(pid, cmdline); helper(pid, cmdline, arg);
} }
closedir(d); closedir(d);
} }
void show_wchan(int pid, const char *name) { static void for_each_pid_helper(int pid, const char *cmdline, void *arg) {
for_each_pid_func *func = arg;
func(pid, cmdline);
}
void for_each_pid(for_each_pid_func func, const char *header) {
__for_each_pid(for_each_pid_helper, header, func);
}
static void for_each_tid_helper(int pid, const char *cmdline, void *arg) {
DIR *d;
struct dirent *de;
char taskpath[255];
for_each_tid_func *func = arg;
sprintf(taskpath, "/proc/%d/task", pid);
if (!(d = opendir(taskpath))) {
printf("Failed to open %s (%s)\n", taskpath, strerror(errno));
return;
}
func(pid, pid, cmdline);
while ((de = readdir(d))) {
int tid;
int fd;
char commpath[255];
char comm[255];
if (!(tid = atoi(de->d_name))) {
continue;
}
if (tid == pid)
continue;
sprintf(commpath,"/proc/%d/comm", tid);
memset(comm, 0, sizeof(cmdline));
if ((fd = open(commpath, O_RDONLY)) < 0) {
strcpy(comm, "N/A");
} else {
char *c;
read(fd, comm, sizeof(comm) - 1);
close(fd);
c = strrchr(comm, '\n');
if (c) {
*c = '\0';
}
}
func(pid, tid, comm);
}
closedir(d);
}
void for_each_tid(for_each_tid_func func, const char *header) {
__for_each_pid(for_each_tid_helper, header, func);
}
void show_wchan(int pid, int tid, const char *name) {
char path[255]; char path[255];
char buffer[255]; char buffer[255];
int fd; int fd;
char name_buffer[255];
memset(buffer, 0, sizeof(buffer)); memset(buffer, 0, sizeof(buffer));
sprintf(path, "/proc/%d/wchan", pid); sprintf(path, "/proc/%d/wchan", tid);
if ((fd = open(path, O_RDONLY)) < 0) { if ((fd = open(path, O_RDONLY)) < 0) {
printf("Failed to open '%s' (%s)\n", path, strerror(errno)); printf("Failed to open '%s' (%s)\n", path, strerror(errno));
return; return;
@ -100,7 +162,10 @@ void show_wchan(int pid, const char *name) {
goto out_close; goto out_close;
} }
printf("%-7d %-32s %s\n", pid, name, buffer); snprintf(name_buffer, sizeof(name_buffer), "%*s%s",
pid == tid ? 0 : 3, "", name);
printf("%-7d %-32s %s\n", tid, name_buffer, buffer);
out_close: out_close:
close(fd); close(fd);