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 (!strcmp(opts->name, map->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;
251 process = malloc(sizeof(*process));
252 memset(process, 0, sizeof(*process));
253 INIT_LIST_HEAD(&process->list);
258 if (!should_scan_process(opts, process))
261 snprintf(path, sizeof(path), "/proc/%d/task/%d/maps", pid, tid);
262 file = fopen(path, "rb");
267 maps = parse_maps(file, pid, tid);
269 process->maps = maps;
271 snprintf(path, sizeof(path), "/proc/%d/task/%d/pagemap", pid, tid);
272 file = fopen(path, "rb");
277 parse_pageframe(file, pageframe, maps, opts);
280 if (read_cmdline(pid, tid, process->name, sizeof(process->name)))
284 list_for_each_entry(maps, &process->maps->list, list) {
285 process->pages_present += maps->pages_present;
286 process->pages_swapped += maps->pages_swapped;
290 if (!is_parse_option(opts, PARSE_NOADD_TREE))
291 process->is_initial_pid = 1;
293 list_add_tail(&process->list, &process_list->list);
302 static int read_pageframe_with_threads(int pid,
303 struct pageframe *pageframe,
304 struct process *process_list,
305 struct parse_opts *opts)
312 if (opts->with_threads)
313 tid = get_next_tid(pid, &dir);
320 count += read_pageframe(pid, tid, pageframe, process_list,
323 if (!opts->with_threads)
330 int scan_all_pids(struct pageframe *pf, struct process *process_list,
331 struct parse_opts *opts)
333 struct pidlist *pidlist;
338 if (is_parse_option(opts, PARSE_PID)) {
339 list_for_each_entry(pidlist, &opts->pidlist, list) {
340 count += read_pageframe_with_threads(pidlist->pid, pf,
345 if ((count == 0) && !(is_parse_option(opts, PARSE_MAP_NAME))) {
346 printf("Failed to find any matching processes "
347 "with given arguments\n");
351 if (is_parse_option(opts, PARSE_DUMP))
354 if (is_parse_option(opts, PARSE_MAP_NAME)) {
356 pid = get_next_pid(&dir);
359 read_pageframe_with_threads(pid, pf, process_list,
363 /* Do not add new pages in the tree after the initial scan */
364 opts->parse_mask |= PARSE_NOADD_TREE;
367 pid = get_next_pid(&dir);
370 read_pageframe_with_threads(pid, pf, process_list, opts);