Line data Source code
1 : /**
2 : Copyright (c) 2020-2022 Roman Katuntsev <sbkarr@stappler.org>
3 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
4 :
5 : Permission is hereby granted, free of charge, to any person obtaining a copy
6 : of this software and associated documentation files (the "Software"), to deal
7 : in the Software without restriction, including without limitation the rights
8 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 : copies of the Software, and to permit persons to whom the Software is
10 : furnished to do so, subject to the following conditions:
11 :
12 : The above copyright notice and this permission notice shall be included in
13 : all copies or substantial portions of the Software.
14 :
15 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 : THE SOFTWARE.
22 : **/
23 :
24 : #include "SPMemPoolInterface.h"
25 : #include "SPMemPoolApi.h"
26 :
27 : #if MODULE_STAPPLER_APR
28 : #define SP_APR_EXPORT SP_EXTERN_C
29 : #else
30 : #define SP_APR_EXPORT static
31 : #endif
32 :
33 : using apr_status_t = int;
34 : using apr_size_t = size_t;
35 : using apr_abortfunc_t = int (*)(int retcode);
36 :
37 : typedef struct apr_allocator_t apr_allocator_t;
38 : typedef struct apr_pool_t apr_pool_t;
39 : typedef struct apr_thread_mutex_t apr_thread_mutex_t;
40 :
41 : typedef struct serenity_memaddr_t serenity_memaddr_t;
42 : typedef struct serenity_allocmngr_t serenity_allocmngr_t;
43 :
44 : SP_APR_EXPORT apr_status_t apr_allocator_create(apr_allocator_t **allocator) __attribute__((nonnull(1)));
45 : SP_APR_EXPORT void apr_allocator_destroy(apr_allocator_t *allocator) __attribute__((nonnull(1)));
46 : SP_APR_EXPORT void apr_allocator_mutex_set(apr_allocator_t *allocator, apr_thread_mutex_t *mutex) __attribute__((nonnull(1)));
47 : SP_APR_EXPORT void apr_allocator_owner_set(apr_allocator_t *allocator, apr_pool_t *pool) __attribute__((nonnull(1)));
48 : SP_APR_EXPORT apr_pool_t * apr_allocator_owner_get(apr_allocator_t *allocator) __attribute__((nonnull(1)));
49 : SP_APR_EXPORT void apr_allocator_max_free_set(apr_allocator_t *allocator, apr_size_t size) __attribute__((nonnull(1)));
50 :
51 : SP_APR_EXPORT void apr_pool_initialize();
52 : SP_APR_EXPORT void apr_pool_terminate();
53 :
54 : SP_APR_EXPORT apr_status_t apr_pool_create_unmanaged_ex(apr_pool_t **newpool,
55 : apr_abortfunc_t abort_fn, apr_allocator_t *allocator) __attribute__((nonnull(1)));
56 :
57 : SP_APR_EXPORT apr_status_t apr_pool_create_ex(apr_pool_t **newpool, apr_pool_t *parent,
58 : apr_abortfunc_t abort_fn, apr_allocator_t *allocator) __attribute__((nonnull(1)));
59 :
60 : SP_APR_EXPORT void apr_pool_tag(apr_pool_t *pool, const char *tag) __attribute__((nonnull(1)));
61 : SP_APR_EXPORT void apr_pool_destroy(apr_pool_t *p) __attribute__((nonnull(1)));
62 : SP_APR_EXPORT void apr_pool_clear(apr_pool_t *p) __attribute__((nonnull(1)));
63 : SP_APR_EXPORT void *apr_palloc(apr_pool_t *p, apr_size_t size) __attribute__((alloc_size(2))) __attribute__((nonnull(1)));
64 :
65 : SP_APR_EXPORT void apr_pool_cleanup_kill(apr_pool_t *p, const void *data,
66 : apr_status_t (*cleanup)(void *)) __attribute__((nonnull(3)));
67 :
68 : SP_APR_EXPORT apr_status_t apr_pool_cleanup_null(void *data);
69 :
70 : SP_APR_EXPORT void apr_pool_cleanup_register( apr_pool_t *p, const void *data,
71 : apr_status_t (*plain_cleanup)(void *), apr_status_t (*child_cleanup)(void *)) __attribute__((nonnull(3,4)));
72 :
73 : SP_APR_EXPORT void apr_pool_pre_cleanup_register( apr_pool_t *p, const void *data,
74 : apr_status_t (*plain_cleanup)(void *)) __attribute__((nonnull(3)));
75 :
76 : SP_APR_EXPORT apr_status_t apr_pool_userdata_set(const void *data, const char *key,
77 : apr_status_t (*cleanup)(void *), apr_pool_t *pool) __attribute__((nonnull(2,4)));
78 :
79 : SP_APR_EXPORT apr_status_t apr_pool_userdata_setn(const void *data, const char *key,
80 : apr_status_t (*cleanup)(void *), apr_pool_t *pool) __attribute__((nonnull(2,4)));
81 :
82 : SP_APR_EXPORT apr_status_t apr_pool_userdata_get(void **data, const char *key, apr_pool_t *pool) __attribute__((nonnull(1,2,3)));
83 :
84 : SP_APR_EXPORT apr_allocator_t *apr_pool_allocator_get(apr_pool_t *pool) __attribute__((nonnull(1)));
85 :
86 : SP_APR_EXPORT void * apr_pmemdup(apr_pool_t *p, const void *m, apr_size_t n) __attribute__((alloc_size(3)));
87 : SP_APR_EXPORT char * apr_pstrdup(apr_pool_t *p, const char *s);
88 :
89 : SP_APR_EXPORT apr_thread_mutex_t *apr_allocator_mutex_get(apr_allocator_t *allocator) __attribute__((nonnull(1)));
90 :
91 : namespace STAPPLER_VERSIONIZED stappler::mempool::apr {
92 :
93 : using pool_t = apr_pool_t;
94 : using status_t = apr_status_t;
95 : using allocator_t = apr_allocator_t;
96 : using cleanup_fn = status_t(*)(void *);
97 :
98 : }
99 :
100 : namespace STAPPLER_VERSIONIZED stappler::mempool::apr::allocator {
101 :
102 0 : SPUNUSED static allocator_t *create() {
103 0 : allocator_t *ret = nullptr;
104 0 : apr_allocator_create(&ret);
105 0 : return ret;
106 : }
107 :
108 0 : SPUNUSED static allocator_t *create(void *mutex) {
109 0 : if (!mutex) {
110 0 : abort();
111 : }
112 0 : allocator_t *ret = nullptr;
113 0 : apr_allocator_create(&ret);
114 0 : apr_allocator_mutex_set(ret, (apr_thread_mutex_t *)mutex);
115 0 : return ret;
116 : }
117 :
118 0 : SPUNUSED static void destroy(allocator_t *alloc) {
119 0 : apr_allocator_destroy(alloc);
120 0 : }
121 0 : SPUNUSED static void owner_set(allocator_t *alloc, pool_t *pool) {
122 0 : apr_allocator_owner_set(alloc, pool);
123 0 : }
124 0 : SPUNUSED static pool_t * owner_get(allocator_t *alloc) {
125 0 : return apr_allocator_owner_get(alloc);
126 : }
127 0 : SPUNUSED static void max_free_set(allocator_t *alloc, size_t size) {
128 0 : apr_allocator_max_free_set(alloc, size);
129 0 : }
130 :
131 : }
132 :
133 :
134 : namespace STAPPLER_VERSIONIZED stappler::mempool::apr::pool {
135 :
136 : struct wrapper_pool_t {
137 : apr_pool_t *parent;
138 : apr_pool_t *child;
139 : apr_pool_t *sibling;
140 : apr_pool_t **ref;
141 : void *cleanups;
142 : void *free_cleanups;
143 : apr_allocator_t *allocator;
144 : struct process_chain *subprocesses;
145 : apr_abortfunc_t abort_fn;
146 : void *user_data;
147 : const char *tag;
148 : };
149 :
150 : static custom::AllocManager *allocmngr_get(pool_t *pool);
151 :
152 0 : SPUNUSED static void initialize() {
153 0 : apr_pool_initialize();
154 0 : }
155 :
156 0 : SPUNUSED static void terminate() {
157 0 : apr_pool_terminate();
158 0 : }
159 :
160 0 : SPUNUSED static pool_t *create() {
161 0 : pool_t *ret = nullptr;
162 0 : apr_pool_create_unmanaged_ex(&ret, NULL, NULL);
163 0 : return ret;
164 : }
165 :
166 0 : SPUNUSED static pool_t *create(apr_allocator_t *alloc) {
167 0 : pool_t *ret = nullptr;
168 0 : apr_pool_create_unmanaged_ex(&ret, NULL, alloc);
169 0 : return ret;
170 : }
171 :
172 0 : SPUNUSED static pool_t *create(pool_t *p) {
173 0 : pool_t *ret = nullptr;
174 0 : if (!p) {
175 0 : apr_pool_create_ex(&ret, nullptr, nullptr, nullptr);
176 : } else {
177 0 : apr_pool_create_ex(&ret, p, nullptr, nullptr);
178 : }
179 0 : return ret;
180 : }
181 :
182 0 : SPUNUSED static pool_t *createTagged(const char *tag) {
183 0 : auto ret = create();
184 0 : apr_pool_tag(ret, tag);
185 0 : return ret;
186 : }
187 :
188 0 : SPUNUSED static pool_t *createTagged(pool_t *p, const char *tag) {
189 0 : auto ret = create(p);
190 0 : apr_pool_tag(ret, tag);
191 0 : return ret;
192 : }
193 :
194 0 : SPUNUSED static void destroy(pool_t *p) {
195 0 : apr_pool_destroy(p);
196 0 : }
197 :
198 0 : SPUNUSED static void clear(pool_t *p) {
199 0 : apr_pool_clear(p);
200 0 : }
201 :
202 0 : SPUNUSED static void *alloc(pool_t *p, size_t &size) {
203 0 : if (auto mngr = allocmngr_get(p)) {
204 0 : if (size >= custom::BlockThreshold) {
205 0 : return mngr->alloc(size, [] (void *p, size_t s) { return apr_palloc((pool_t *)p, s); });
206 : } else {
207 0 : mngr->increment_alloc(size);
208 : }
209 : }
210 0 : return apr_palloc(p, size);
211 : }
212 :
213 0 : SPUNUSED static void free(pool_t *p, void *ptr, size_t size) {
214 0 : if (size >= custom::BlockThreshold) {
215 0 : if (auto m = allocmngr_get(p)) {
216 0 : return m->free(ptr, size, [] (void *p, size_t s) { return apr_palloc((pool_t *)p, s); });
217 : }
218 : }
219 : }
220 :
221 0 : SPUNUSED static void *palloc(pool_t *p, size_t size) {
222 0 : return pool::alloc(p, size);
223 : }
224 :
225 0 : SPUNUSED static void *calloc(pool_t *p, size_t count, size_t eltsize) {
226 0 : size_t s = count * eltsize;
227 0 : auto ptr = pool::alloc(p, s);
228 0 : memset(ptr, 0, s);
229 0 : return ptr;
230 : }
231 :
232 0 : SPUNUSED static void cleanup_kill(pool_t *p, void *ptr, status_t(*cb)(void *)) {
233 0 : apr_pool_cleanup_kill(p, ptr, cb);
234 0 : }
235 :
236 : struct __CleaupData {
237 : void *data;
238 : pool_t *pool;
239 : status_t(*callback)(void *);
240 :
241 0 : static status_t doCleanup(void *data) {
242 0 : if (auto d = (__CleaupData *)data) {
243 0 : memory::pool::push((memory::pool_t *)d->pool);
244 0 : d->callback(d->data);
245 0 : memory::pool::pop();
246 : }
247 0 : return 0;
248 : }
249 : };
250 :
251 0 : SPUNUSED static void cleanup_register(pool_t *p, void *ptr, status_t(*cb)(void *)) {
252 0 : auto data = (__CleaupData *)apr_palloc(p, sizeof(__CleaupData));
253 0 : data->data = ptr;
254 0 : data->pool = p;
255 0 : data->callback = cb;
256 0 : apr_pool_cleanup_register(p, data, &__CleaupData::doCleanup, apr_pool_cleanup_null);
257 0 : }
258 :
259 0 : SPUNUSED static void pre_cleanup_register(pool_t *p, void *ptr, status_t(*cb)(void *)) {
260 0 : auto data = (__CleaupData *)apr_palloc(p, sizeof(__CleaupData));
261 0 : data->data = ptr;
262 0 : data->pool = p;
263 0 : data->callback = cb;
264 0 : apr_pool_pre_cleanup_register(p, data, &__CleaupData::doCleanup);
265 0 : }
266 :
267 0 : SPUNUSED static status_t userdata_set(const void *data, const char *key, cleanup_fn cb, pool_t *pool) {
268 0 : return apr_pool_userdata_set(data, key, cb, pool);
269 : }
270 :
271 0 : SPUNUSED static status_t userdata_setn(const void *data, const char *key, cleanup_fn cb, pool_t *pool) {
272 0 : return apr_pool_userdata_setn(data, key, cb, pool);
273 : }
274 :
275 0 : SPUNUSED static status_t userdata_get(void **data, const char *key, pool_t *pool) {
276 0 : return apr_pool_userdata_get(data, key, pool);
277 : }
278 :
279 0 : SPUNUSED static size_t get_allocated_bytes(pool_t *p) {
280 0 : return allocmngr_get(p)->get_alloc();
281 : }
282 0 : SPUNUSED static size_t get_return_bytes(pool_t *p) {
283 0 : return allocmngr_get(p)->get_return();
284 : }
285 :
286 0 : SPUNUSED static allocator_t *get_allocator(pool_t *p) {
287 0 : return apr_pool_allocator_get(p);
288 : }
289 :
290 0 : SPUNUSED static void *pmemdup(pool_t *a, const void *m, size_t n) { return apr_pmemdup(a, m, n); }
291 0 : SPUNUSED static char *pstrdup(pool_t *a, const char *s) { return apr_pstrdup(a, s); }
292 :
293 0 : SPUNUSED static void setPoolInfo(pool_t *p, uint32_t tag, const void *ptr) {
294 0 : if (auto mngr = allocmngr_get(p)) {
295 0 : if (tag > mngr->tag) {
296 0 : mngr->tag = tag;
297 : }
298 0 : mngr->ptr = ptr;
299 : }
300 0 : }
301 :
302 0 : SPUNUSED static bool isThreadSafeAsParent(pool_t *pool) {
303 0 : if (auto a = apr_pool_allocator_get(pool)) {
304 0 : return apr_allocator_mutex_get(a) != nullptr;
305 : }
306 0 : return false;
307 : }
308 :
309 0 : static custom::AllocManager *allocmngr_get(pool_t *pool) {
310 0 : return nullptr;
311 :
312 : /*wrapper_pool_t *p = (wrapper_pool_t *)pool;
313 : if (p->tag) {
314 : auto m = (custom::AllocManager *)p->tag;
315 : if (m->pool == pool) {
316 : return m;
317 : }
318 : }
319 :
320 : auto m = (custom::AllocManager *)apr_palloc(pool, sizeof(custom::AllocManager *));
321 : m->pool = pool;
322 : m->name = p->tag;
323 :
324 : cleanup_register(pool, m, [] (void *ptr) {
325 : auto m = (custom::AllocManager *)ptr;
326 :
327 : wrapper_pool_t *p = (wrapper_pool_t *)m->pool;
328 : p->tag = m->name;
329 : return 0;
330 : });
331 :
332 : p->tag = (const char *)m;
333 : return m;*/
334 : }
335 :
336 0 : SPUNUSED static const char *get_tag(pool_t *pool) {
337 0 : wrapper_pool_t *p = (wrapper_pool_t *)pool;
338 0 : if (p->tag) {
339 0 : auto m = (custom::AllocManager *)p->tag;
340 0 : if (m->pool == pool) {
341 0 : return m->name;
342 : }
343 0 : return p->tag;
344 : }
345 0 : return NULL;
346 : }
347 :
348 : }
349 :
350 : #ifndef MODULE_STAPPLER_APR
351 :
352 0 : SP_APR_EXPORT apr_status_t apr_allocator_create(apr_allocator_t **allocator) { return 0; }
353 0 : SP_APR_EXPORT void apr_allocator_destroy(apr_allocator_t *allocator) { }
354 0 : SP_APR_EXPORT void apr_allocator_mutex_set(apr_allocator_t *allocator, apr_thread_mutex_t *mutex) { }
355 0 : SP_APR_EXPORT void apr_allocator_owner_set(apr_allocator_t *allocator, apr_pool_t *pool) { }
356 0 : SP_APR_EXPORT apr_pool_t * apr_allocator_owner_get(apr_allocator_t *allocator) { return nullptr; }
357 0 : SP_APR_EXPORT void apr_allocator_max_free_set(apr_allocator_t *allocator, apr_size_t size) { }
358 :
359 0 : SP_APR_EXPORT void apr_pool_initialize() { }
360 0 : SP_APR_EXPORT void apr_pool_terminate() { }
361 :
362 0 : SP_APR_EXPORT apr_status_t apr_pool_create_unmanaged_ex(apr_pool_t **newpool,
363 0 : apr_abortfunc_t abort_fn, apr_allocator_t *allocator) { return 0; }
364 :
365 0 : SP_APR_EXPORT apr_status_t apr_pool_create_ex(apr_pool_t **newpool, apr_pool_t *parent,
366 0 : apr_abortfunc_t abort_fn, apr_allocator_t *allocator) { return 0; }
367 :
368 0 : SP_APR_EXPORT void apr_pool_tag(apr_pool_t *pool, const char *tag) { }
369 0 : SP_APR_EXPORT void apr_pool_destroy(apr_pool_t *p) { }
370 0 : SP_APR_EXPORT void apr_pool_clear(apr_pool_t *p) { }
371 0 : SP_APR_EXPORT void *apr_palloc(apr_pool_t *p, apr_size_t size) { return nullptr; }
372 :
373 0 : SP_APR_EXPORT void apr_pool_cleanup_kill(apr_pool_t *p, const void *data,
374 0 : apr_status_t (*cleanup)(void *)) { }
375 :
376 0 : SP_APR_EXPORT apr_status_t apr_pool_cleanup_null(void *data) { return 0; }
377 :
378 0 : SP_APR_EXPORT void apr_pool_cleanup_register( apr_pool_t *p, const void *data,
379 0 : apr_status_t (*plain_cleanup)(void *), apr_status_t (*child_cleanup)(void *)) { }
380 :
381 0 : SP_APR_EXPORT void apr_pool_pre_cleanup_register( apr_pool_t *p, const void *data,
382 0 : apr_status_t (*plain_cleanup)(void *)) { }
383 :
384 0 : SP_APR_EXPORT apr_status_t apr_pool_userdata_set(const void *data, const char *key,
385 0 : apr_status_t (*cleanup)(void *), apr_pool_t *pool) { return 0; }
386 :
387 0 : SP_APR_EXPORT apr_status_t apr_pool_userdata_setn(const void *data, const char *key,
388 0 : apr_status_t (*cleanup)(void *), apr_pool_t *pool) { return 0; }
389 :
390 0 : SP_APR_EXPORT apr_status_t apr_pool_userdata_get(void **data, const char *key, apr_pool_t *pool) { return 0; }
391 :
392 0 : SP_APR_EXPORT apr_allocator_t *apr_pool_allocator_get(apr_pool_t *pool) { return nullptr; }
393 :
394 0 : SP_APR_EXPORT void * apr_pmemdup(apr_pool_t *p, const void *m, apr_size_t n) { return nullptr; }
395 0 : SP_APR_EXPORT char * apr_pstrdup(apr_pool_t *p, const char *s) { return nullptr; }
396 :
397 0 : SP_APR_EXPORT apr_thread_mutex_t *apr_allocator_mutex_get(apr_allocator_t *allocator) { return nullptr; }
398 :
399 : #endif
|