]> git.itanic.dy.fi Git - scan-pagemap/blobdiff - parse.c
Add support for parsing all threads, not just thead parents
[scan-pagemap] / parse.c
diff --git a/parse.c b/parse.c
index 8895173a2e9f511018dd8b478d55030f6e33205b..dfbcba6e8f60276d1f52dce26509d2ac4628cf63 100644 (file)
--- a/parse.c
+++ b/parse.c
@@ -36,7 +36,7 @@ err:
        return map;
 }
 
-static struct maps *parse_maps(FILE *file, int pid)
+static struct maps *parse_maps(FILE *file, int pid, int tid)
 {
        struct maps *the_map = NULL;
        char line[1024];
@@ -65,6 +65,7 @@ static struct maps *parse_maps(FILE *file, int pid)
                map->end = end;
                map->size = end - start;
                map->pid = pid;
+               map->tid = tid;
 
                if (ret >= 3)
                        strncpy(map->name, name, sizeof(map->name));
@@ -233,7 +234,7 @@ static int parse_pageframe(FILE *file, struct pageframe *pf_tree,
        return 0;
 }
 
-void read_pageframe(int pid, struct pageframe *pageframe,
+void read_pageframe(int pid, int tid, struct pageframe *pageframe,
                struct process **process_list, struct parse_opts *opts)
 {
        struct maps *maps;
@@ -250,20 +251,21 @@ void read_pageframe(int pid, struct pageframe *pageframe,
                *process_list = process;
 
        process->pid = pid;
+       process->tid = tid;
 
        list_add_tail(&process->list, &(*process_list)->list);
 
-       snprintf(path, sizeof(path), "/proc/%d/maps", pid);
+       snprintf(path, sizeof(path), "/proc/%d/task/%d/maps", pid, tid);
        file = fopen(path, "rb");
 
        if (!file)
                return;
 
-       maps = parse_maps(file, pid);
+       maps = parse_maps(file, pid, tid);
        fclose(file);
        process->maps = maps;
 
-       snprintf(path, sizeof(path), "/proc/%d/pagemap", pid);
+       snprintf(path, sizeof(path), "/proc/%d/task/%d/pagemap", pid, tid);
        file = fopen(path, "rb");
 
        if (!file)
@@ -272,7 +274,7 @@ void read_pageframe(int pid, struct pageframe *pageframe,
        parse_pageframe(file, pageframe, maps, opts);
        fclose(file);
 
-       snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
+       snprintf(path, sizeof(path), "/proc/%d/task/%d/cmdline", pid, tid);
        file = fopen(path, "rb");
 
        if (!file)
@@ -294,28 +296,17 @@ void read_pageframe(int pid, struct pageframe *pageframe,
        return;
 }
 
-static int get_next_pid(void)
+static int parse_pid(DIR **dir)
 {
-       static DIR *dir = NULL;
        struct dirent *dirent;
        int error;
 
-       if (!dir) {
-               dir = opendir("/proc");
-               if (!dir) {
-                       error = errno;
-                       printf("Failed to open /proc directory: %s\n",
-                               strerror(error));
-                       return -1;
-               }
-       }
-
 restart:
-       dirent = readdir(dir);
+       dirent = readdir(*dir);
        if (!dirent) {
                if (errno == 0) {
-                       closedir(dir);
-                       dir = NULL;
+                       closedir(*dir);
+                       *dir = NULL;
                        return 0;
                }
                error = errno;
@@ -329,18 +320,75 @@ restart:
        return atoi(dirent->d_name);
 }
 
+static int get_next_tid(int pid, DIR **dir)
+{
+       int error;
+
+       if (*dir == NULL) {
+               char path[64];
+
+               snprintf(path, sizeof(path), "/proc/%d/task/", pid);
+               *dir = opendir(path);
+               if (!*dir) {
+                       error = errno;
+                       printf("Failed to open %s directory: %s\n",
+                               path,
+                               strerror(error));
+                       return -1;
+               }
+       }
+
+       return parse_pid(dir);
+}
+
+static int get_next_pid(void)
+{
+       static DIR *dir = NULL;
+       int error;
+
+       if (!dir) {
+               dir = opendir("/proc");
+               if (!dir) {
+                       error = errno;
+                       printf("Failed to open /proc directory: %s\n",
+                               strerror(error));
+                       return -1;
+               }
+       }
+
+       return parse_pid(&dir);
+}
+
+static void read_pageframe_with_threads(int pid,
+                                       struct pageframe *pageframe,
+                                       struct process **process_list,
+                                       struct parse_opts *opts)
+{
+       DIR *dir = NULL;
+       int tid;
+
+       while (1) {
+               tid = get_next_tid(pid, &dir);
+
+               if (tid <= 0)
+                       return;
+
+               read_pageframe(pid, pid, pageframe, process_list, opts);
+       }
+}
+
 void scan_all_pids(struct pageframe *pf, struct process **process_list,
                struct parse_opts *opts)
 {
        int pid;
 
        if (opts->parse_mask & PARSE_PID)
-               read_pageframe(opts->pid, pf, process_list, opts);
+               read_pageframe_with_threads(opts->pid, pf, process_list, opts);
 
        while(1) {
                pid = get_next_pid();
                if (pid <= 0)
                        break;
-               read_pageframe(pid, pf, process_list, opts);
+               read_pageframe_with_threads(pid, pf, process_list, opts);
        }
 }