#include "analyze.h"
#include "utils.h"
-#include "bintree.h"
struct kpageflag_str kpageflag_str[] = {
{ .flag = LOCKED, .str = "locked", },
#define PAGE_TO_NICE_UNIT(a) NICE_UNIT((long long)a * PAGE_SIZE)
struct analyze_frames {
- struct bintree_ops ops;
-
int pid;
struct list_head *pidlist;
#define bintree_ops_to_af(bintree_ops) \
container_of((bintree_ops), struct analyze_frames, ops)
-static void count_pages(struct bintree *b, struct bintree_ops *ops)
+static int count_pages(struct rb_root *root, struct analyze_frames *af)
{
- struct pageframe *pf = tree_to_pageframe(b);
- struct analyze_frames *af = bintree_ops_to_af(ops);
+ struct pageframe *pf;
struct maps_list *ml;
- int i;
+ int i, pages = 0;
- if (af->pid) {
- /* Find pages which reference at least once a pid */
- list_for_each_entry(ml, &pf->ml, list) {
- if (ml->map->pid == af->pid)
- goto get_stats;
- }
- return;
- } else if (af->pidlist && af->map) {
- /*
- * Find pages that reference at least once all of the
- * given pids and a given mapping
- */
- struct pidlist *pid;
- int matches = 0;
+ pf = rb_to_pageframe(rb_first(root));
- /*
- * Check that we reference the given mapping at least
- * once
- */
- list_for_each_entry(ml, &pf->ml, list) {
- if (ml->map == af->map) {
- matches++;
- break;
- }
- }
+ while (pf) {
+ pages++;
- if (!matches)
- return;
- matches = 0;
+ if (af->pid) {
+ /* Find pages which reference at least once a pid */
+ list_for_each_entry(ml, &pf->ml, list) {
+ if (ml->map->pid == af->pid)
+ goto get_stats;
+ }
+ goto next;
+ } else if (af->pidlist && af->map) {
+ /*
+ * Find pages that reference at least once all
+ * of the given pids and a given mapping
+ */
+ struct pidlist *pid;
+ int matches = 0;
- /*
- * Check that we reference all of the given pids
- * too. The order of the loops is important here. We
- * must scan through all the references and test for a
- * given pid. If we would iterate through the
- * references in the outer loop, we might get
- * duplicate matches for a pid since it is possible
- * that a page is mapped multiple times in a process's
- * addrses space.
- */
- list_for_each_entry(pid, af->pidlist, list) {
+ /*
+ * Check that we reference the given mapping
+ * at least once
+ */
list_for_each_entry(ml, &pf->ml, list) {
- if (ml->map->pid == pid->pid) {
+ if (ml->map == af->map) {
matches++;
break;
}
}
+ if (!matches)
+ goto next;
+ matches = 0;
+
/*
- * If we have found as many matches as ther
- * are pids, we will count the stats
+ * Check that we reference all of the given
+ * pids too. The order of the loops is
+ * important here. We must scan through all
+ * the references and test for a given pid. If
+ * we would iterate through the references in
+ * the outer loop, we might get duplicate
+ * matches for a pid since it is possible that
+ * a page is mapped multiple times in a
+ * process's addrses space.
*/
- if (matches == af->pids)
- goto get_stats;
+ list_for_each_entry(pid, af->pidlist, list) {
+ list_for_each_entry(ml, &pf->ml, list) {
+ if (ml->map->pid == pid->pid) {
+ matches++;
+ break;
+ }
+ }
+
+ /*
+ * If we have found as many matches as ther
+ * are pids, we will count the stats
+ */
+ if (matches == af->pids)
+ goto get_stats;
+ }
+ goto next;
}
- return;
- }
get_stats:
- if (page_present(pf))
- af->pages_present++;
- else if (page_swapped(pf))
- af->pages_swapped++;
- if (pf->kpagecount == 1)
- af->pages_unique++;
-
- for (i = 0; i < KPAGEFLAGS_NUM; i++)
- if (kpageflag_is_set(pf, i))
- af->kpageflag[i]++;
+ if (page_present(pf))
+ af->pages_present++;
+ else if (page_swapped(pf))
+ af->pages_swapped++;
+ if (pf->kpagecount == 1)
+ af->pages_unique++;
+
+ for (i = 0; i < KPAGEFLAGS_NUM; i++)
+ if (kpageflag_is_set(pf, i))
+ af->kpageflag[i]++;
+
+next:
+ pf = rb_to_pageframe(rb_next(&pf->tree));
+ }
+
+ return pages;
}
/*
* print_page_stats - Prints system wide page stats
*/
-void print_page_stats(struct pageframe *pf)
+void print_page_stats(struct rb_root *root)
{
struct analyze_frames af;
long count;
int i;
memset(&af, 0, sizeof(af));
- af.ops.callback = count_pages;
-
- count = bintree_walk(&pf->tree, &af.ops);
+ count = count_pages(root, &af);
printf("\n");
PAGE_TO_NICE_UNIT(count));
}
-void print_pid_stats(struct pageframe *pf, struct process *process_list,
+void print_pid_stats(struct rb_root *root, struct process *process_list,
struct parse_opts *opts)
{
struct analyze_frames af;
fflush(stdout);
memset(&af, 0, sizeof(af));
- af.ops.callback = count_pages;
af.pid = ps->pid;
- bintree_walk(&pf->tree, &af.ops);
+ count_pages(root, &af);
ps->pages_present = af.pages_present;
ps->pages_swapped = af.pages_swapped;
ps->pages_unique = af.pages_unique;
printf("Total %d processes\n", processes);
}
-static void _dump_process_maps(struct pageframe *pf, struct process *ps,
+static void _dump_process_maps(struct rb_root *root, struct process *ps,
struct parse_opts *opts)
{
struct maps *map;
if (is_parse_option(opts, PARSE_SHARED_MAPPING)) {
memset(&af, 0, sizeof(af));
- af.ops.callback = count_pages;
af.pidlist = &opts->pidlist;
af.pids = pids;
af.map = map;
- bintree_walk(&pf->tree, &af.ops);
+ count_pages(root, &af);
map->pages_present = af.pages_present;
map->pages_swapped = af.pages_swapped;
}
printf("\n");
}
-void dump_process_maps(struct pageframe *pf, struct process *process_list,
+void dump_process_maps(struct rb_root *root, struct process *process_list,
struct parse_opts *opts)
{
struct process *ps;
list_for_each_entry(ps, &process_list->list, list) {
- _dump_process_maps(pf, ps, opts);
+ _dump_process_maps(root, ps, opts);
}
}