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_ */
|