From 9d764e26faa7f60efb88c4d2f365f146453769eb Mon Sep 17 00:00:00 2001 From: Timo Kokkonen Date: Sun, 15 Aug 2010 19:43:08 +0300 Subject: [PATCH] parser: Do not scan processes twice Before we would scan some processes twice: First when we find out the pages of the interesting processes, then again when we scan the rest of the processes. This patch changes the handling so that the second time we ignore all interesting pids that we already scanned. Signed-off-by: Timo Kokkonen --- pagemap.h | 1 + parse.c | 58 +++++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 47 insertions(+), 12 deletions(-) diff --git a/pagemap.h b/pagemap.h index fae18f0..27e4918 100644 --- a/pagemap.h +++ b/pagemap.h @@ -67,6 +67,7 @@ struct process { #define PARSE_MAP_NAME 0x2 #define PARSE_PROCESS_NAME 0x4 #define PARSE_DUMP 0x8 +#define PARSE_NOADD_TREE 0x10 struct parse_opts { int parse_mask; diff --git a/parse.c b/parse.c index 3934fff..7f62748 100644 --- a/parse.c +++ b/parse.c @@ -165,25 +165,51 @@ static char *get_name_by_pid(int pid) return bname; } -static int check_parse_opts(struct parse_opts *opts, struct pageframe *pf, - struct maps *map) +static int should_scan_process(struct parse_opts *opts, struct process *process) { + int match = 0; + char *name; + + if (opts->parse_mask & PARSE_PROCESS_NAME) { + name = get_name_by_pid(process->pid); + if (!strcmp(opts->name, name ? name : "")) + match = 1; + } + if (opts->parse_mask & PARSE_PID) { - if (opts->pid == map->pid) - return 1; + if (opts->pid == process->pid) + match = 1; } + if (opts->parse_mask & PARSE_NOADD_TREE) + match = !match; + + return match; +} + +static int should_scan_mapping(struct parse_opts *opts, struct maps *map) +{ + int match = 0; + if (opts->parse_mask & PARSE_MAP_NAME) { if (!strcmp(opts->name, map->name)) - return 1; - } + match = 1; - if (opts->parse_mask & PARSE_PROCESS_NAME) { - if (!strcmp(opts->name, get_name_by_pid(map->pid))) - return 1; - } + if (opts->parse_mask & PARSE_NOADD_TREE) + match = !match; + } else + match = 1; - return 0; + return match; +} + +static int should_add_to_tree(struct parse_opts *opts, struct pageframe *pf, + struct maps *map) +{ + if (opts->parse_mask & PARSE_NOADD_TREE) + return 0; + + return 1; } /* Read data from the /proc/pid/pagemap file */ @@ -205,6 +231,9 @@ static int parse_pageframe(FILE *file, struct pageframe *pf_tree, start = map->start >> (PAGE_SHIFT - 3); len = map->size >> (PAGE_SHIFT); + if (!should_scan_mapping(opts, map)) + continue; + ret = fseek(file, start, SEEK_SET); if (ret) { error = errno; @@ -237,7 +266,7 @@ static int parse_pageframe(FILE *file, struct pageframe *pf_tree, pageframe->page_present)) continue; - if (check_parse_opts(opts, pageframe, map)) { + if (should_add_to_tree(opts, pageframe, map)) { match = tree_to_pageframe( bintree_add(&pf_tree->tree, &pageframe->tree, @@ -297,6 +326,8 @@ static int read_pageframe(int pid, int tid, struct pageframe *pageframe, process->pid = pid; process->tid = tid; + if (!should_scan_process(opts, process)) + goto free; snprintf(path, sizeof(path), "/proc/%d/task/%d/maps", pid, tid); file = fopen(path, "rb"); @@ -480,6 +511,9 @@ int scan_all_pids(struct pageframe *pf, struct process **process_list, if (opts->parse_mask & PARSE_DUMP) return 0; + /* Do not add new pages in the tree after the initial scan */ + opts->parse_mask |= PARSE_NOADD_TREE; + while (1) { pid = get_next_pid(&dir); if (pid <= 0) -- 2.45.0