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 :
26 : #include "SPMemFunction.h"
27 : #include "SPMemPoolApi.h"
28 :
29 : // requires libbacktrace
30 : #define DEBUG_BACKTRACE 0
31 : #define DEBUG_POOL_LIST 0
32 :
33 : #if DEBUG_BACKTRACE
34 : #include <backtrace.h>
35 : #endif
36 :
37 : namespace STAPPLER_VERSIONIZED stappler::mempool::base::pool {
38 :
39 : static constexpr size_t SP_ALLOC_STACK_SIZE = 256;
40 :
41 : static void setPoolInfo(pool_t *p, uint32_t tag, const void *ptr);
42 :
43 : class AllocStack {
44 : public:
45 : struct Info {
46 : pool_t *pool;
47 : uint32_t tag;
48 : const void *ptr;
49 : };
50 :
51 : AllocStack();
52 :
53 : pool_t *top() const;
54 : Pair<uint32_t, const void *> info() const;
55 : const Info &back() const;
56 :
57 : void push(pool_t *);
58 : void push(pool_t *, uint32_t, const void *);
59 : void pop();
60 :
61 : void foreachInfo(void *, bool(*cb)(void *, pool_t *, uint32_t, const void *));
62 :
63 : protected:
64 : template <typename T>
65 : struct stack {
66 : size_t size = 0;
67 : std::array<T, SP_ALLOC_STACK_SIZE> data;
68 :
69 : bool empty() const { return size == 0; }
70 : #if DEBUG
71 441851937 : void push(const T &t) {
72 441851937 : if (size < data.size()) {
73 441804764 : data[size] = t; ++ size;
74 : } else {
75 0 : abort();
76 : }
77 441811420 : }
78 442005115 : void pop() {
79 442005115 : if (size > 0) {
80 442075538 : -- size;
81 : } else {
82 0 : abort();
83 : }
84 442075538 : }
85 42342086 : const T &get() const {
86 42342086 : if (size == 0) {
87 0 : abort();
88 : }
89 42342086 : return data[size - 1];
90 : }
91 : #else
92 : void push(const T &t) { data[size ++] = t; }
93 : void pop() { -- size; }
94 : const T &get() const { return data[size - 1]; }
95 : #endif
96 : };
97 :
98 : stack<Info> _stack;
99 : };
100 :
101 580 : AllocStack::AllocStack() {
102 558 : _stack.push(Info{nullptr, 0, nullptr});
103 568 : }
104 :
105 42342047 : pool_t *AllocStack::top() const {
106 42342047 : return _stack.get().pool;
107 : }
108 :
109 0 : Pair<uint32_t, const void *> AllocStack::info() const {
110 0 : return pair(_stack.get().tag, _stack.get().ptr);
111 : }
112 :
113 0 : const AllocStack::Info &AllocStack::back() const {
114 0 : return _stack.get();
115 : }
116 :
117 441853286 : void AllocStack::push(pool_t *p) {
118 441853286 : if (p) {
119 441903612 : _stack.push(Info{p, 0, nullptr});
120 : } else {
121 0 : abort();
122 : }
123 442475458 : }
124 19849 : void AllocStack::push(pool_t *p, uint32_t tag, const void *ptr) {
125 19849 : if (p) {
126 19849 : _stack.push(Info{p, tag, ptr});
127 : } else {
128 0 : abort();
129 : }
130 19849 : }
131 :
132 442080943 : void AllocStack::pop() {
133 442080943 : _stack.pop();
134 442022891 : }
135 :
136 13400 : void AllocStack::foreachInfo(void *data, bool(*cb)(void *, pool_t *, uint32_t, const void *)) {
137 24850 : for (size_t i = 0; i < _stack.size; ++ i) {
138 23150 : auto &it = _stack.data[_stack.size - 1 - i];
139 23150 : if (it.pool && !cb(data, it.pool, it.tag, it.ptr)) {
140 11700 : break;
141 : }
142 : }
143 13400 : }
144 :
145 924529428 : static AllocStack &get_stack() {
146 924529428 : static thread_local AllocStack tl_stack;
147 924529406 : return tl_stack;
148 : }
149 :
150 42341943 : pool_t *acquire() {
151 42341943 : return get_stack().top();
152 : }
153 :
154 0 : Pair<uint32_t, const void *> info() {
155 0 : return get_stack().info();
156 : }
157 :
158 441998995 : void push(pool_t *p) {
159 441998995 : return get_stack().push(p);
160 : }
161 19849 : void push(pool_t *p, uint32_t tag, const void *ptr) {
162 19849 : setPoolInfo(p, tag, ptr);
163 19849 : return get_stack().push(p, tag, ptr);
164 : }
165 442234214 : void pop() {
166 442234214 : return get_stack().pop();
167 : }
168 :
169 13400 : void foreach_info(void *data, bool(*cb)(void *, pool_t *, uint32_t, const void *)) {
170 13400 : get_stack().foreachInfo(data, cb);
171 13400 : }
172 :
173 : static inline bool isCustom(allocator_t *alloc) {
174 : if constexpr (apr::SP_APR_COMPATIBLE) {
175 : if (alloc && *((uintptr_t *)alloc) == custom::POOL_MAGIC) {
176 : return true;
177 : } else {
178 : return false;
179 : }
180 : }
181 : return true;
182 : }
183 :
184 : static inline bool isCustom(pool_t *p) {
185 : if constexpr (apr::SP_APR_COMPATIBLE) {
186 : if (p && *((uintptr_t *)p) == custom::POOL_MAGIC) {
187 : return true;
188 : } else {
189 : return false;
190 : }
191 : }
192 : return true;
193 : }
194 :
195 : }
196 :
197 :
198 : typedef struct apr_allocator_t apr_allocator_t;
199 : typedef struct apr_pool_t apr_pool_t;
200 :
201 : using apr_status_t = int;
202 :
203 : namespace STAPPLER_VERSIONIZED stappler::mempool::apr {
204 :
205 : using allocator_t = apr_allocator_t;
206 : using status_t = apr_status_t;
207 : using pool_t = apr_pool_t;
208 : using cleanup_fn = status_t(*)(void *);
209 :
210 : }
211 :
212 : namespace STAPPLER_VERSIONIZED stappler::mempool::apr::allocator {
213 :
214 : SPUNUSED static allocator_t *create();
215 : SPUNUSED static allocator_t *create(void *mutex);
216 : SPUNUSED static void destroy(allocator_t *alloc);
217 : SPUNUSED static void owner_set(allocator_t *alloc, pool_t *pool);
218 : SPUNUSED static pool_t * owner_get(allocator_t *alloc);
219 : SPUNUSED static void max_free_set(allocator_t *alloc, size_t size);
220 :
221 : }
222 :
223 : namespace STAPPLER_VERSIONIZED stappler::mempool::apr::pool {
224 :
225 : SPUNUSED static void initialize();
226 : SPUNUSED static void terminate();
227 : SPUNUSED static pool_t *create();
228 : SPUNUSED static pool_t *create(apr_allocator_t *alloc);
229 : SPUNUSED static pool_t *create(pool_t *p);
230 : SPUNUSED static pool_t *createTagged(const char *tag);
231 : SPUNUSED static pool_t *createTagged(pool_t *p, const char *tag);
232 : SPUNUSED static void destroy(pool_t *p);
233 : SPUNUSED static void clear(pool_t *p);
234 : SPUNUSED static void *alloc(pool_t *p, size_t &size);
235 : SPUNUSED static void free(pool_t *p, void *ptr, size_t size);
236 : SPUNUSED static void *palloc(pool_t *p, size_t size);
237 : SPUNUSED static void *calloc(pool_t *p, size_t count, size_t eltsize);
238 : SPUNUSED static void cleanup_kill(pool_t *p, void *ptr, status_t(*cb)(void *));
239 : SPUNUSED static void cleanup_register(pool_t *p, void *ptr, status_t(*cb)(void *));
240 : SPUNUSED static void pre_cleanup_register(pool_t *p, void *ptr, status_t(*cb)(void *));
241 : SPUNUSED static status_t userdata_set(const void *data, const char *key, cleanup_fn cb, pool_t *pool);
242 : SPUNUSED static status_t userdata_setn(const void *data, const char *key, cleanup_fn cb, pool_t *pool);
243 : SPUNUSED static status_t userdata_get(void **data, const char *key, pool_t *pool);
244 : SPUNUSED static size_t get_allocated_bytes(pool_t *p);
245 : SPUNUSED static size_t get_return_bytes(pool_t *p);
246 : SPUNUSED static allocator_t *get_allocator(pool_t *p);
247 : SPUNUSED static void *pmemdup(pool_t *a, const void *m, size_t n);
248 : SPUNUSED static char *pstrdup(pool_t *a, const char *s);
249 : SPUNUSED static void setPoolInfo(pool_t *p, uint32_t tag, const void *ptr);
250 : SPUNUSED static bool isThreadSafeAsParent(pool_t *pool);
251 : SPUNUSED static const char *get_tag(pool_t *pool);
252 :
253 : }
254 :
255 :
256 : namespace STAPPLER_VERSIONIZED stappler::mempool::base::allocator {
257 :
258 274 : allocator_t *create(bool custom) {
259 : if constexpr (apr::SP_APR_COMPATIBLE) {
260 : if (!custom) {
261 : return (allocator_t *)apr::allocator::create();
262 : }
263 : }
264 274 : return (allocator_t *) (new custom::Allocator());
265 : }
266 :
267 0 : allocator_t *create(void *mutex) {
268 : if constexpr (apr::SP_APR_COMPATIBLE) {
269 : return (allocator_t *)apr::allocator::create(mutex);
270 : }
271 0 : abort(); // custom allocator with mutex is not available
272 : return nullptr;
273 : }
274 :
275 0 : allocator_t *createWithMmap(uint32_t initialPages) {
276 : #if LINUX
277 0 : auto alloc = new custom::Allocator();
278 0 : alloc->run_mmap(initialPages);
279 0 : return (allocator_t *) alloc;
280 : #endif
281 : return (allocator_t *) nullptr;
282 : }
283 :
284 238 : void destroy(allocator_t *alloc) {
285 : if constexpr (apr::SP_APR_COMPATIBLE) {
286 : if (pool::isCustom(alloc)) {
287 : delete (custom::Allocator *)alloc;
288 : } else {
289 : apr::allocator::destroy((apr::allocator_t *)alloc);
290 : }
291 : } else {
292 238 : delete (custom::Allocator *)alloc;
293 : }
294 265 : }
295 :
296 0 : void owner_set(allocator_t *alloc, pool_t *pool) {
297 : if constexpr (apr::SP_APR_COMPATIBLE) {
298 : if (pool::isCustom(alloc)) {
299 : if (pool::isCustom(pool)) {
300 : ((custom::Allocator *)alloc)->owner = (custom::Pool *)pool;
301 : } else {
302 : abort();
303 : }
304 : } else {
305 : apr::allocator::owner_set((apr::allocator_t *)alloc, (apr::pool_t *)pool);
306 : }
307 : } else {
308 0 : ((custom::Allocator *)alloc)->owner = (custom::Pool *)pool;
309 : }
310 0 : }
311 :
312 0 : pool_t * owner_get(allocator_t *alloc) {
313 : if constexpr (apr::SP_APR_COMPATIBLE) {
314 : if (!pool::isCustom(alloc)) {
315 : return (pool_t *)apr::allocator::owner_get((apr::allocator_t *)alloc);
316 : }
317 : }
318 0 : return (pool_t *)((custom::Allocator *)alloc)->owner;
319 : }
320 :
321 25 : void max_free_set(allocator_t *alloc, size_t size) {
322 : if constexpr (apr::SP_APR_COMPATIBLE) {
323 : if (pool::isCustom(alloc)) {
324 : ((custom::Allocator *)alloc)->set_max(size);
325 : } else {
326 : apr::allocator::max_free_set((apr::allocator_t *)alloc, size);
327 : }
328 : } else {
329 25 : ((custom::Allocator *)alloc)->set_max(size);
330 : }
331 25 : }
332 :
333 : }
334 :
335 : namespace STAPPLER_VERSIONIZED stappler::mempool::base::pool {
336 :
337 : static std::atomic<size_t> s_activePools = 0;
338 : static std::atomic<bool> s_poolDebug = 0;
339 : static std::mutex s_poolDebugMutex;
340 : static pool_t *s_poolDebugTarget = nullptr;
341 : static std::map<pool_t *, const char **, std::less<void>> s_poolDebugInfo;
342 :
343 : #if DEBUG_POOL_LIST
344 : static std::vector<pool_t *> s_poolList;
345 : #endif
346 :
347 : #if DEBUG_BACKTRACE
348 : static ::backtrace_state *s_backtraceState;
349 :
350 : struct debug_bt_info {
351 : pool_t *pool;
352 : const char **target;
353 : size_t index;
354 : };
355 :
356 : static void debug_backtrace_error(void *data, const char *msg, int errnum) {
357 : std::cout << "Backtrace error: " << msg << "\n";
358 : }
359 :
360 : static int debug_backtrace_full_callback(void *data, uintptr_t pc, const char *filename, int lineno, const char *function) {
361 : auto ptr = (debug_bt_info *)data;
362 :
363 : std::ostringstream f;
364 : f << "[" << ptr->index << " - 0x" << std::hex << pc << std::dec << "]";
365 :
366 : if (filename) {
367 : auto name = filepath::name(filename);
368 : f << " " << name << ":" << lineno;
369 : }
370 : if (function) {
371 : f << " - ";
372 : int status = 0;
373 : auto ptr = abi::__cxa_demangle (function, nullptr, nullptr, &status);
374 : if (ptr) {
375 : f << (const char *)ptr;
376 : ::free(ptr);
377 : } else {
378 : f << function;
379 : }
380 : }
381 :
382 : auto tmp = f.str();
383 : *ptr->target = pstrdup(ptr->pool, tmp.data());
384 : ++ ptr->target;
385 : ++ ptr->index;
386 :
387 : if (ptr->index > 20) {
388 : return 1;
389 : }
390 :
391 : return 0;
392 : }
393 :
394 : static const char **getPoolInfo(pool_t *pool) {
395 : static constexpr size_t len = 20;
396 : static constexpr size_t offset = 2;
397 : const char **ret = (const char **)calloc(s_poolDebugTarget, len + offset + 2, sizeof(const char *));
398 : size_t retIt = 0;
399 :
400 : do {
401 : std::ostringstream f;
402 : f << "Pool " << (void *)pool << " (" << s_activePools.load() << ")";
403 : auto tmp = f.str();
404 : ret[retIt] = pstrdup(s_poolDebugTarget, tmp.data()); ++ retIt;
405 : } while(0);
406 :
407 : debug_bt_info info;
408 : info.pool = s_poolDebugTarget;
409 : info.target = ret + 1;
410 : info.index = 0;
411 :
412 : backtrace_full(s_backtraceState, 2, debug_backtrace_full_callback, debug_backtrace_error, &info);
413 : return ret;
414 : }
415 : #else
416 0 : static const char **getPoolInfo(pool_t *pool) {
417 0 : return nullptr;
418 : }
419 : #endif
420 :
421 195396 : static pool_t *pushPoolInfo(pool_t *pool) {
422 195396 : if (pool) {
423 195410 : ++ s_activePools;
424 195638 : if (s_poolDebug.load()) {
425 0 : if (auto ret = getPoolInfo(pool)) {
426 0 : s_poolDebugMutex.lock();
427 0 : s_poolDebugInfo.emplace(pool, ret);
428 0 : s_poolDebugMutex.unlock();
429 : }
430 : }
431 : #if DEBUG_POOL_LIST
432 : if (isCustom(pool)) {
433 : s_poolDebugMutex.lock();
434 : s_poolList.emplace_back(pool);
435 : s_poolDebugMutex.unlock();
436 : }
437 : #endif
438 : }
439 195351 : return pool;
440 : }
441 :
442 387744 : SPUNUSED static void popPoolInfo(pool_t *pool) {
443 387744 : if (pool) {
444 387753 : if (s_poolDebug.load()) {
445 0 : s_poolDebugMutex.lock();
446 0 : s_poolDebugInfo.erase(pool);
447 0 : s_poolDebugMutex.unlock();
448 : }
449 : #if DEBUG_POOL_LIST
450 : if (isCustom(pool)) {
451 : s_poolDebugMutex.lock();
452 : auto it = std::find(s_poolList.begin(), s_poolList.end(), pool);
453 : if (it != s_poolList.end()) {
454 : s_poolList.erase(it);
455 : }
456 : s_poolDebugMutex.unlock();
457 : }
458 : #endif
459 387773 : -- s_activePools;
460 : }
461 387923 : }
462 :
463 1274 : void initialize() {
464 : if constexpr (apr::SP_APR_COMPATIBLE) { apr::pool::initialize(); }
465 1274 : custom::initialize();
466 1273 : }
467 :
468 1087 : void terminate() {
469 : if constexpr (apr::SP_APR_COMPATIBLE) { apr::pool::terminate(); }
470 1087 : custom::terminate();
471 1111 : }
472 :
473 5874 : pool_t *create(PoolFlags flags) {
474 : if constexpr (apr::SP_APR_COMPATIBLE) {
475 : if ((flags & PoolFlags::Custom) == PoolFlags::None) {
476 : return pushPoolInfo((pool_t *)apr::pool::create());
477 : }
478 : }
479 5874 : return pushPoolInfo((pool_t *)custom::Pool::create(nullptr, flags));
480 : }
481 :
482 274 : pool_t *create(allocator_t *alloc, PoolFlags flags) {
483 : if constexpr (apr::SP_APR_COMPATIBLE) {
484 : if (isCustom(alloc)) {
485 : return pushPoolInfo((pool_t *)custom::Pool::create((custom::Allocator *)alloc, flags));
486 : } else if ((flags & PoolFlags::ThreadSafePool) == PoolFlags::None) {
487 : return pushPoolInfo((pool_t *)apr::pool::create((apr::allocator_t *)alloc));
488 : } else {
489 : abort(); // thread-safe APR pools is not supported
490 : }
491 : }
492 274 : return pushPoolInfo((pool_t *)custom::Pool::create((custom::Allocator *)alloc, flags));
493 : }
494 :
495 : // creates managed pool (managed by root, if parent in mullptr)
496 188876 : pool_t *create(pool_t *pool) {
497 : if constexpr (apr::SP_APR_COMPATIBLE) {
498 : if (!isCustom(pool)) {
499 : return pushPoolInfo((pool_t *)apr::pool::create((apr::pool_t *)pool));
500 : }
501 : }
502 188876 : return pushPoolInfo((pool_t *)custom::create((custom::Pool *)pool));
503 : }
504 :
505 : // creates unmanaged pool
506 425 : pool_t *createTagged(const char *tag, PoolFlags flags) {
507 : if constexpr (apr::SP_APR_COMPATIBLE) {
508 : if ((flags & PoolFlags::Custom) == PoolFlags::None) {
509 : return pushPoolInfo((pool_t *)apr::pool::createTagged(tag));
510 : }
511 : }
512 425 : if (auto ret = custom::Pool::create(nullptr, flags)) {
513 425 : ret->allocmngr.name = tag;
514 425 : return pushPoolInfo((pool_t *)ret);
515 : }
516 0 : return nullptr;
517 : }
518 :
519 25 : pool_t *createTagged(pool_t *p, const char *tag) {
520 : if constexpr (apr::SP_APR_COMPATIBLE) {
521 : if (!isCustom(p)) {
522 : return pushPoolInfo((pool_t *)apr::pool::createTagged((apr::pool_t *)p, tag));
523 : }
524 : }
525 25 : if (auto ret = custom::create((custom::Pool *)p)) {
526 25 : ret->allocmngr.name = tag;
527 25 : return pushPoolInfo((pool_t *)ret);
528 : }
529 0 : return nullptr;
530 : }
531 :
532 192902 : void destroy(pool_t *p) {
533 192902 : popPoolInfo(p);
534 : if constexpr (apr::SP_APR_COMPATIBLE) {
535 : if (!isCustom(p)) {
536 : apr::pool::destroy((apr::pool_t *)p);
537 : } else {
538 : custom::destroy((custom::Pool *)p);
539 : }
540 : } else {
541 192920 : custom::destroy((custom::Pool *)p);
542 : }
543 192868 : }
544 :
545 219454418 : void clear(pool_t *p) {
546 : if constexpr (apr::SP_APR_COMPATIBLE) {
547 : if (!isCustom(p)) {
548 : apr::pool::clear((apr::pool_t *)p);
549 : } else {
550 : ((custom::Pool *)p)->clear();
551 : }
552 : } else {
553 219454418 : ((custom::Pool *)p)->clear();
554 : }
555 219240544 : }
556 :
557 22479571 : void *alloc(pool_t *pool, size_t &size) {
558 : if constexpr (apr::SP_APR_COMPATIBLE) {
559 : if (!isCustom(pool)) {
560 : return apr::pool::alloc((apr::pool_t *)pool, size);
561 : }
562 : }
563 22479571 : return ((custom::Pool *)pool)->alloc(size);
564 : }
565 :
566 2943660 : void *palloc(pool_t *pool, size_t size) {
567 : if constexpr (apr::SP_APR_COMPATIBLE) {
568 : if (!isCustom(pool)) {
569 : return apr::pool::palloc((apr::pool_t *)pool, size);
570 : }
571 : }
572 2943660 : return ((custom::Pool *)pool)->palloc(size);
573 : }
574 :
575 15746 : void *calloc(pool_t *pool, size_t count, size_t eltsize) {
576 : if constexpr (apr::SP_APR_COMPATIBLE) {
577 : if (!isCustom(pool)) {
578 : return apr::pool::calloc((apr::pool_t *)pool, count, eltsize);
579 : }
580 : }
581 15746 : return ((custom::Pool *)pool)->calloc(count, eltsize);
582 : }
583 :
584 3976965 : void free(pool_t *pool, void *ptr, size_t size) {
585 : if constexpr (apr::SP_APR_COMPATIBLE) {
586 : if (!isCustom(pool)) {
587 : apr::pool::free((apr::pool_t *)pool, ptr, size);
588 : return;
589 : }
590 : }
591 3976965 : ((custom::Pool *)pool)->free(ptr, size);
592 3976995 : }
593 :
594 0 : void cleanup_kill(pool_t *pool, void *ptr, cleanup_fn cb) {
595 : if constexpr (apr::SP_APR_COMPATIBLE) {
596 : if (!isCustom(pool)) {
597 : apr::pool::cleanup_kill((apr::pool_t *)pool, ptr, cb);
598 : return;
599 : }
600 : }
601 0 : ((custom::Pool *)pool)->cleanup_kill(ptr, (custom::Cleanup::Callback)cb);
602 0 : }
603 :
604 2950 : void cleanup_register(pool_t *pool, void *ptr, cleanup_fn cb) {
605 : if constexpr (apr::SP_APR_COMPATIBLE) {
606 : if (!isCustom(pool)) {
607 : apr::pool::cleanup_register((apr::pool_t *)pool, ptr, cb);
608 : return;
609 : }
610 : }
611 2950 : ((custom::Pool *)pool)->cleanup_register(ptr, (custom::Cleanup::Callback)cb);
612 2950 : }
613 :
614 304 : void pre_cleanup_register(pool_t *pool, void *ptr, cleanup_fn cb) {
615 : if constexpr (apr::SP_APR_COMPATIBLE) {
616 : if (!isCustom(pool)) {
617 : apr::pool::pre_cleanup_register((apr::pool_t *)pool, ptr, cb);
618 : return;
619 : }
620 : }
621 304 : ((custom::Pool *)pool)->pre_cleanup_register(ptr, (custom::Cleanup::Callback)cb);
622 304 : }
623 :
624 24185 : status_t userdata_set(const void *data, const char *key, cleanup_fn cb, pool_t *pool) {
625 : if constexpr (apr::SP_APR_COMPATIBLE) {
626 : if (!isCustom(pool)) {
627 : return apr::pool::userdata_set(data, key, cb, (apr::pool_t *)pool);
628 : }
629 : }
630 24185 : return ((custom::Pool *)pool)->userdata_set(data, key, (custom::Cleanup::Callback)cb);
631 : }
632 :
633 0 : status_t userdata_setn(const void *data, const char *key, cleanup_fn cb, pool_t *pool) {
634 : if constexpr (apr::SP_APR_COMPATIBLE) {
635 : if (!isCustom(pool)) {
636 : return apr::pool::userdata_setn(data, key, cb, (apr::pool_t *)pool);
637 : }
638 : }
639 0 : return ((custom::Pool *)pool)->userdata_setn(data, key, (custom::Cleanup::Callback)cb);
640 : }
641 :
642 82874 : status_t userdata_get(void **data, const char *key, pool_t *pool) {
643 : if constexpr (apr::SP_APR_COMPATIBLE) {
644 : if (!isCustom(pool)) {
645 : return apr::pool::userdata_get(data, key, (apr::pool_t *)pool);
646 : }
647 : }
648 82874 : return ((custom::Pool *)pool)->userdata_get(data, key);
649 : }
650 :
651 108204 : status_t userdata_get(void **data, const char *key, size_t klen, pool_t *pool) {
652 : if constexpr (apr::SP_APR_COMPATIBLE) {
653 : if (!isCustom(pool)) {
654 : if (key[klen]) {
655 : return apr::pool::userdata_get(data, key, (apr::pool_t *)pool);
656 : } else {
657 : char buf[klen + 1];
658 : memcpy(buf, key, klen);
659 : buf[klen] = 0;
660 : return apr::pool::userdata_get(data, key, (apr::pool_t *)pool);
661 : }
662 : }
663 : }
664 108204 : return ((custom::Pool *)pool)->userdata_get(data, key, klen);
665 : }
666 :
667 : // debug counters
668 50 : size_t get_allocated_bytes(pool_t *pool) {
669 : if constexpr (apr::SP_APR_COMPATIBLE) {
670 : if (!isCustom(pool)) {
671 : return apr::pool::get_allocated_bytes((apr::pool_t *)pool);
672 : }
673 : }
674 50 : return ((custom::Pool *)pool)->allocmngr.allocated;
675 : }
676 :
677 50 : size_t get_return_bytes(pool_t *pool) {
678 : if constexpr (apr::SP_APR_COMPATIBLE) {
679 : if (!isCustom(pool)) {
680 : return apr::pool::get_return_bytes((apr::pool_t *)pool);
681 : }
682 : }
683 50 : return ((custom::Pool *)pool)->allocmngr.returned;
684 : }
685 :
686 0 : allocator_t *get_allocator(pool_t *pool) {
687 : if constexpr (apr::SP_APR_COMPATIBLE) {
688 : if (!isCustom(pool)) {
689 : return (allocator_t *)apr::pool::get_allocator((apr::pool_t *)pool);
690 : }
691 : }
692 0 : return (allocator_t *)(((custom::Pool *)pool)->allocator);
693 : }
694 :
695 0 : void *pmemdup(pool_t *pool, const void *m, size_t n) {
696 : if constexpr (apr::SP_APR_COMPATIBLE) {
697 : if (!isCustom(pool)) {
698 : return apr::pool::pmemdup((apr::pool_t *)pool, m, n);
699 : }
700 : }
701 0 : return ((custom::Pool *)pool)->pmemdup(m, n);
702 : }
703 :
704 0 : char *pstrdup(pool_t *pool, const char *s) {
705 : if constexpr (apr::SP_APR_COMPATIBLE) {
706 : if (!isCustom(pool)) {
707 : return apr::pool::pstrdup((apr::pool_t *)pool, s);
708 : }
709 : }
710 0 : return ((custom::Pool *)pool)->pstrdup(s);
711 : }
712 :
713 0 : bool isThreadSafeForAllocations(pool_t *pool) {
714 : if constexpr (apr::SP_APR_COMPATIBLE) {
715 : if (isCustom(pool)) {
716 : return ((custom::Pool *)pool)->threadSafe;
717 : }
718 : return false; // APR pools can not be thread safe for allocations
719 : } else {
720 0 : return ((custom::Pool *)pool)->threadSafe;
721 : }
722 : }
723 :
724 0 : bool isThreadSafeAsParent(pool_t *pool) {
725 : if constexpr (apr::SP_APR_COMPATIBLE) {
726 : if (isCustom(pool)) {
727 : return ((custom::Pool *)pool)->allocator->mutex != nullptr;
728 : } else {
729 : return apr::pool::isThreadSafeAsParent((apr::pool_t *)pool);
730 : }
731 : } else {
732 0 : return ((custom::Pool *)pool)->allocator->mutex != nullptr;
733 : }
734 : }
735 :
736 0 : const char *get_tag(pool_t *pool) {
737 : if constexpr (apr::SP_APR_COMPATIBLE) {
738 : if (isCustom(pool)) {
739 : return ((custom::Pool *)pool)->allocmngr.name;
740 : } else {
741 : return apr::pool::get_tag((apr::pool_t *)pool);
742 : }
743 : } else {
744 0 : return ((custom::Pool *)pool)->allocmngr.name;
745 : }
746 : }
747 :
748 19849 : void setPoolInfo(pool_t *pool, uint32_t tag, const void *ptr) {
749 : if constexpr (apr::SP_APR_COMPATIBLE) {
750 : if (!isCustom(pool)) {
751 : apr::pool::setPoolInfo((apr::pool_t *)pool, tag, ptr);
752 : return;
753 : }
754 : }
755 :
756 19849 : if (auto mngr = &((custom::Pool *)pool)->allocmngr) {
757 19849 : if (tag > mngr->tag) {
758 4874 : mngr->tag = tag;
759 : }
760 19849 : mngr->ptr = ptr;
761 : }
762 19849 : }
763 :
764 3079 : static status_t cleanup_register_fn(void *ptr) {
765 3079 : if (auto fn = (memory::function<void()> *)ptr) {
766 3079 : (*fn)();
767 : }
768 3079 : return 0;
769 : }
770 :
771 2950 : void cleanup_register(pool_t *p, memory::function<void()> &&cb) {
772 2950 : pool::push(p);
773 2950 : auto fn = new (p) memory::function<void()>(move(cb));
774 2950 : pool::pop();
775 2950 : pool::cleanup_register(p, fn, &cleanup_register_fn);
776 2950 : }
777 :
778 154 : void pre_cleanup_register(pool_t *p, memory::function<void()> &&cb) {
779 154 : pool::push(p);
780 154 : auto fn = new (p) memory::function<void()>(move(cb));
781 154 : pool::pop();
782 154 : pool::pre_cleanup_register(p, fn, &cleanup_register_fn);
783 154 : }
784 :
785 0 : size_t get_active_count() {
786 0 : return s_activePools.load();
787 : }
788 :
789 0 : bool debug_begin(pool_t *pool) {
790 0 : if (!pool) {
791 0 : pool = acquire();
792 : }
793 0 : bool expected = false;
794 0 : if (s_poolDebug.compare_exchange_strong(expected, true)) {
795 0 : s_poolDebugMutex.lock();
796 0 : s_poolDebugTarget = pool;
797 : #if DEBUG_BACKTRACE
798 : if (!s_backtraceState) {
799 : s_backtraceState = backtrace_create_state(nullptr, 1, debug_backtrace_error, nullptr);
800 : }
801 : #endif
802 0 : s_poolDebugInfo.clear();
803 0 : s_poolDebugMutex.unlock();
804 0 : return true;
805 : }
806 0 : return false;
807 : }
808 :
809 0 : std::map<pool_t *, const char **, std::less<void>> debug_end() {
810 0 : std::map<pool_t *, const char **, std::less<void>> ret;
811 0 : s_poolDebugMutex.lock();
812 0 : ret = std::move(s_poolDebugInfo);
813 0 : s_poolDebugInfo.clear();
814 0 : s_poolDebugTarget = nullptr;
815 0 : s_poolDebugMutex.unlock();
816 0 : s_poolDebug.store(false);
817 0 : return ret;
818 0 : }
819 :
820 0 : void debug_foreach(void *ptr, void(*cb)(void *, pool_t *)) {
821 : #if DEBUG_POOL_LIST
822 : s_poolDebugMutex.lock();
823 : for (auto &it : s_poolList) {
824 : cb(ptr, it);
825 : }
826 : s_poolDebugMutex.unlock();
827 : #endif
828 0 : }
829 :
830 : }
|