pagemap.h revision 9eed624c760b9c70de9a8f75ff84c5f085d62fdc
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 30typedef struct pm_proportional_swap pm_proportional_swap_t; 31 32typedef struct pm_swap_offset pm_swap_offset_t; 33 34struct pm_swap_offset { 35 unsigned int offset; 36 SIMPLEQ_ENTRY(pm_swap_offset) simpleqe; 37}; 38 39typedef struct pm_memusage pm_memusage_t; 40 41/* Holds the various metrics for memory usage of a process or a mapping. */ 42struct 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 53typedef struct pm_swapusage pm_swapusage_t; 54struct pm_swapusage { 55 size_t proportional; 56 size_t unique; 57}; 58 59/* Clears a memusage. */ 60void pm_memusage_zero(pm_memusage_t *mu); 61/* Adds one memusage (a) to another (b). */ 62void pm_memusage_add(pm_memusage_t *a, pm_memusage_t *b); 63/* Adds a swap offset */ 64void pm_memusage_pswap_add_offset(pm_memusage_t *mu, unsigned int offset); 65/* Enable proportional swap computing. */ 66void pm_memusage_pswap_init_handle(pm_memusage_t *mu, pm_proportional_swap_t *p_swap); 67/* Computes and return the proportional swap */ 68void pm_memusage_pswap_get_usage(pm_memusage_t *mu, pm_swapusage_t *su); 69void 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 */ 72pm_proportional_swap_t * pm_memusage_pswap_create(int swap_size); 73void pm_memusage_pswap_destroy(pm_proportional_swap_t *p_swap); 74 75typedef struct pm_kernel pm_kernel_t; 76typedef struct pm_process pm_process_t; 77typedef 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. */ 81struct 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. */ 90struct 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. */ 103struct 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. */ 115int 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. */ 122int 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. */ 126int 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 */ 132int pm_kernel_flags(pm_kernel_t *ker, uint64_t pfn, uint64_t *flags_out); 133 134/* Destroy a pm_kernel_t. */ 135int 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. */ 142int 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. */ 145int 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. */ 149int 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). */ 154int 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. */ 159int 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. */ 176int pm_process_maps(pm_process_t *proc, pm_map_t ***maps_out, size_t *len); 177 178/* Destroy a pm_process_t. */ 179int 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. */ 195int pm_map_pagemap(pm_map_t *map, uint64_t **pagemap_out, size_t *len); 196 197/* Get the memory usage of this map alone. */ 198int 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. */ 202int 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. */ 206int pm_map_workingset(pm_map_t *map, pm_memusage_t *ws_out); 207 208__END_DECLS 209 210#endif 211