-
Notifications
You must be signed in to change notification settings - Fork 7
/
page-info.h
152 lines (124 loc) · 4.79 KB
/
page-info.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/*
* page-info.h
*/
#ifndef PAGE_INFO_H_
#define PAGE_INFO_H_
#include <stddef.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
/* page frame number: if present, the physical frame for the page */
uint64_t pfn;
/* soft-dirty set */
bool softdirty;
/* exclusively mapped, see e.g., https://patchwork.kernel.org/patch/6787921/ */
bool exclusive;
/* is a file mapping */
bool file;
/* page is swapped out */
bool swapped;
/* page is present, i.e, a physical page is allocated */
bool present;
/* if true, the kpageflags were successfully loaded, if false they were not (and are all zero) */
bool kpageflags_ok;
/* the 64-bit flag value extracted from /proc/kpageflags only if pfn is non-null */
uint64_t kpageflags;
} page_info;
/*
* Information for a number of virtually consecutive pages.
*/
typedef struct {
/* how many page_info structures are in the array pointed to by info */
size_t num_pages;
/* pointer to the array of page_info structures */
page_info *info;
} page_info_array;
typedef struct {
/* the number of pages on which this flag was set, always <= pages_available */
size_t pages_set;
/* the number of pages on which information could be obtained */
size_t pages_available;
/* the total number of pages examined, which may be greater than pages_available if
* the flag value could not be obtained for some pages (usually because the pfn is not available
* since the page is not yet present or because running as non-root.
*/
size_t pages_total;
/* the flag the values were queried for */
int flag;
} flag_count;
/**
* Examine the page info in infos to count the number of times a specified /proc/kpageflags flag was set,
* effectively giving you a ratio, so you can say "80% of the pages for this allocation are backed by
* huge pages" or whatever.
*
* The flags *must* come from kpageflags (these are not the same as those in /proc/pid/pagemap) and
* are declared in linux/kernel-page-flags.h.
*
* Ideally, the flag information is available for all the pages in the range, so you can
* say something about the entire range, but this is often not the case because (a) flags
* are not available for pages that aren't present and (b) flags are generally never available
* for non-root users. So the ratio structure indicates both the total number of pages as
* well as the number of pages for which the flag information was available.
*/
flag_count get_flag_count(page_info_array infos, int flag);
/**
* Given the case-insensitive name of a flag, return the flag number (the index of the bit
* representing this flag), or -1 if the flag is not found. The "names" of the flags are
* the same as the macro names in <linux/kernel-page-flags.h> without the KPF_ prefix.
*
* For example, the name of the transparent hugepages flag is "THP" and the corresponding
* macro is KPF_THP, and the value of this macro and returned by this method is 22.
*
* You can generate the corresponding mask value to check the flag using (1ULL << value).
*/
int flag_from_name(char const *name);
/**
* Print the info in the page_info structure to stdout.
*/
void print_info(page_info info);
/**
* Print the info in the page_info structure to the give file.
*/
void fprint_info(FILE* file, page_info info);
/**
* Print the table header that lines up with the tabluar format used by the "table" printing
* functions. Called by fprint_ratios, or you can call it yourself if you want to prefix the
* output with your own columns.
*/
void fprint_info_header(FILE *file);
/* print one info in a tabular format (as a single row) */
void fprint_info_row(FILE *file, page_info info);
/**
* Print the ratio for each flag in infos. The ratio is the number of times the flag was set over
* the total number of pages (or the total number of pages for which the information could be obtained).
*/
void fprint_ratios_noheader(FILE *file, page_info_array infos);
/*
* Print a table with one row per page from the given infos.
*/
void fprint_ratios(FILE *file, page_info_array infos);
/*
* Prints a summary of all the pages in the given array as ratios: the fraction of the time the given
* flag was set.
*/
void fprint_table(FILE *f, page_info_array infos);
/**
* Get info for a single page indicated by the given pointer (which may point anywhere in the page).
*/
page_info get_page_info(void *p);
/**
* Get information for each page in the range from start (inclusive) to end (exclusive).
*/
page_info_array get_info_for_range(void *start, void *end);
/**
* Free the memory associated with the given page_info_array. You shouldn't use it after this call.
*/
void free_info_array(page_info_array infos);
#ifdef __cplusplus
}
#endif
#endif /* PAGE_INFO_H_ */