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)
110 if (is_parse_option(opts, PARSE_PROCESS_NAME)) {
111 name = get_name_by_pid(process->pid);
112 if (!strcmp(opts->name, name ? name : ""))
116 if (is_parse_option(opts, PARSE_PID)) {
117 list_for_each_entry(pid, &opts->pidlist, list) {
118 if (pid->pid == process->pid) {
125 if (is_parse_option(opts, PARSE_MAP_NAME))
128 if (is_parse_option(opts, PARSE_NOADD_TREE))
134 static int should_scan_mapping(struct parse_opts *opts, struct maps *map)
138 if (is_parse_option(opts, PARSE_MAP_NAME)) {
139 if (!strcmp(opts->name, map->name))
142 if (is_parse_option(opts, PARSE_NOADD_TREE))
150 static int should_add_to_tree(struct parse_opts *opts, struct pageframe *pf,
153 if (is_parse_option(opts, PARSE_NOADD_TREE))
159 /* Read data from the /proc/pid/pagemap file */
160 static int parse_pageframe(FILE *file, struct pageframe *pf_tree,
161 struct maps *maps, struct parse_opts *opts)
164 struct maps_list *tmp;
165 struct pageframe *match, *pageframe = NULL;
167 unsigned long long pf[10240];
173 /* Go through the list of allocated memory areas */
174 list_for_each_entry(map, &maps->list, list) {
175 start = map->start >> (PAGE_SHIFT - 3);
176 len = map->size >> (PAGE_SHIFT);
178 if (!should_scan_mapping(opts, map))
181 ret = fseek(file, start, SEEK_SET);
184 fprintf(stderr, "Error seeking to %lx: %s\n", start,
189 for (i = 0; i < len; i++) {
192 MIN(sizeof(pf), (len - i) * 8), file);
199 pageframe = alloc_pageframe();
200 ret -= sizeof(pf[0]);
202 /* ignore unused pages */
203 if (!pf[ret / sizeof(pf[0])])
206 pageframe->pf = (pf[ret / sizeof(pf[0])]);
208 /* ignore unused pages */
209 if (!(page_swapped(pageframe) ||
210 page_present(pageframe)))
213 if (should_add_to_tree(opts, pageframe, map)) {
214 match = tree_to_pageframe(
215 bintree_add(&pf_tree->tree,
219 match = tree_to_pageframe(
220 bintree_find(&pf_tree->tree,
228 if (match == pageframe)
233 * Add a link from the physical page to this
236 tmp = alloc_maplist();
238 list_add(&tmp->list, &match->ml);
240 if (page_present(match))
241 map->pages_present++;
242 else if (page_swapped(match))
243 map->pages_swapped++;
250 static int read_pageframe(int pid, int tid, struct pageframe *pageframe,
251 struct process *process_list, struct parse_opts *opts)
254 struct process *process;
258 process = malloc(sizeof(*process));
259 memset(process, 0, sizeof(*process));
260 INIT_LIST_HEAD(&process->list);
265 if (!should_scan_process(opts, process))
268 snprintf(path, sizeof(path), "/proc/%d/task/%d/maps", pid, tid);
269 file = fopen(path, "rb");
274 maps = parse_maps(file, pid, tid);
276 process->maps = maps;
278 snprintf(path, sizeof(path), "/proc/%d/task/%d/pagemap", pid, tid);
279 file = fopen(path, "rb");
284 parse_pageframe(file, pageframe, maps, opts);
287 if (read_cmdline(pid, tid, process->name, sizeof(process->name)))
291 list_for_each_entry(maps, &process->maps->list, list) {
292 process->pages_present += maps->pages_present;
293 process->pages_swapped += maps->pages_swapped;
297 if (!is_parse_option(opts, PARSE_NOADD_TREE))
298 process->is_initial_pid = 1;
300 list_add_tail(&process->list, &process_list->list);
309 static int read_pageframe_with_threads(int pid,
310 struct pageframe *pageframe,
311 struct process *process_list,
312 struct parse_opts *opts)
319 if (opts->with_threads)
320 tid = get_next_tid(pid, &dir);
327 count += read_pageframe(pid, tid, pageframe, process_list,
330 if (!opts->with_threads)
337 int scan_all_pids(struct pageframe *pf, struct process *process_list,
338 struct parse_opts *opts)
340 struct pidlist *pidlist;
345 if (is_parse_option(opts, PARSE_PROCESS_NAME)) {
346 while ((pid = get_next_pid_by_name(&dir, opts->name))) {
347 count += read_pageframe_with_threads(pid, pf,
354 if (is_parse_option(opts, PARSE_PID)) {
355 list_for_each_entry(pidlist, &opts->pidlist, list) {
356 count += read_pageframe_with_threads(pidlist->pid, pf,
361 if ((count == 0) && !(is_parse_option(opts, PARSE_MAP_NAME))) {
362 printf("Failed to find any matching processes "
363 "with given arguments\n");
367 if (is_parse_option(opts, PARSE_DUMP))
370 if (is_parse_option(opts, PARSE_MAP_NAME)) {
372 pid = get_next_pid(&dir);
375 read_pageframe_with_threads(pid, pf, process_list,
379 /* Do not add new pages in the tree after the initial scan */
380 opts->parse_mask |= PARSE_NOADD_TREE;
383 pid = get_next_pid(&dir);
386 read_pageframe_with_threads(pid, pf, process_list, opts);