LCOV - code coverage report
Current view: top level - core/core/memory/pool - SPMemPoolStruct.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 2 4 50.0 %
Date: 2024-05-12 00:16:13 Functions: 2 4 50.0 %

          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             : #ifndef STAPPLER_CORE_MEMORY_POOL_SPMEMPOOLSTRUCT_H_
      25             : #define STAPPLER_CORE_MEMORY_POOL_SPMEMPOOLSTRUCT_H_
      26             : 
      27             : #include "SPMemPoolConfig.h"
      28             : 
      29             : namespace STAPPLER_VERSIONIZED stappler::mempool::custom {
      30             : 
      31             : struct MemAddr {
      32             :         uint32_t size = 0;
      33             :         MemAddr *next = nullptr;
      34             :         void *address = nullptr;
      35             : };
      36             : 
      37             : struct AllocManager {
      38             :         using AllocFn = void *(*) (void *, size_t);
      39             :         void *pool = nullptr;
      40             :         MemAddr *buffered = nullptr;
      41             :         MemAddr *free_buffered = nullptr;
      42             : 
      43             :         const char *name = nullptr;
      44             :         uint32_t tag = 0;
      45             :         const void *ptr = 0;
      46             : 
      47             :         size_t alloc_buffer = 0;
      48             :         size_t allocated = 0;
      49             :         size_t returned = 0;
      50             :         size_t opts = 0; // deprecated/unused
      51             : 
      52             :         void reset(void *);
      53             : 
      54             :         void *alloc(size_t &sizeInBytes, AllocFn);
      55             :         void free(void *ptr, size_t sizeInBytes, AllocFn);
      56             : 
      57    22992062 :         void increment_alloc(size_t s) { allocated += s; alloc_buffer += s; }
      58      479878 :         void increment_return(size_t s) { returned += s; }
      59             : 
      60           0 :         size_t get_alloc() { return allocated; }
      61           0 :         size_t get_return() { return returned; }
      62             : };
      63             : 
      64             : struct Pool;
      65             : struct HashTable;
      66             : 
      67             : struct MemNode {
      68             :         MemNode *next; // next memnode
      69             :         MemNode **ref; // reference to self
      70             :         uint32_t index; // size
      71             :         uint32_t free_index; // how much free
      72             :         uint8_t *first_avail; // pointer to first free memory
      73             :         uint8_t *endp; // pointer to end of free memory
      74             : 
      75             :         void insert(MemNode *point);
      76             :         void remove();
      77             : 
      78             :         size_t free_space() const;
      79             : };
      80             : 
      81             : struct Cleanup {
      82             :         using Callback = Status (*)(void *data);
      83             : 
      84             :         Cleanup *next;
      85             :         const void *data;
      86             :         Callback fn;
      87             : 
      88             :         static void run(Cleanup **cref);
      89             : };
      90             : 
      91             : struct Allocator {
      92             :         using AllocMutex = std::recursive_mutex;
      93             : 
      94             : #if MODULE_STAPPLER_APR
      95             :         uintptr_t magic = POOL_MAGIC; // used to detect stappler allocators
      96             : #endif
      97             :         uint32_t last = 0; // largest used index into free
      98             :         uint32_t max = ALLOCATOR_MAX_FREE_UNLIMITED; // Total size (in BOUNDARY_SIZE multiples) of unused memory before blocks are given back
      99             :         uint32_t current = 0; // current allocated size in BOUNDARY_SIZE
     100             :         Pool *owner = nullptr;
     101             : 
     102             :         AllocMutex *mutex = nullptr;
     103             :         std::array<MemNode *, MAX_INDEX> buf;
     104             :         std::atomic<size_t> allocated;
     105             : 
     106             :         static size_t getAllocatorsCount();
     107             : 
     108             :         Allocator(bool threadSafe = true);
     109             :         ~Allocator();
     110             : 
     111             :         void set_max(uint32_t);
     112             : 
     113             :         MemNode *alloc(uint32_t);
     114             :         void free(MemNode *);
     115             : 
     116             :         void lock();
     117             :         void unlock();
     118             : 
     119             : #if LINUX
     120             :         int mmapdes = -1;
     121             :         void *mmapPtr = nullptr;
     122             :         uint32_t mmapCurrent = 0;
     123             :         uint32_t mmapMax = 0;
     124             : 
     125             :         bool run_mmap(uint64_t);
     126             : #endif
     127             : 
     128             :         AllocManager::AllocFn allocationTracker = nullptr;
     129             : };
     130             : 
     131             : struct Pool {
     132             :         Pool *parent = nullptr;
     133             :         Pool *child = nullptr;
     134             :         Pool *sibling = nullptr;
     135             :         Pool **ref = nullptr;
     136             :         Cleanup *cleanups = nullptr;
     137             :         Cleanup *free_cleanups = nullptr;
     138             :         Allocator *allocator = nullptr;
     139             : #if MODULE_STAPPLER_APR
     140             :         uint64_t magic = POOL_MAGIC; // used to detect stappler pools
     141             : #endif
     142             :         MemNode *active = nullptr;
     143             :         MemNode *self = nullptr; /* The node containing the pool itself */
     144             :         uint8_t *self_first_avail = nullptr;
     145             :         Cleanup *pre_cleanups = nullptr;
     146             :     HashTable *user_data = nullptr;
     147             : 
     148             :         AllocManager allocmngr;
     149             :         bool threadSafe = false;
     150             : 
     151             :         static Pool *create(Allocator *alloc = nullptr, PoolFlags flags = PoolFlags::Default);
     152             :         static void destroy(Pool *);
     153             :         static size_t getPoolsCount();
     154             : 
     155             :         Pool();
     156             :         Pool(Allocator *alloc, MemNode *node, bool threadSafe = false);
     157             :         Pool(Pool *parent, Allocator *alloc, MemNode *node, bool threadSafe = false);
     158             :         ~Pool();
     159             : 
     160             :         void *alloc(size_t &sizeInBytes);
     161             :         void free(void *ptr, size_t sizeInBytes);
     162             : 
     163             :         void *palloc(size_t);
     164             :         void *palloc_self(size_t);
     165             :         void *calloc(size_t count, size_t eltsize);
     166             : 
     167             :         void *pmemdup(const void *m, size_t n);
     168             :         char *pstrdup(const char *s);
     169             : 
     170             :         void clear();
     171             : 
     172             :         Pool *make_child();
     173             :         Pool *make_child(Allocator *);
     174             : 
     175             :         void cleanup_register(const void *, Cleanup::Callback cb);
     176             :         void pre_cleanup_register(const void *, Cleanup::Callback cb);
     177             : 
     178             :         void cleanup_kill(void *, Cleanup::Callback cb);
     179             :         void cleanup_run(void *, Cleanup::Callback cb);
     180             : 
     181             :         Status userdata_set(const void *data, const char *key, Cleanup::Callback cb);
     182             :         Status userdata_setn(const void *data, const char *key, Cleanup::Callback cb);
     183             :         Status userdata_get(void **data, const char *key);
     184             :         Status userdata_get(void **data, const char *key, size_t);
     185             : 
     186             :         void lock();
     187             :         void unlock();
     188             : };
     189             : 
     190             : using HashFunc = uint32_t (*)(const char *key, size_t *klen);
     191             : 
     192             : struct HashEntry {
     193             :         HashEntry *next;
     194             :         uint32_t hash;
     195             :         const void *key;
     196             :         size_t klen;
     197             :         const void *val;
     198             : };
     199             : 
     200             : struct HashIndex {
     201             :         HashTable *ht;
     202             :         HashEntry *_self, *_next;
     203             :         uint32_t index;
     204             : 
     205             :         HashIndex * next();
     206             : 
     207             :         void self(const void **key, size_t *klen, void **val);
     208             : };
     209             : 
     210             : struct HashTable {
     211             :         using merge_fn = void *(*)(Pool *p, const void *key, size_t klen, const void *h1_val, const void *h2_val, const void *data);
     212             :         using foreach_fn = bool (*)(void *rec, const void *key, size_t klen, const void *value);
     213             : 
     214             :         Pool *pool;
     215             :         HashEntry **array;
     216             :         HashIndex iterator; /* For apr_hash_first(NULL, ...) */
     217             :         uint32_t count, max, seed;
     218             :         HashFunc hash_func;
     219             :         HashEntry *free; /* List of recycled entries */
     220             : 
     221             :         static void init(HashTable *ht, Pool *pool);
     222             : 
     223             :         static HashTable *make(Pool *pool);
     224             :         static HashTable *make(Pool *pool, HashFunc);
     225             : 
     226             :         HashIndex * first(Pool *p = nullptr);
     227             : 
     228             :         HashTable *copy(Pool *pool) const;
     229             : 
     230             :         void *get(const void *key, size_t klen);
     231             :         void set(const void *key, size_t klen, const void *val);
     232             : 
     233             :         size_t size() const;
     234             : 
     235             :         void clear();
     236             : 
     237             :         HashTable *merge(Pool *, const HashTable *ov) const;
     238             :         HashTable *merge(Pool *, const HashTable *ov, merge_fn, const void *data) const;
     239             : 
     240             :         bool foreach(foreach_fn, void *rec) const;
     241             : };
     242             : 
     243             : void initialize();
     244             : void terminate();
     245             : 
     246             : // creates managed pool (managed by root, if parent in mullptr)
     247             : Pool *create(Pool *);
     248             : 
     249             : void destroy(Pool *);
     250             : void clear(Pool *);
     251             : 
     252             : constexpr size_t SIZEOF_MEMNODE ( SPALIGN_DEFAULT(sizeof(MemNode)) );
     253             : constexpr size_t SIZEOF_POOL ( SPALIGN_DEFAULT(sizeof(Pool)) );
     254             : 
     255             : }
     256             : 
     257             : #endif /* STAPPLER_CORE_MEMORY_POOL_SPMEMPOOLSTRUCT_H_ */

Generated by: LCOV version 1.14