]> git.itanic.dy.fi Git - scan-pagemap/commitdiff
Add support for parsing all threads, not just thead parents
authorTimo Kokkonen <kaapeli@itanic.dy.fi>
Mon, 19 Jul 2010 11:51:39 +0000 (14:51 +0300)
committerTimo Kokkonen <kaapeli@itanic.dy.fi>
Mon, 19 Jul 2010 11:51:39 +0000 (14:51 +0300)
Some threads may have different memory address space than their
parents. Therefore it makes sense to allow scanning all threads
separately.

Signed-off-by: Timo Kokkonen <kaapeli@itanic.dy.fi>
analyze.c
pagemap.h
parse.c

index 7dc2859772bf11a1397dc0d93f7c8274b5d83993..a56f94d60f9c30c3dca72ab95eae03361f6984ce 100644 (file)
--- a/analyze.c
+++ b/analyze.c
@@ -114,7 +114,7 @@ void print_pid_stats(struct pageframe *pf, struct process *process_list)
                biggest = MAX(biggest, ps->pages_present + ps->pages_swapped);
        }
 
-       printf("   in ram   swapped   pid name\n");
+       printf("   in ram   swapped   pid   tid name\n");
 
 restart:
        second_biggest = 0;
@@ -135,10 +135,10 @@ restart:
                if (total == 0)
                        continue;
 
-               printf("%6lld %sB %6lld %sB %5d %s\n",
+               printf("%6lld %sB %6lld %sB %5d %5d %s\n",
                        PAGE_TO_NICE(present), PAGE_TO_NICE_UNIT(present),
                        PAGE_TO_NICE(swapped), PAGE_TO_NICE_UNIT(swapped),
-                       ps->pid, ps->name);
+                       ps->pid, ps->tid,ps->name);
                count++;
                processes++;
        }
index 414f4fecd55ad27f36b54d66f58a622eb11e9f6c..3de6650ac4335b5ddfe12e897bd23e8f1bbe1574 100644 (file)
--- a/pagemap.h
+++ b/pagemap.h
@@ -44,6 +44,7 @@ struct maps {
        /* Name of the mapping, such as library name or something else */
        char name[128];
        int pid; /* Process which address space the mapping belongs to */
+       int tid; /* thread id */
 };
 
 #define list_to_maps(list_head)                                \
@@ -53,6 +54,7 @@ struct process {
        struct maps *maps;
        struct list_head list;
        int pid;
+       int tid;
        char name[256];
 
        long int pages_present;
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);
        }
 }