207 lines
6.7 KiB
C
207 lines
6.7 KiB
C
|
/*
|
||
|
* Copyright (C) 2008 The Android Open Source Project
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
|
||
|
#ifndef _PAGEMAP_PAGEMAP_H
|
||
|
#define _PAGEMAP_PAGEMAP_H
|
||
|
|
||
|
#include <stdint.h>
|
||
|
#include <stdio.h>
|
||
|
#include <sys/cdefs.h>
|
||
|
#include <sys/types.h>
|
||
|
|
||
|
__BEGIN_DECLS
|
||
|
|
||
|
typedef struct pm_memusage pm_memusage_t;
|
||
|
|
||
|
/* Holds the various metrics for memory usage of a process or a mapping. */
|
||
|
struct pm_memusage {
|
||
|
size_t vss;
|
||
|
size_t rss;
|
||
|
size_t pss;
|
||
|
size_t uss;
|
||
|
size_t swap;
|
||
|
};
|
||
|
|
||
|
/* Clears a memusage. */
|
||
|
void pm_memusage_zero(pm_memusage_t *mu);
|
||
|
/* Adds one memusage (a) to another (b). */
|
||
|
void pm_memusage_add(pm_memusage_t *a, pm_memusage_t *b);
|
||
|
|
||
|
typedef struct pm_kernel pm_kernel_t;
|
||
|
typedef struct pm_process pm_process_t;
|
||
|
typedef struct pm_map pm_map_t;
|
||
|
|
||
|
/* pm_kernel_t holds the state necessary to interface to the kernel's pagemap
|
||
|
* system on a global level. */
|
||
|
struct pm_kernel {
|
||
|
int kpagecount_fd;
|
||
|
int kpageflags_fd;
|
||
|
|
||
|
int pagesize;
|
||
|
};
|
||
|
|
||
|
/* pm_process_t holds the state necessary to interface to a particular process'
|
||
|
* pagemap. */
|
||
|
struct pm_process {
|
||
|
pm_kernel_t *ker;
|
||
|
|
||
|
pid_t pid;
|
||
|
|
||
|
pm_map_t **maps;
|
||
|
int num_maps;
|
||
|
|
||
|
int pagemap_fd;
|
||
|
};
|
||
|
|
||
|
/* pm_map_t holds the state necessary to access information about a particular
|
||
|
* mapping in a particular process. */
|
||
|
struct pm_map {
|
||
|
pm_process_t *proc;
|
||
|
|
||
|
uint64_t start;
|
||
|
uint64_t end;
|
||
|
uint64_t offset;
|
||
|
int flags;
|
||
|
|
||
|
char *name;
|
||
|
};
|
||
|
|
||
|
/* Create a pm_kernel_t. */
|
||
|
int pm_kernel_create(pm_kernel_t **ker_out);
|
||
|
|
||
|
#define pm_kernel_pagesize(ker) ((ker)->pagesize)
|
||
|
|
||
|
/* Get a list of probably-existing PIDs (returned through *pids_out).
|
||
|
* Length of the array (in sizeof(pid_t) units) is returned through *len.
|
||
|
* The array should be freed by the caller. */
|
||
|
int pm_kernel_pids(pm_kernel_t *ker, pid_t **pids_out, size_t *len);
|
||
|
|
||
|
/* Get the map count (from /proc/kpagecount) of a physical frame.
|
||
|
* The count is returned through *count_out. */
|
||
|
int pm_kernel_count(pm_kernel_t *ker, uint64_t pfn, uint64_t *count_out);
|
||
|
|
||
|
/* Get the page flags (from /proc/kpageflags) of a physical frame.
|
||
|
* The count is returned through *flags_out. */
|
||
|
int pm_kernel_flags(pm_kernel_t *ker, uint64_t pfn, uint64_t *flags_out);
|
||
|
|
||
|
#define PM_PAGE_LOCKED (1 << 0)
|
||
|
#define PM_PAGE_ERROR (1 << 1)
|
||
|
#define PM_PAGE_REFERENCED (1 << 2)
|
||
|
#define PM_PAGE_UPTODATE (1 << 3)
|
||
|
#define PM_PAGE_DIRTY (1 << 4)
|
||
|
#define PM_PAGE_LRU (1 << 5)
|
||
|
#define PM_PAGE_ACTIVE (1 << 6)
|
||
|
#define PM_PAGE_SLAB (1 << 7)
|
||
|
#define PM_PAGE_WRITEBACK (1 << 8)
|
||
|
#define PM_PAGE_RECLAIM (1 << 9)
|
||
|
#define PM_PAGE_BUDDY (1 << 10)
|
||
|
|
||
|
/* for kernels >= 2.6.31 */
|
||
|
#define PM_PAGE_MMAP (1 << 11)
|
||
|
#define PM_PAGE_ANON (1 << 12)
|
||
|
#define PM_PAGE_SWAPCACHE (1 << 13)
|
||
|
#define PM_PAGE_SWAPBACKED (1 << 14)
|
||
|
#define PM_PAGE_COMPOUND_HEAD (1 << 15)
|
||
|
#define PM_PAGE_COMPOUND_TAIL (1 << 16)
|
||
|
#define PM_PAGE_HUGE (1 << 17)
|
||
|
#define PM_PAGE_UNEVICTABLE (1 << 18)
|
||
|
#define PM_PAGE_HWPOISON (1 << 19)
|
||
|
#define PM_PAGE_NOPAGE (1 << 20)
|
||
|
|
||
|
/* for kernels >= 2.6.32 */
|
||
|
#define PM_PAGE_KSM (1 << 21)
|
||
|
|
||
|
/* for kernels >= 3.4 */
|
||
|
#define PM_PAGE_THP (1 << 22)
|
||
|
|
||
|
/* Destroy a pm_kernel_t. */
|
||
|
int pm_kernel_destroy(pm_kernel_t *ker);
|
||
|
|
||
|
/* Get the PID of a pm_process_t. */
|
||
|
#define pm_process_pid(proc) ((proc)->pid)
|
||
|
|
||
|
/* Create a pm_process_t and returns it through *proc_out.
|
||
|
* Takes a pm_kernel_t, and the PID of the process. */
|
||
|
int pm_process_create(pm_kernel_t *ker, pid_t pid, pm_process_t **proc_out);
|
||
|
|
||
|
/* Get the total memory usage of a process and store in *usage_out. */
|
||
|
int pm_process_usage(pm_process_t *proc, pm_memusage_t *usage_out);
|
||
|
|
||
|
/* Get the total memory usage of a process and store in *usage_out, only
|
||
|
* counting pages with specified flags. */
|
||
|
int pm_process_usage_flags(pm_process_t *proc, pm_memusage_t *usage_out,
|
||
|
uint64_t flags_mask, uint64_t required_flags);
|
||
|
|
||
|
/* Get the working set of a process (if ws_out != NULL), and reset it
|
||
|
* (if reset != 0). */
|
||
|
int pm_process_workingset(pm_process_t *proc, pm_memusage_t *ws_out, int reset);
|
||
|
|
||
|
/* Get the PFNs corresponding to a range of virtual addresses.
|
||
|
* The array of PFNs is returned through *range_out, and the caller has the
|
||
|
* responsibility to free it. */
|
||
|
int pm_process_pagemap_range(pm_process_t *proc,
|
||
|
uint64_t low, uint64_t hi,
|
||
|
uint64_t **range_out, size_t *len);
|
||
|
|
||
|
#define _BITS(x, offset, bits) (((x) >> offset) & ((1LL << (bits)) - 1))
|
||
|
|
||
|
#define PM_PAGEMAP_PRESENT(x) (_BITS(x, 63, 1))
|
||
|
#define PM_PAGEMAP_SWAPPED(x) (_BITS(x, 62, 1))
|
||
|
#define PM_PAGEMAP_SHIFT(x) (_BITS(x, 55, 6))
|
||
|
#define PM_PAGEMAP_PFN(x) (_BITS(x, 0, 55))
|
||
|
#define PM_PAGEMAP_SWAP_OFFSET(x) (_BITS(x, 5, 50))
|
||
|
#define PM_PAGEMAP_SWAP_TYPE(x) (_BITS(x, 0, 5))
|
||
|
|
||
|
/* Get the maps in the virtual address space of this process.
|
||
|
* Returns an array of pointers to pm_map_t through *maps.
|
||
|
* The array should be freed by the caller, but the maps should not be
|
||
|
* modified or destroyed. */
|
||
|
int pm_process_maps(pm_process_t *proc, pm_map_t ***maps_out, size_t *len);
|
||
|
|
||
|
/* Destroy a pm_process_t. */
|
||
|
int pm_process_destroy(pm_process_t *proc);
|
||
|
|
||
|
/* Get the name, flags, start/end address, or offset of a map. */
|
||
|
#define pm_map_name(map) ((map)->name)
|
||
|
#define pm_map_flags(map) ((map)->flags)
|
||
|
#define PM_MAP_READ 1
|
||
|
#define PM_MAP_WRITE 2
|
||
|
#define PM_MAP_EXEC 4
|
||
|
#define PM_MAP_PERMISSIONS (PM_MAP_READ | PM_MAP_WRITE | PM_MAP_EXEC)
|
||
|
#define pm_map_start(map) ((map)->start)
|
||
|
#define pm_map_end(map) ((map)->end)
|
||
|
#define pm_map_offset(map) ((map)->offset)
|
||
|
|
||
|
/* Get the PFNs of the pages in the virtual address space of this map.
|
||
|
* Array of PFNs is returned through *pagemap_out, and should be freed by the
|
||
|
* caller. */
|
||
|
int pm_map_pagemap(pm_map_t *map, uint64_t **pagemap_out, size_t *len);
|
||
|
|
||
|
/* Get the memory usage of this map alone. */
|
||
|
int pm_map_usage(pm_map_t *map, pm_memusage_t *usage_out);
|
||
|
|
||
|
/* Get the memory usage of this map alone, only counting pages with specified
|
||
|
* flags. */
|
||
|
int pm_map_usage_flags(pm_map_t *map, pm_memusage_t *usage_out,
|
||
|
uint64_t flags_mask, uint64_t required_flags);
|
||
|
|
||
|
/* Get the working set of this map alone. */
|
||
|
int pm_map_workingset(pm_map_t *map, pm_memusage_t *ws_out);
|
||
|
|
||
|
__END_DECLS
|
||
|
|
||
|
#endif
|