9 #define SI_M (SI_k * SI_k)
10 #define SI_G (SI_M * SI_k)
12 #define PRETTY_THRESH 98
14 ((a) < SI_k * 4 ? (a) : \
15 (a < SI_M * PRETTY_THRESH ? ((a) / SI_k) : \
16 (a < SI_G * PRETTY_THRESH ? ((a) / SI_M) : \
19 #define NICE_UNIT(a) \
20 ((a) < (SI_k * 4) ? " " : \
21 ((a) < (SI_M * PRETTY_THRESH) ? "k" : \
22 ((a) < (SI_G * PRETTY_THRESH) ? "M" : "G")))
24 #define PAGE_TO_NICE(a) NICE_DIV((long long)a * PAGE_SIZE)
25 #define PAGE_TO_NICE_UNIT(a) NICE_UNIT((long long)a * PAGE_SIZE)
27 struct analyze_frames {
28 struct bintree_ops ops;
32 struct list_head *pidlist;
36 long int pages_present;
37 long int pages_swapped;
38 long int pages_unique;
41 #define bintree_ops_to_af(bintree_ops) \
42 container_of((bintree_ops), struct analyze_frames, ops)
44 static void count_pages(struct bintree *b, struct bintree_ops *ops)
46 struct pageframe *pf = tree_to_pageframe(b);
47 struct analyze_frames *af = bintree_ops_to_af(ops);
51 /* Find pages which reference at least once a pid */
52 list_for_each_entry(ml, &pf->ml, list) {
53 if (ml->map->pid == af->pid)
57 } else if (af->pidlist && af->map) {
59 * Find pages that reference at least once all of the
60 * given pids and a given mapping
66 * Check that we reference the given mapping at least
69 list_for_each_entry(ml, &pf->ml, list) {
70 if (ml->map == af->map) {
81 * Check that we reference all of the given pids
82 * too. The order of the loops is important here. We
83 * must scan through all the references and test for a
84 * given pid. If we would iterate through the
85 * references in the outer loop, we might get
86 * duplicate matches for a pid since it is possible
87 * that a page is mapped multiple times in a process's
90 list_for_each_entry(pid, af->pidlist, list) {
91 list_for_each_entry(ml, &pf->ml, list) {
92 if (ml->map->pid == pid->pid) {
99 * If we have found as many matches as ther
100 * are pids, we will count the stats
102 if (matches == af->pids)
109 if (page_present(pf))
111 else if (page_swapped(pf))
113 if (pf->refcount == 1)
118 * print_page_stats - Prints system wide page stats
120 void print_page_stats(struct pageframe *pf)
122 struct analyze_frames af;
124 memset(&af, 0, sizeof(af));
126 af.ops.callback = count_pages;
128 count = bintree_walk(&pf->tree, &af.ops);
129 printf("present pages: %ld, %lld %sB\n"
130 "Swapped pages: %ld, %lld %sB\n"
131 "Unique pages: %ld, %lld %sB\n"
132 "Total %ld physical pages, %lld %sB\n",
134 PAGE_TO_NICE(af.pages_present),
135 PAGE_TO_NICE_UNIT(af.pages_present),
137 PAGE_TO_NICE(af.pages_swapped),
138 PAGE_TO_NICE_UNIT(af.pages_swapped),
140 PAGE_TO_NICE(af.pages_unique),
141 PAGE_TO_NICE_UNIT(af.pages_unique),
144 PAGE_TO_NICE_UNIT(count));
147 void print_pid_stats(struct pageframe *pf, struct process *process_list,
148 struct parse_opts *opts)
150 struct analyze_frames af;
152 long int swapped, present, total;
153 long int biggest = 0, second_biggest;
154 int count, processes = 0;
157 * walk through all processes, find the one with most present
160 list_for_each_entry(ps, &process_list->list, list) {
161 memset(&af, 0, sizeof(af));
162 af.ops.callback = count_pages;
165 bintree_walk(&pf->tree, &af.ops);
166 ps->pages_present = af.pages_present;
167 ps->pages_swapped = af.pages_swapped;
168 biggest = MAX(biggest, ps->pages_present + ps->pages_swapped);
171 printf(" in ram swapped total pid");
172 if (opts->with_threads)
179 list_for_each_entry(ps, &process_list->list, list) {
181 present = ps->pages_present;
182 swapped = ps->pages_swapped;
183 total = present + swapped;
185 second_biggest = (total < biggest) &&
186 (second_biggest < total) ?
187 total : second_biggest;
189 if (total != biggest)
195 printf("%5lld %sB %5lld %sB %5lld %sB %5d ",
196 PAGE_TO_NICE(present), PAGE_TO_NICE_UNIT(present),
197 PAGE_TO_NICE(swapped), PAGE_TO_NICE_UNIT(swapped),
198 PAGE_TO_NICE(total), PAGE_TO_NICE_UNIT(total),
201 if (opts->with_threads)
202 printf("%5d ", ps->tid);
205 ps->is_initial_pid ? '*' : ' ',
213 biggest = second_biggest;
217 printf("Total %d processes\n", processes);
220 static void _dump_process_maps(struct pageframe *pf, struct process *ps,
221 struct parse_opts *opts)
224 long int swapped, present, total;
225 long int biggest = 0, second_biggest;
226 int count, processes = 0, pids = 0;
228 if (is_parse_option(opts, PARSE_SHARED_MAPPING)) {
230 list_for_each_entry(pid, &opts->pidlist, list)
234 list_for_each_entry(map, &ps->maps->list, list) {
235 struct analyze_frames af;
237 if (is_parse_option(opts, PARSE_SHARED_MAPPING)) {
238 memset(&af, 0, sizeof(af));
239 af.ops.callback = count_pages;
240 af.pidlist = &opts->pidlist;
244 bintree_walk(&pf->tree, &af.ops);
245 map->pages_present = af.pages_present;
246 map->pages_swapped = af.pages_swapped;
249 biggest = MAX(biggest, map->pages_present + map->pages_swapped);
252 printf("process: [%d] %s\n", ps->pid, ps->name);
253 printf(" size in ram swapped total name\n");
257 list_for_each_entry(map, &ps->maps->list, list) {
259 present = map->pages_present;
260 swapped = map->pages_swapped;
261 total = present + swapped;
263 second_biggest = (total < biggest) &&
264 (second_biggest < total) ?
265 total : second_biggest;
267 if (total != biggest)
271 * Do not print zero sized mappings if
272 * --shared-mappings is enabled
274 if (is_parse_option(opts, PARSE_SHARED_MAPPING) && total == 0)
277 printf("%5lld %sB %5lld %sB %5lld %sB %5lld %sB %s\n",
278 NICE_DIV(map->size), NICE_UNIT(map->size),
279 PAGE_TO_NICE(present), PAGE_TO_NICE_UNIT(present),
280 PAGE_TO_NICE(swapped), PAGE_TO_NICE_UNIT(swapped),
281 PAGE_TO_NICE(total), PAGE_TO_NICE_UNIT(total),
288 if (count > 0 && biggest > 0) {
289 biggest = second_biggest;
295 void dump_process_maps(struct pageframe *pf, struct process *process_list,
296 struct parse_opts *opts)
300 list_for_each_entry(ps, &process_list->list, list) {
301 _dump_process_maps(pf, ps, opts);