pagemap.h revision 7341494707810f709855ea85ce03a8ec3ac8dbaf
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 24typedef struct pm_memusage pm_memusage_t; 25 26/* Holds the various metrics for memory usage of a process or a mapping. */ 27struct pm_memusage { 28 size_t vss; 29 size_t rss; 30 size_t pss; 31 size_t uss; 32}; 33 34/* Clears a memusage. */ 35void pm_memusage_zero(pm_memusage_t *mu); 36/* Adds one memusage (a) to another (b). */ 37void pm_memusage_add(pm_memusage_t *a, pm_memusage_t *b); 38 39typedef struct pm_kernel pm_kernel_t; 40typedef struct pm_process pm_process_t; 41typedef 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. */ 45struct 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. */ 54struct 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. */ 67struct 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. */ 79int 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. */ 86int 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. */ 90int 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. */ 94int 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. */ 109int 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. */ 116int 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. */ 119int 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). */ 123int 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. */ 128int 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)) - 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. */ 145int pm_process_maps(pm_process_t *proc, pm_map_t ***maps_out, size_t *len); 146 147/* Destroy a pm_process_t. */ 148int 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. */ 163int pm_map_pagemap(pm_map_t *map, uint64_t **pagemap_out, size_t *len); 164 165/* Get the memory usage of this map alone. */ 166int pm_map_usage(pm_map_t *map, pm_memusage_t *usage_out); 167 168/* Get the working set of this map alone. */ 169int pm_map_workingset(pm_map_t *map, pm_memusage_t *ws_out); 170 171#endif 172