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/cdefs.h>
     23 #include <sys/types.h>
     24 #include <sys/queue.h>
     25 
     26 #include <linux/kernel-page-flags.h>
     27 
     28 __BEGIN_DECLS
     29 
     30 typedef struct pm_proportional_swap pm_proportional_swap_t;
     31 
     32 typedef struct pm_swap_offset pm_swap_offset_t;
     33 
     34 struct pm_swap_offset {
     35     unsigned int offset;
     36     SIMPLEQ_ENTRY(pm_swap_offset) simpleqe;
     37 };
     38 
     39 typedef struct pm_memusage pm_memusage_t;
     40 
     41 /* Holds the various metrics for memory usage of a process or a mapping. */
     42 struct pm_memusage {
     43     size_t vss;
     44     size_t rss;
     45     size_t pss;
     46     size_t uss;
     47     size_t swap;
     48     /* if non NULL then use swap_offset_list to compute proportional swap */
     49     pm_proportional_swap_t *p_swap;
     50     SIMPLEQ_HEAD(simpleqhead, pm_swap_offset) swap_offset_list;
     51 };
     52 
     53 typedef struct pm_swapusage pm_swapusage_t;
     54 struct pm_swapusage {
     55     size_t proportional;
     56     size_t unique;
     57 };
     58 
     59 /* Clears a memusage. */
     60 void pm_memusage_zero(pm_memusage_t *mu);
     61 /* Adds one memusage (a) to another (b). */
     62 void pm_memusage_add(pm_memusage_t *a, pm_memusage_t *b);
     63 /* Adds a swap offset */
     64 void pm_memusage_pswap_add_offset(pm_memusage_t *mu, unsigned int offset);
     65 /* Enable proportional swap computing. */
     66 void pm_memusage_pswap_init_handle(pm_memusage_t *mu, pm_proportional_swap_t *p_swap);
     67 /* Computes and return the proportional swap */
     68 void pm_memusage_pswap_get_usage(pm_memusage_t *mu, pm_swapusage_t *su);
     69 void pm_memusage_pswap_free(pm_memusage_t *mu);
     70 /* Initialize a proportional swap computing handle:
     71    assumes only 1 swap device, total swap size of this device in bytes to be given as argument */
     72 pm_proportional_swap_t * pm_memusage_pswap_create(int swap_size);
     73 void pm_memusage_pswap_destroy(pm_proportional_swap_t *p_swap);
     74 
     75 typedef struct pm_kernel   pm_kernel_t;
     76 typedef struct pm_process  pm_process_t;
     77 typedef struct pm_map      pm_map_t;
     78 
     79 /* pm_kernel_t holds the state necessary to interface to the kernel's pagemap
     80  * system on a global level. */
     81 struct pm_kernel {
     82     int kpagecount_fd;
     83     int kpageflags_fd;
     84 
     85     int pagesize;
     86 };
     87 
     88 /* pm_process_t holds the state necessary to interface to a particular process'
     89  * pagemap. */
     90 struct pm_process {
     91     pm_kernel_t *ker;
     92 
     93     pid_t pid;
     94 
     95     pm_map_t **maps;
     96     int num_maps;
     97 
     98     int pagemap_fd;
     99 };
    100 
    101 /* pm_map_t holds the state necessary to access information about a particular
    102  * mapping in a particular process. */
    103 struct pm_map {
    104     pm_process_t *proc;
    105 
    106     uint64_t start;
    107     uint64_t end;
    108     uint64_t offset;
    109     int flags;
    110 
    111     char *name;
    112 };
    113 
    114 /* Create a pm_kernel_t. */
    115 int pm_kernel_create(pm_kernel_t **ker_out);
    116 
    117 #define pm_kernel_pagesize(ker) ((ker)->pagesize)
    118 
    119 /* Get a list of probably-existing PIDs (returned through *pids_out).
    120  * Length of the array (in sizeof(pid_t) units) is returned through *len.
    121  * The array should be freed by the caller. */
    122 int pm_kernel_pids(pm_kernel_t *ker, pid_t **pids_out, size_t *len);
    123 
    124 /* Get the map count (from /proc/kpagecount) of a physical frame.
    125  * The count is returned through *count_out. */
    126 int pm_kernel_count(pm_kernel_t *ker, uint64_t pfn, uint64_t *count_out);
    127 
    128 /* Get the page flags (from /proc/kpageflags) of a physical frame.
    129  * Flag constants are in <linux/kernel-page-flags.h>.
    130  * The count is returned through *flags_out.
    131  */
    132 int pm_kernel_flags(pm_kernel_t *ker, uint64_t pfn, uint64_t *flags_out);
    133 
    134 /* Destroy a pm_kernel_t. */
    135 int pm_kernel_destroy(pm_kernel_t *ker);
    136 
    137 /* Get the PID of a pm_process_t. */
    138 #define pm_process_pid(proc) ((proc)->pid)
    139 
    140 /* Create a pm_process_t and returns it through *proc_out.
    141  * Takes a pm_kernel_t, and the PID of the process. */
    142 int pm_process_create(pm_kernel_t *ker, pid_t pid, pm_process_t **proc_out);
    143 
    144 /* Get the total memory usage of a process and store in *usage_out. */
    145 int pm_process_usage(pm_process_t *proc, pm_memusage_t *usage_out);
    146 
    147 /* Get the total memory usage of a process and store in *usage_out, only
    148  * counting pages with specified flags. */
    149 int pm_process_usage_flags(pm_process_t *proc, pm_memusage_t *usage_out,
    150                         uint64_t flags_mask, uint64_t required_flags);
    151 
    152 /* Get the working set of a process (if ws_out != NULL), and reset it
    153  * (if reset != 0). */
    154 int pm_process_workingset(pm_process_t *proc, pm_memusage_t *ws_out, int reset);
    155 
    156 /* Get the PFNs corresponding to a range of virtual addresses.
    157  * The array of PFNs is returned through *range_out, and the caller has the
    158  * responsibility to free it. */
    159 int pm_process_pagemap_range(pm_process_t *proc,
    160                              uint64_t low, uint64_t hi,
    161                              uint64_t **range_out, size_t *len);
    162 
    163 #define _BITS(x, offset, bits) (((x) >> (offset)) & ((1LL << (bits)) - 1))
    164 
    165 #define PM_PAGEMAP_PRESENT(x)     (_BITS(x, 63, 1))
    166 #define PM_PAGEMAP_SWAPPED(x)     (_BITS(x, 62, 1))
    167 #define PM_PAGEMAP_SHIFT(x)       (_BITS(x, 55, 6))
    168 #define PM_PAGEMAP_PFN(x)         (_BITS(x, 0, 55))
    169 #define PM_PAGEMAP_SWAP_OFFSET(x) (_BITS(x, 5, 50))
    170 #define PM_PAGEMAP_SWAP_TYPE(x)   (_BITS(x, 0,  5))
    171 
    172 /* Get the maps in the virtual address space of this process.
    173  * Returns an array of pointers to pm_map_t through *maps.
    174  * The array should be freed by the caller, but the maps should not be
    175  * modified or destroyed. */
    176 int pm_process_maps(pm_process_t *proc, pm_map_t ***maps_out, size_t *len);
    177 
    178 /* Destroy a pm_process_t. */
    179 int pm_process_destroy(pm_process_t *proc);
    180 
    181 /* Get the name, flags, start/end address, or offset of a map. */
    182 #define pm_map_name(map)   ((map)->name)
    183 #define pm_map_flags(map)  ((map)->flags)
    184 #define PM_MAP_READ  1
    185 #define PM_MAP_WRITE 2
    186 #define PM_MAP_EXEC  4
    187 #define PM_MAP_PERMISSIONS (PM_MAP_READ | PM_MAP_WRITE | PM_MAP_EXEC)
    188 #define pm_map_start(map)  ((map)->start)
    189 #define pm_map_end(map)    ((map)->end)
    190 #define pm_map_offset(map) ((map)->offset)
    191 
    192 /* Get the PFNs of the pages in the virtual address space of this map.
    193  * Array of PFNs is returned through *pagemap_out, and should be freed by the
    194  * caller. */
    195 int pm_map_pagemap(pm_map_t *map, uint64_t **pagemap_out, size_t *len);
    196 
    197 /* Get the memory usage of this map alone. */
    198 int pm_map_usage(pm_map_t *map, pm_memusage_t *usage_out);
    199 
    200 /* Get the memory usage of this map alone, only counting pages with specified
    201  * flags. */
    202 int pm_map_usage_flags(pm_map_t *map, pm_memusage_t *usage_out,
    203                         uint64_t flags_mask, uint64_t required_flags);
    204 
    205 /* Get the working set of this map alone. */
    206 int pm_map_workingset(pm_map_t *map, pm_memusage_t *ws_out);
    207 
    208 __END_DECLS
    209 
    210 #endif
    211