Home | History | Annotate | Download | only in pagemap
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef _PAGEMAP_PAGEMAP_H
     18 #define _PAGEMAP_PAGEMAP_H
     19 
     20 #include <stdint.h>
     21 #include <stdio.h>
     22 #include <sys/types.h>
     23 
     24 typedef struct pm_memusage pm_memusage_t;
     25 
     26 /* Holds the various metrics for memory usage of a process or a mapping. */
     27 struct pm_memusage {
     28     size_t vss;
     29     size_t rss;
     30     size_t pss;
     31     size_t uss;
     32 };
     33 
     34 /* Clears a memusage. */
     35 void pm_memusage_zero(pm_memusage_t *mu);
     36 /* Adds one memusage (a) to another (b). */
     37 void pm_memusage_add(pm_memusage_t *a, pm_memusage_t *b);
     38 
     39 typedef struct pm_kernel   pm_kernel_t;
     40 typedef struct pm_process  pm_process_t;
     41 typedef struct pm_map      pm_map_t;
     42 
     43 /* pm_kernel_t holds the state necessary to interface to the kernel's pagemap
     44  * system on a global level. */
     45 struct pm_kernel {
     46     int kpagecount_fd;
     47     int kpageflags_fd;
     48 
     49     int pagesize;
     50 };
     51 
     52 /* pm_process_t holds the state necessary to interface to a particular process'
     53  * pagemap. */
     54 struct pm_process {
     55     pm_kernel_t *ker;
     56 
     57     pid_t pid;
     58 
     59     pm_map_t **maps;
     60     int num_maps;
     61 
     62     int pagemap_fd;
     63 };
     64 
     65 /* pm_map_t holds the state necessary to access information about a particular
     66  * mapping in a particular process. */
     67 struct pm_map {
     68     pm_process_t *proc;
     69 
     70     unsigned long start;
     71     unsigned long end;
     72     unsigned long offset;
     73     int flags;
     74 
     75     char *name;
     76 };
     77 
     78 /* Create a pm_kernel_t. */
     79 int pm_kernel_create(pm_kernel_t **ker_out);
     80 
     81 #define pm_kernel_pagesize(ker) ((ker)->pagesize)
     82 
     83 /* Get a list of probably-existing PIDs (returned through *pids_out).
     84  * Length of the array (in sizeof(pid_t) units) is returned through *len.
     85  * The array should be freed by the caller. */
     86 int pm_kernel_pids(pm_kernel_t *ker, pid_t **pids_out, size_t *len);
     87 
     88 /* Get the map count (from /proc/kpagecount) of a physical frame.
     89  * The count is returned through *count_out. */
     90 int pm_kernel_count(pm_kernel_t *ker, unsigned long pfn, uint64_t *count_out);
     91 
     92 /* Get the page flags (from /proc/kpageflags) of a physical frame.
     93  * The count is returned through *flags_out. */
     94 int pm_kernel_flags(pm_kernel_t *ker, unsigned long pfn, uint64_t *flags_out);
     95 
     96 #define PM_PAGE_LOCKED     (1 <<  0)
     97 #define PM_PAGE_ERROR      (1 <<  1)
     98 #define PM_PAGE_REFERENCED (1 <<  2)
     99 #define PM_PAGE_UPTODATE   (1 <<  3)
    100 #define PM_PAGE_DIRTY      (1 <<  4)
    101 #define PM_PAGE_LRU        (1 <<  5)
    102 #define PM_PAGE_ACTIVE     (1 <<  6)
    103 #define PM_PAGE_SLAB       (1 <<  7)
    104 #define PM_PAGE_WRITEBACK  (1 <<  8)
    105 #define PM_PAGE_RECLAIM    (1 <<  9)
    106 #define PM_PAGE_BUDDY      (1 << 10)
    107 
    108 /* Destroy a pm_kernel_t. */
    109 int pm_kernel_destroy(pm_kernel_t *ker);
    110 
    111 /* Get the PID of a pm_process_t. */
    112 #define pm_process_pid(proc) ((proc)->pid)
    113 
    114 /* Create a pm_process_t and returns it through *proc_out.
    115  * Takes a pm_kernel_t, and the PID of the process. */
    116 int pm_process_create(pm_kernel_t *ker, pid_t pid, pm_process_t **proc_out);
    117 
    118 /* Get the total memory usage of a process and store in *usage_out. */
    119 int pm_process_usage(pm_process_t *proc, pm_memusage_t *usage_out);
    120 
    121 /* Get the working set of a process (if ws_out != NULL), and reset it
    122  * (if reset != 0). */
    123 int pm_process_workingset(pm_process_t *proc, pm_memusage_t *ws_out, int reset);
    124 
    125 /* Get the PFNs corresponding to a range of virtual addresses.
    126  * The array of PFNs is returned through *range_out, and the caller has the
    127  * responsibility to free it. */
    128 int pm_process_pagemap_range(pm_process_t *proc,
    129                              unsigned long low, unsigned long hi,
    130                              uint64_t **range_out, size_t *len);
    131 
    132 #define _BITS(x, offset, bits) (((x) >> offset) & ((1LL << (bits)) - 1))
    133 
    134 #define PM_PAGEMAP_PRESENT(x)     (_BITS(x, 63, 1))
    135 #define PM_PAGEMAP_SWAPPED(x)     (_BITS(x, 62, 1))
    136 #define PM_PAGEMAP_SHIFT(x)       (_BITS(x, 55, 6))
    137 #define PM_PAGEMAP_PFN(x)         (_BITS(x, 0, 55))
    138 #define PM_PAGEMAP_SWAP_OFFSET(x) (_BITS(x, 5, 50))
    139 #define PM_PAGEMAP_SWAP_TYPE(x)   (_BITS(x, 0,  5))
    140 
    141 /* Get the maps in the virtual address space of this process.
    142  * Returns an array of pointers to pm_map_t through *maps.
    143  * The array should be freed by the caller, but the maps should not be
    144  * modified or destroyed. */
    145 int pm_process_maps(pm_process_t *proc, pm_map_t ***maps_out, size_t *len);
    146 
    147 /* Destroy a pm_process_t. */
    148 int pm_process_destroy(pm_process_t *proc);
    149 
    150 /* Get the name, flags, start/end address, or offset of a map. */
    151 #define pm_map_name(map)   ((map)->name)
    152 #define pm_map_flags(map)  ((map)->flags)
    153 #define PM_MAP_READ  1
    154 #define PM_MAP_WRITE 2
    155 #define PM_MAP_EXEC  4
    156 #define pm_map_start(map)  ((map)->start)
    157 #define pm_map_end(map)    ((map)->end)
    158 #define pm_map_offset(map) ((map)->offset)
    159 
    160 /* Get the PFNs of the pages in the virtual address space of this map.
    161  * Array of PFNs is returned through *pagemap_out, and should be freed by the
    162  * caller. */
    163 int pm_map_pagemap(pm_map_t *map, uint64_t **pagemap_out, size_t *len);
    164 
    165 /* Get the memory usage of this map alone. */
    166 int pm_map_usage(pm_map_t *map, pm_memusage_t *usage_out);
    167 
    168 /* Get the working set of this map alone. */
    169 int pm_map_workingset(pm_map_t *map, pm_memusage_t *ws_out);
    170 
    171 #endif
    172