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