10 static struct maps_list *alloc_maplist(void)
12 struct maps_list *map;
14 map = malloc(sizeof *map);
18 memset(map, 0, sizeof(*map));
19 INIT_LIST_HEAD(&map->list);
24 static struct maps *alloc_map(void)
28 map = malloc(sizeof *map);
32 memset(map, 0, sizeof(*map));
33 INIT_LIST_HEAD(&map->list);
38 static struct maps *parse_maps(FILE *file, int pid, int tid)
40 struct maps *the_map = NULL;
44 while (fgets(line, sizeof(line), file)) {
45 struct maps *map = alloc_map();
46 unsigned long start, end;
55 ret = sscanf(line, "%lx-%lx %*s %*s %*s %*s %s",
59 printf("Error reading input: %s\n", line);
65 map->size = end - start;
70 strncpy(map->name, name, sizeof(map->name));
72 list_add_tail(&map->list, &the_map->list);
78 static struct pageframe *alloc_pageframe(void)
80 struct pageframe *pageframe;
82 pageframe = malloc(sizeof *pageframe);
83 if (pageframe == NULL)
86 clear_pageframe(pageframe);
91 static int compare_pageframe(struct bintree *at, struct bintree *bt)
93 struct pageframe *a, *b;
94 a = tree_to_pageframe(at);
95 b = tree_to_pageframe(bt);
100 struct bintree_ops pageframe_ops = {
101 .compare = compare_pageframe,
104 static int should_scan_process(struct parse_opts *opts, struct process *process)
109 if (is_parse_option(opts, PARSE_PID)) {
110 list_for_each_entry(pid, &opts->pidlist, list) {
111 if (pid->pid == process->pid) {
118 if (is_parse_option(opts, PARSE_MAP_NAME))
121 if (is_parse_option(opts, PARSE_NOADD_TREE))
127 static int should_scan_mapping(struct parse_opts *opts, struct maps *map)
131 if (is_parse_option(opts, PARSE_MAP_NAME)) {
132 if (strstr(map->name, opts->name))
135 if (is_parse_option(opts, PARSE_NOADD_TREE))
143 static int should_add_to_tree(struct parse_opts *opts, struct pageframe *pf,
146 if (is_parse_option(opts, PARSE_NOADD_TREE))
152 /* Read data from the /proc/pid/pagemap file */
153 static int parse_pageframe(FILE *file, struct pageframe *pf_tree,
154 struct maps *maps, struct parse_opts *opts)
157 struct maps_list *tmp;
158 struct pageframe *match, *pageframe = NULL;
160 unsigned long long pf[10240];
166 /* Go through the list of allocated memory areas */
167 list_for_each_entry(map, &maps->list, list) {
168 start = map->start >> (PAGE_SHIFT - 3);
169 len = map->size >> (PAGE_SHIFT);
171 if (!should_scan_mapping(opts, map))
174 ret = fseek(file, start, SEEK_SET);
177 fprintf(stderr, "Error seeking to %lx: %s\n", start,
182 for (i = 0; i < len; i++) {
185 MIN(sizeof(pf), (len - i) * 8), file);
192 pageframe = alloc_pageframe();
193 ret -= sizeof(pf[0]);
195 /* ignore unused pages */
196 if (!pf[ret / sizeof(pf[0])])
199 pageframe->pf = (pf[ret / sizeof(pf[0])]);
201 /* ignore unused pages */
202 if (!(page_swapped(pageframe) ||
203 page_present(pageframe)))
206 if (should_add_to_tree(opts, pageframe, map)) {
207 match = tree_to_pageframe(
208 bintree_add(&pf_tree->tree,
212 match = tree_to_pageframe(
213 bintree_find(&pf_tree->tree,
221 if (match == pageframe)
226 * Add a link from the physical page to this
229 tmp = alloc_maplist();
231 list_add(&tmp->list, &match->ml);
233 if (page_present(match))
234 map->pages_present++;
235 else if (page_swapped(match))
236 map->pages_swapped++;
243 static int read_pageframe(int pid, int tid, struct pageframe *pageframe,
244 struct process *process_list, struct parse_opts *opts)
247 struct process *process;
248 struct pidlist *pidl, *n;
252 process = malloc(sizeof(*process));
253 memset(process, 0, sizeof(*process));
254 INIT_LIST_HEAD(&process->list);
259 if (!should_scan_process(opts, process))
262 snprintf(path, sizeof(path), "/proc/%d/task/%d/maps", pid, tid);
263 file = fopen(path, "rb");
268 maps = parse_maps(file, pid, tid);
270 process->maps = maps;
272 snprintf(path, sizeof(path), "/proc/%d/task/%d/pagemap", pid, tid);
273 file = fopen(path, "rb");
278 parse_pageframe(file, pageframe, maps, opts);
281 if (read_cmdline(pid, tid, process->name, sizeof(process->name)))
285 list_for_each_entry(maps, &process->maps->list, list) {
286 process->pages_present += maps->pages_present;
287 process->pages_swapped += maps->pages_swapped;
291 if (!is_parse_option(opts, PARSE_NOADD_TREE))
292 process->is_initial_pid = 1;
294 list_add_tail(&process->list, &process_list->list);
301 * Remove the pid from the list. It is no longer an
302 * interesting pid, since we can't access its data
304 list_for_each_entry_safe(pidl, n, &opts->pidlist, list) {
305 if (pidl->pid == pid) {
306 list_del(&pidl->list);
314 static int read_pageframe_with_threads(int pid,
315 struct pageframe *pageframe,
316 struct process *process_list,
317 struct parse_opts *opts)
324 if (opts->with_threads)
325 tid = get_next_tid(pid, &dir);
332 count += read_pageframe(pid, tid, pageframe, process_list,
335 if (!opts->with_threads)
342 int scan_all_pids(struct pageframe *pf, struct process *process_list,
343 struct parse_opts *opts)
345 struct pidlist *pidlist, *n;
350 if (is_parse_option(opts, PARSE_PID)) {
351 list_for_each_entry_safe(pidlist, n, &opts->pidlist, list) {
352 count += read_pageframe_with_threads(pidlist->pid, pf,
357 if ((count == 0) && !(is_parse_option(opts, PARSE_MAP_NAME))) {
358 printf("Failed to find any matching processes "
359 "with given arguments\n");
363 if (is_parse_option(opts, PARSE_DUMP))
366 if (is_parse_option(opts, PARSE_MAP_NAME)) {
368 pid = get_next_pid(&dir);
371 read_pageframe_with_threads(pid, pf, process_list,
375 /* Do not add new pages in the tree after the initial scan */
376 opts->parse_mask |= PARSE_NOADD_TREE;
379 pid = get_next_pid(&dir);
382 read_pageframe_with_threads(pid, pf, process_list, opts);