11 static struct maps_list *alloc_maplist(void)
13 struct maps_list *map;
15 map = malloc(sizeof *map);
19 memset(map, 0, sizeof(*map));
20 INIT_LIST_HEAD(&map->list);
25 static struct maps *alloc_map(void)
29 map = malloc(sizeof *map);
33 memset(map, 0, sizeof(*map));
34 INIT_LIST_HEAD(&map->list);
39 static struct maps *parse_maps(FILE *file, int pid)
41 struct maps *the_map = NULL;
45 while(fgets(line, sizeof(line), file)) {
46 struct maps *map = alloc_map();
47 unsigned long start, end;
56 ret = sscanf(line, "%lx-%lx %*s %*s %*s %*s %s",
60 printf("Error reading input: %s\n", line);
66 map->size = end - start;
70 strncpy(map->name, name, sizeof(map->name));
72 list_add_tail(&map->list, &the_map->list);
78 static void clear_pageframe(struct pageframe *pf)
80 memset(pf, 0, sizeof(*pf));
83 static struct pageframe *alloc_pageframe(void)
85 struct pageframe *pageframe;
87 pageframe = malloc(sizeof *pageframe);
88 if (pageframe == NULL)
91 clear_pageframe(pageframe);
96 #define BITRANGE(first, last) (((2ll << (last - first)) - 1) << first)
98 static void pageframe_to_struct(unsigned long long p, struct pageframe *pf)
100 pf->page_present = !!(BITRANGE(63, 63) & p);
101 pf->page_swapped = !!(BITRANGE(62, 62) & p);
102 pf->page_shift = (BITRANGE(55, 60) & p) >> 55;
103 pf->pfn = (BITRANGE(0, 54) & p);
104 pf->swap_type = (BITRANGE(0, 4) & p);
105 pf->swap_offset = (BITRANGE(5, 54) & p) >> 5;
107 printf("pfn: %lx shift: %d present: %d swapped %d\n",
108 pf->pfn, pf->page_shift, pf->page_present, pf->page_swapped);
112 static int compare_pageframe(struct bintree *at, struct bintree *bt)
114 struct pageframe *a, *b;
115 a = tree_to_pageframe(at);
116 b = tree_to_pageframe(bt);
118 return a->pfn - b->pfn;
121 struct bintree_ops pageframe_ops = {
122 .compare = compare_pageframe,
125 /* Read data from the /proc/pid/pagemap file */
126 static int parse_pageframe(FILE *file, struct pageframe *pf_tree,
127 struct maps *maps, int add_to_tree)
130 struct maps_list *tmp;
131 struct pageframe *match, *pageframe = NULL;
133 unsigned long long pf;
139 /* Go through the list of allocated memory areas */
140 list_for_each_entry(map, &maps->list, list) {
141 start = map->start >> (PAGE_SHIFT - 3);
142 len = map->size >> (PAGE_SHIFT - 3);
144 ret = fseek(file, start, SEEK_SET);
147 fprintf(stderr, "Error seeking to %lx: %s\n", start,
152 for (i = 0; i < len; i++) {
153 ret = fread(&pf, 1, sizeof(pf), file);
154 if (ret != sizeof(pf)) {
159 pageframe = alloc_pageframe();
161 pageframe_to_struct(pf, pageframe);
164 match = tree_to_pageframe(
165 bintree_add(&pf_tree->tree,
169 match = tree_to_pageframe(
170 bintree_find(&pf_tree->tree,
178 if (match == pageframe)
183 * Add a link from the physical page to this
187 match->ml = alloc_maplist();
188 match->ml->map = map;
190 tmp = alloc_maplist();
192 list_add(&match->ml->list, &tmp->list);
195 if (match->page_present) {
196 map->pages_present++;
197 } else if (match->page_swapped) {
198 map->pages_swapped++;
206 void read_pageframe(int pid, struct pageframe *pageframe,
207 struct process **process_list, int add_to_tree)
210 struct process *process;
215 process = malloc(sizeof(*process));
216 memset(process, 0, sizeof(*process));
217 INIT_LIST_HEAD(&process->list);
219 if (*process_list == NULL)
220 *process_list = process;
224 list_add_tail(&process->list, &(*process_list)->list);
226 snprintf(path, sizeof(path), "/proc/%d/maps", pid);
227 file = fopen(path, "rb");
232 maps = parse_maps(file, pid);
234 process->maps = maps;
236 snprintf(path, sizeof(path), "/proc/%d/pagemap", pid);
237 file = fopen(path, "rb");
242 parse_pageframe(file, pageframe, maps, add_to_tree);
245 snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
246 file = fopen(path, "rb");
251 ret = fread(process->name, 1, sizeof(process->name), file);
253 process->name[ret - 1] = 0;
259 list_for_each_entry(maps, &process->maps->list, list) {
260 process->pages_present += maps->pages_present;
261 process->pages_swapped += maps->pages_swapped;
267 static int get_next_pid(void)
269 static DIR *dir = NULL;
270 struct dirent *dirent;
274 dir = opendir("/proc");
277 printf("Failed to open /proc directory: %s\n",
284 dirent = readdir(dir);
292 printf("Failed to read /proc directory: %s\n", strerror(error));
296 printf("%s\n", dirent->d_name);
297 if (dirent->d_name[0] < '0' || dirent->d_name[0] > '9')
300 return atoi(dirent->d_name);
303 void scan_all_pids(struct pageframe *pf, struct process **process_list,
308 read_pageframe(interesting_pid, pf, process_list, 1);
311 pid = get_next_pid();
314 read_pageframe(pid, pf, process_list, 0);