xref: /src/contrib/jemalloc/include/jemalloc/internal/hpa.h (revision c43cad87172039ccf38172129c79755ea79e6102)
1 #ifndef JEMALLOC_INTERNAL_HPA_H
2 #define JEMALLOC_INTERNAL_HPA_H
3 
4 #include "jemalloc/internal/exp_grow.h"
5 #include "jemalloc/internal/hpa_hooks.h"
6 #include "jemalloc/internal/hpa_opts.h"
7 #include "jemalloc/internal/pai.h"
8 #include "jemalloc/internal/psset.h"
9 
10 typedef struct hpa_central_s hpa_central_t;
11 struct hpa_central_s {
12 	/*
13 	 * The mutex guarding most of the operations on the central data
14 	 * structure.
15 	 */
16 	malloc_mutex_t mtx;
17 	/*
18 	 * Guards expansion of eden.  We separate this from the regular mutex so
19 	 * that cheaper operations can still continue while we're doing the OS
20 	 * call.
21 	 */
22 	malloc_mutex_t grow_mtx;
23 	/*
24 	 * Either NULL (if empty), or some integer multiple of a
25 	 * hugepage-aligned number of hugepages.  We carve them off one at a
26 	 * time to satisfy new pageslab requests.
27 	 *
28 	 * Guarded by grow_mtx.
29 	 */
30 	void *eden;
31 	size_t eden_len;
32 	/* Source for metadata. */
33 	base_t *base;
34 	/* Number of grow operations done on this hpa_central_t. */
35 	uint64_t age_counter;
36 
37 	/* The HPA hooks. */
38 	hpa_hooks_t hooks;
39 };
40 
41 typedef struct hpa_shard_nonderived_stats_s hpa_shard_nonderived_stats_t;
42 struct hpa_shard_nonderived_stats_s {
43 	/*
44 	 * The number of times we've purged within a hugepage.
45 	 *
46 	 * Guarded by mtx.
47 	 */
48 	uint64_t npurge_passes;
49 	/*
50 	 * The number of individual purge calls we perform (which should always
51 	 * be bigger than npurge_passes, since each pass purges at least one
52 	 * extent within a hugepage.
53 	 *
54 	 * Guarded by mtx.
55 	 */
56 	uint64_t npurges;
57 
58 	/*
59 	 * The number of times we've hugified a pageslab.
60 	 *
61 	 * Guarded by mtx.
62 	 */
63 	uint64_t nhugifies;
64 	/*
65 	 * The number of times we've dehugified a pageslab.
66 	 *
67 	 * Guarded by mtx.
68 	 */
69 	uint64_t ndehugifies;
70 };
71 
72 /* Completely derived; only used by CTL. */
73 typedef struct hpa_shard_stats_s hpa_shard_stats_t;
74 struct hpa_shard_stats_s {
75 	psset_stats_t psset_stats;
76 	hpa_shard_nonderived_stats_t nonderived_stats;
77 };
78 
79 typedef struct hpa_shard_s hpa_shard_t;
80 struct hpa_shard_s {
81 	/*
82 	 * pai must be the first member; we cast from a pointer to it to a
83 	 * pointer to the hpa_shard_t.
84 	 */
85 	pai_t pai;
86 
87 	/* The central allocator we get our hugepages from. */
88 	hpa_central_t *central;
89 	/* Protects most of this shard's state. */
90 	malloc_mutex_t mtx;
91 	/*
92 	 * Guards the shard's access to the central allocator (preventing
93 	 * multiple threads operating on this shard from accessing the central
94 	 * allocator).
95 	 */
96 	malloc_mutex_t grow_mtx;
97 	/* The base metadata allocator. */
98 	base_t *base;
99 
100 	/*
101 	 * This edata cache is the one we use when allocating a small extent
102 	 * from a pageslab.  The pageslab itself comes from the centralized
103 	 * allocator, and so will use its edata_cache.
104 	 */
105 	edata_cache_fast_t ecf;
106 
107 	psset_t psset;
108 
109 	/*
110 	 * How many grow operations have occurred.
111 	 *
112 	 * Guarded by grow_mtx.
113 	 */
114 	uint64_t age_counter;
115 
116 	/* The arena ind we're associated with. */
117 	unsigned ind;
118 
119 	/*
120 	 * Our emap.  This is just a cache of the emap pointer in the associated
121 	 * hpa_central.
122 	 */
123 	emap_t *emap;
124 
125 	/* The configuration choices for this hpa shard. */
126 	hpa_shard_opts_t opts;
127 
128 	/*
129 	 * How many pages have we started but not yet finished purging in this
130 	 * hpa shard.
131 	 */
132 	size_t npending_purge;
133 
134 	/*
135 	 * Those stats which are copied directly into the CTL-centric hpa shard
136 	 * stats.
137 	 */
138 	hpa_shard_nonderived_stats_t stats;
139 
140 	/*
141 	 * Last time we performed purge on this shard.
142 	 */
143 	nstime_t last_purge;
144 };
145 
146 /*
147  * Whether or not the HPA can be used given the current configuration.  This is
148  * is not necessarily a guarantee that it backs its allocations by hugepages,
149  * just that it can function properly given the system it's running on.
150  */
151 bool hpa_supported();
152 bool hpa_central_init(hpa_central_t *central, base_t *base, const hpa_hooks_t *hooks);
153 bool hpa_shard_init(hpa_shard_t *shard, hpa_central_t *central, emap_t *emap,
154     base_t *base, edata_cache_t *edata_cache, unsigned ind,
155     const hpa_shard_opts_t *opts);
156 
157 void hpa_shard_stats_accum(hpa_shard_stats_t *dst, hpa_shard_stats_t *src);
158 void hpa_shard_stats_merge(tsdn_t *tsdn, hpa_shard_t *shard,
159     hpa_shard_stats_t *dst);
160 
161 /*
162  * Notify the shard that we won't use it for allocations much longer.  Due to
163  * the possibility of races, we don't actually prevent allocations; just flush
164  * and disable the embedded edata_cache_small.
165  */
166 void hpa_shard_disable(tsdn_t *tsdn, hpa_shard_t *shard);
167 void hpa_shard_destroy(tsdn_t *tsdn, hpa_shard_t *shard);
168 
169 void hpa_shard_set_deferral_allowed(tsdn_t *tsdn, hpa_shard_t *shard,
170     bool deferral_allowed);
171 void hpa_shard_do_deferred_work(tsdn_t *tsdn, hpa_shard_t *shard);
172 
173 /*
174  * We share the fork ordering with the PA and arena prefork handling; that's why
175  * these are 3 and 4 rather than 0 and 1.
176  */
177 void hpa_shard_prefork3(tsdn_t *tsdn, hpa_shard_t *shard);
178 void hpa_shard_prefork4(tsdn_t *tsdn, hpa_shard_t *shard);
179 void hpa_shard_postfork_parent(tsdn_t *tsdn, hpa_shard_t *shard);
180 void hpa_shard_postfork_child(tsdn_t *tsdn, hpa_shard_t *shard);
181 
182 #endif /* JEMALLOC_INTERNAL_HPA_H */
183