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