1 /*
2 * Boilerplate code used for testing extent hooks via interception and
3 * passthrough.
4 */
5
6 static void *extent_alloc_hook(extent_hooks_t *extent_hooks, void *new_addr,
7 size_t size, size_t alignment, bool *zero, bool *commit,
8 unsigned arena_ind);
9 static bool extent_dalloc_hook(extent_hooks_t *extent_hooks, void *addr,
10 size_t size, bool committed, unsigned arena_ind);
11 static bool extent_commit_hook(extent_hooks_t *extent_hooks, void *addr,
12 size_t size, size_t offset, size_t length, unsigned arena_ind);
13 static bool extent_decommit_hook(extent_hooks_t *extent_hooks, void *addr,
14 size_t size, size_t offset, size_t length, unsigned arena_ind);
15 static bool extent_purge_lazy_hook(extent_hooks_t *extent_hooks, void *addr,
16 size_t size, size_t offset, size_t length, unsigned arena_ind);
17 static bool extent_purge_forced_hook(extent_hooks_t *extent_hooks,
18 void *addr, size_t size, size_t offset, size_t length, unsigned arena_ind);
19 static bool extent_split_hook(extent_hooks_t *extent_hooks, void *addr,
20 size_t size, size_t size_a, size_t size_b, bool committed,
21 unsigned arena_ind);
22 static bool extent_merge_hook(extent_hooks_t *extent_hooks, void *addr_a,
23 size_t size_a, void *addr_b, size_t size_b, bool committed,
24 unsigned arena_ind);
25
26 static extent_hooks_t *default_hooks;
27 static extent_hooks_t hooks = {
28 extent_alloc_hook,
29 extent_dalloc_hook,
30 extent_commit_hook,
31 extent_decommit_hook,
32 extent_purge_lazy_hook,
33 extent_purge_forced_hook,
34 extent_split_hook,
35 extent_merge_hook
36 };
37
38 /* Control whether hook functions pass calls through to default hooks. */
39 static bool try_alloc = true;
40 static bool try_dalloc = true;
41 static bool try_commit = true;
42 static bool try_decommit = true;
43 static bool try_purge_lazy = true;
44 static bool try_purge_forced = true;
45 static bool try_split = true;
46 static bool try_merge = true;
47
48 /* Set to false prior to operations, then introspect after operations. */
49 static bool called_alloc;
50 static bool called_dalloc;
51 static bool called_commit;
52 static bool called_decommit;
53 static bool called_purge_lazy;
54 static bool called_purge_forced;
55 static bool called_split;
56 static bool called_merge;
57
58 /* Set to false prior to operations, then introspect after operations. */
59 static bool did_alloc;
60 static bool did_dalloc;
61 static bool did_commit;
62 static bool did_decommit;
63 static bool did_purge_lazy;
64 static bool did_purge_forced;
65 static bool did_split;
66 static bool did_merge;
67
68 #if 0
69 # define TRACE_HOOK(fmt, ...) malloc_printf(fmt, __VA_ARGS__)
70 #else
71 # define TRACE_HOOK(fmt, ...)
72 #endif
73
74 static void *
extent_alloc_hook(extent_hooks_t * extent_hooks,void * new_addr,size_t size,size_t alignment,bool * zero,bool * commit,unsigned arena_ind)75 extent_alloc_hook(extent_hooks_t *extent_hooks, void *new_addr, size_t size,
76 size_t alignment, bool *zero, bool *commit, unsigned arena_ind)
77 {
78 void *ret;
79
80 TRACE_HOOK("%s(extent_hooks=%p, new_addr=%p, size=%zu, alignment=%zu, "
81 "*zero=%s, *commit=%s, arena_ind=%u)\n", __func__, extent_hooks,
82 new_addr, size, alignment, *zero ? "true" : "false", *commit ?
83 "true" : "false", arena_ind);
84 assert_ptr_eq(extent_hooks, &hooks,
85 "extent_hooks should be same as pointer used to set hooks");
86 assert_ptr_eq(extent_hooks->alloc, extent_alloc_hook,
87 "Wrong hook function");
88 called_alloc = true;
89 if (!try_alloc)
90 return (NULL);
91 ret = default_hooks->alloc(default_hooks, new_addr, size, alignment,
92 zero, commit, 0);
93 did_alloc = (ret != NULL);
94 return (ret);
95 }
96
97 static bool
extent_dalloc_hook(extent_hooks_t * extent_hooks,void * addr,size_t size,bool committed,unsigned arena_ind)98 extent_dalloc_hook(extent_hooks_t *extent_hooks, void *addr, size_t size,
99 bool committed, unsigned arena_ind)
100 {
101 bool err;
102
103 TRACE_HOOK("%s(extent_hooks=%p, addr=%p, size=%zu, committed=%s, "
104 "arena_ind=%u)\n", __func__, extent_hooks, addr, size, committed ?
105 "true" : "false", arena_ind);
106 assert_ptr_eq(extent_hooks, &hooks,
107 "extent_hooks should be same as pointer used to set hooks");
108 assert_ptr_eq(extent_hooks->dalloc, extent_dalloc_hook,
109 "Wrong hook function");
110 called_dalloc = true;
111 if (!try_dalloc)
112 return (true);
113 err = default_hooks->dalloc(default_hooks, addr, size, committed, 0);
114 did_dalloc = !err;
115 return (err);
116 }
117
118 static bool
extent_commit_hook(extent_hooks_t * extent_hooks,void * addr,size_t size,size_t offset,size_t length,unsigned arena_ind)119 extent_commit_hook(extent_hooks_t *extent_hooks, void *addr, size_t size,
120 size_t offset, size_t length, unsigned arena_ind)
121 {
122 bool err;
123
124 TRACE_HOOK("%s(extent_hooks=%p, addr=%p, size=%zu, offset=%zu, "
125 "length=%zu, arena_ind=%u)\n", __func__, extent_hooks, addr, size,
126 offset, length, arena_ind);
127 assert_ptr_eq(extent_hooks, &hooks,
128 "extent_hooks should be same as pointer used to set hooks");
129 assert_ptr_eq(extent_hooks->commit, extent_commit_hook,
130 "Wrong hook function");
131 called_commit = true;
132 if (!try_commit)
133 return (true);
134 err = default_hooks->commit(default_hooks, addr, size, offset, length,
135 0);
136 did_commit = !err;
137 return (err);
138 }
139
140 static bool
extent_decommit_hook(extent_hooks_t * extent_hooks,void * addr,size_t size,size_t offset,size_t length,unsigned arena_ind)141 extent_decommit_hook(extent_hooks_t *extent_hooks, void *addr, size_t size,
142 size_t offset, size_t length, unsigned arena_ind)
143 {
144 bool err;
145
146 TRACE_HOOK("%s(extent_hooks=%p, addr=%p, size=%zu, offset=%zu, "
147 "length=%zu, arena_ind=%u)\n", __func__, extent_hooks, addr, size,
148 offset, length, arena_ind);
149 assert_ptr_eq(extent_hooks, &hooks,
150 "extent_hooks should be same as pointer used to set hooks");
151 assert_ptr_eq(extent_hooks->decommit, extent_decommit_hook,
152 "Wrong hook function");
153 called_decommit = true;
154 if (!try_decommit)
155 return (true);
156 err = default_hooks->decommit(default_hooks, addr, size, offset, length,
157 0);
158 did_decommit = !err;
159 return (err);
160 }
161
162 static bool
extent_purge_lazy_hook(extent_hooks_t * extent_hooks,void * addr,size_t size,size_t offset,size_t length,unsigned arena_ind)163 extent_purge_lazy_hook(extent_hooks_t *extent_hooks, void *addr, size_t size,
164 size_t offset, size_t length, unsigned arena_ind)
165 {
166 bool err;
167
168 TRACE_HOOK("%s(extent_hooks=%p, addr=%p, size=%zu, offset=%zu, "
169 "length=%zu arena_ind=%u)\n", __func__, extent_hooks, addr, size,
170 offset, length, arena_ind);
171 assert_ptr_eq(extent_hooks, &hooks,
172 "extent_hooks should be same as pointer used to set hooks");
173 assert_ptr_eq(extent_hooks->purge_lazy, extent_purge_lazy_hook,
174 "Wrong hook function");
175 called_purge_lazy = true;
176 if (!try_purge_lazy)
177 return (true);
178 err = default_hooks->purge_lazy == NULL ||
179 default_hooks->purge_lazy(default_hooks, addr, size, offset, length,
180 0);
181 did_purge_lazy = !err;
182 return (err);
183 }
184
185 static bool
extent_purge_forced_hook(extent_hooks_t * extent_hooks,void * addr,size_t size,size_t offset,size_t length,unsigned arena_ind)186 extent_purge_forced_hook(extent_hooks_t *extent_hooks, void *addr, size_t size,
187 size_t offset, size_t length, unsigned arena_ind)
188 {
189 bool err;
190
191 TRACE_HOOK("%s(extent_hooks=%p, addr=%p, size=%zu, offset=%zu, "
192 "length=%zu arena_ind=%u)\n", __func__, extent_hooks, addr, size,
193 offset, length, arena_ind);
194 assert_ptr_eq(extent_hooks, &hooks,
195 "extent_hooks should be same as pointer used to set hooks");
196 assert_ptr_eq(extent_hooks->purge_forced, extent_purge_forced_hook,
197 "Wrong hook function");
198 called_purge_forced = true;
199 if (!try_purge_forced)
200 return (true);
201 err = default_hooks->purge_forced == NULL ||
202 default_hooks->purge_forced(default_hooks, addr, size, offset,
203 length, 0);
204 did_purge_forced = !err;
205 return (err);
206 }
207
208 static bool
extent_split_hook(extent_hooks_t * extent_hooks,void * addr,size_t size,size_t size_a,size_t size_b,bool committed,unsigned arena_ind)209 extent_split_hook(extent_hooks_t *extent_hooks, void *addr, size_t size,
210 size_t size_a, size_t size_b, bool committed, unsigned arena_ind)
211 {
212 bool err;
213
214 TRACE_HOOK("%s(extent_hooks=%p, addr=%p, size=%zu, size_a=%zu, "
215 "size_b=%zu, committed=%s, arena_ind=%u)\n", __func__, extent_hooks,
216 addr, size, size_a, size_b, committed ? "true" : "false",
217 arena_ind);
218 assert_ptr_eq(extent_hooks, &hooks,
219 "extent_hooks should be same as pointer used to set hooks");
220 assert_ptr_eq(extent_hooks->split, extent_split_hook,
221 "Wrong hook function");
222 called_split = true;
223 if (!try_split)
224 return (true);
225 err = (default_hooks->split == NULL ||
226 default_hooks->split(default_hooks, addr, size, size_a, size_b,
227 committed, 0));
228 did_split = !err;
229 return (err);
230 }
231
232 static bool
extent_merge_hook(extent_hooks_t * extent_hooks,void * addr_a,size_t size_a,void * addr_b,size_t size_b,bool committed,unsigned arena_ind)233 extent_merge_hook(extent_hooks_t *extent_hooks, void *addr_a, size_t size_a,
234 void *addr_b, size_t size_b, bool committed, unsigned arena_ind)
235 {
236 bool err;
237
238 TRACE_HOOK("%s(extent_hooks=%p, addr_a=%p, size_a=%zu, addr_b=%p "
239 "size_b=%zu, committed=%s, arena_ind=%u)\n", __func__, extent_hooks,
240 addr_a, size_a, addr_b, size_b, committed ? "true" : "false",
241 arena_ind);
242 assert_ptr_eq(extent_hooks, &hooks,
243 "extent_hooks should be same as pointer used to set hooks");
244 assert_ptr_eq(extent_hooks->merge, extent_merge_hook,
245 "Wrong hook function");
246 called_merge = true;
247 if (!try_merge)
248 return (true);
249 err = (default_hooks->merge == NULL ||
250 default_hooks->merge(default_hooks, addr_a, size_a, addr_b, size_b,
251 committed, 0));
252 did_merge = !err;
253 return (err);
254 }
255
256 static void
extent_hooks_prep(void)257 extent_hooks_prep(void)
258 {
259 size_t sz;
260
261 sz = sizeof(default_hooks);
262 assert_d_eq(mallctl("arena.0.extent_hooks", (void *)&default_hooks, &sz,
263 NULL, 0), 0, "Unexpected mallctl() error");
264 }
265