dumpstate: dump all threads in show_wchan

for_each_pid only finds processes and not their threads.  Add
for_each_tid and call it for show_wchan so we can see where all
threads are blocked in the kernel.

Change-Id: Iffb59f7c2933cecf51cdd358a36e19932c2f24c7
This commit is contained in:
Colin Cross 2012-11-02 15:46:56 -07:00
parent 7e25127388
commit 0c22e8b316
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);
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");
run_command("SYSTEM LOG", 20, "logcat", "-v", "threadtime", "-d", "*:v", NULL);

View File

@ -19,10 +19,14 @@
#include <time.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdio.h>
#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 */
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();
/* 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 */
void show_wchan(int pid, const char *name);
void show_wchan(int pid, int tid, const char *name);
/* Runs "showmap" for a process */
void do_showmap(int pid, const char *name);

View File

@ -48,7 +48,7 @@ static const char* native_processes_to_dump[] = {
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;
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) {
strcpy(cmdline, "N/A");
} else {
read(fd, cmdline, sizeof(cmdline));
read(fd, cmdline, sizeof(cmdline) - 1);
close(fd);
}
func(pid, cmdline);
helper(pid, cmdline, arg);
}
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 buffer[255];
int fd;
char name_buffer[255];
memset(buffer, 0, sizeof(buffer));
sprintf(path, "/proc/%d/wchan", pid);
sprintf(path, "/proc/%d/wchan", tid);
if ((fd = open(path, O_RDONLY)) < 0) {
printf("Failed to open '%s' (%s)\n", path, strerror(errno));
return;
@ -100,7 +162,10 @@ void show_wchan(int pid, const char *name) {
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:
close(fd);