• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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