LCOV - code coverage report
Current view: top level - core/core/memory/pool - SPMemPoolInterface.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 140 215 65.1 %
Date: 2024-05-12 00:16:13 Functions: 44 64 68.8 %

          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             : }

Generated by: LCOV version 1.14