From 14b657197b1da63dee21f45762c78d6121f418f4 Mon Sep 17 00:00:00 2001 From: Timo Kokkonen Date: Mon, 19 Jul 2010 14:51:39 +0300 Subject: [PATCH] Add support for parsing all threads, not just thead parents 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 --- analyze.c | 6 ++-- pagemap.h | 2 ++ parse.c | 94 +++++++++++++++++++++++++++++++++++++++++-------------- 3 files changed, 76 insertions(+), 26 deletions(-) diff --git a/analyze.c b/analyze.c index 7dc2859..a56f94d 100644 --- 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++; } diff --git a/pagemap.h b/pagemap.h index 414f4fe..3de6650 100644 --- 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 8895173..dfbcba6 100644 --- 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); } } -- 2.44.0