]> git.itanic.dy.fi Git - scan-pagemap/blobdiff - analyze.c
Replace bintree with rbtree implementation
[scan-pagemap] / analyze.c
index 57d08694d2fcac4b9011a602797c049b40b36f49..a032eff139e271eede59eaa3e26fdf2687748193 100644 (file)
--- a/analyze.c
+++ b/analyze.c
@@ -20,7 +20,6 @@
 
 #include "analyze.h"
 #include "utils.h"
-#include "bintree.h"
 
 struct kpageflag_str kpageflag_str[] = {
        { .flag = LOCKED,               .str = "locked", },
@@ -67,8 +66,6 @@ struct kpageflag_str kpageflag_str[] = {
 #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;
@@ -87,97 +84,106 @@ struct analyze_frames {
 #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");
 
@@ -210,7 +216,7 @@ void print_page_stats(struct pageframe *pf)
                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;
@@ -232,10 +238,9 @@ void print_pid_stats(struct pageframe *pf, struct process *process_list,
                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;
@@ -296,7 +301,7 @@ restart:
        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;
@@ -315,12 +320,11 @@ static void _dump_process_maps(struct pageframe *pf, struct process *ps,
 
                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;
                }
@@ -371,12 +375,12 @@ restart:
        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);
        }
 }