blob: 9ec9fc7ef5bfd25f8dc089add897b297567bd9bd [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
Willy Tarreau62405a22014-12-23 13:51:28 +01002 * include/common/memory.h
3 * Memory management definitions..
4 *
5 * Copyright (C) 2000-2014 Willy Tarreau - w@1wt.eu
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation, version 2.1
10 * exclusively.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
Willy Tarreaubaaee002006-06-26 02:48:02 +020021
Willy Tarreau2dd0d472006-06-29 17:53:05 +020022#ifndef _COMMON_MEMORY_H
23#define _COMMON_MEMORY_H
Willy Tarreaubaaee002006-06-26 02:48:02 +020024
Willy Tarreau158fa752017-11-22 15:47:29 +010025#include <sys/mman.h>
26
Willy Tarreaubaaee002006-06-26 02:48:02 +020027#include <stdlib.h>
Willy Tarreaue430e772014-12-23 14:13:16 +010028#include <string.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020029
Willy Tarreau2dd0d472006-06-29 17:53:05 +020030#include <common/config.h>
Willy Tarreau50e608d2007-05-13 18:26:08 +020031#include <common/mini-clist.h>
Christopher Fauletb349e482017-08-29 09:52:38 +020032#include <common/hathreads.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020033
Willy Tarreaua84dcb82015-10-28 12:04:02 +010034#ifndef DEBUG_DONT_SHARE_POOLS
Willy Tarreau50e608d2007-05-13 18:26:08 +020035#define MEM_F_SHARED 0x1
Willy Tarreaua84dcb82015-10-28 12:04:02 +010036#else
37#define MEM_F_SHARED 0
38#endif
Willy Tarreau581bf812016-01-25 02:19:13 +010039#define MEM_F_EXACT 0x2
Willy Tarreau50e608d2007-05-13 18:26:08 +020040
Willy Tarreauac421112015-10-28 15:09:29 +010041/* reserve an extra void* at the end of a pool for linking */
42#ifdef DEBUG_MEMORY_POOLS
43#define POOL_EXTRA (sizeof(void *))
44#define POOL_LINK(pool, item) (void **)(((char *)item) + (pool->size))
45#else
46#define POOL_EXTRA (0)
47#define POOL_LINK(pool, item) ((void **)(item))
48#endif
49
Olivier Houchardcf975d42018-01-24 18:38:31 +010050#ifdef HA_HAVE_CAS_DW
51struct pool_free_list {
52 void **free_list;
53 uintptr_t seq;
54};
55#endif
56
Willy Tarreau50e608d2007-05-13 18:26:08 +020057struct pool_head {
Willy Tarreau1ca1b702017-11-26 10:50:36 +010058 void **free_list;
Olivier Houchardcf975d42018-01-24 18:38:31 +010059#ifdef HA_HAVE_CAS_DW
60 uintptr_t seq;
61#else
62 __decl_hathreads(HA_SPINLOCK_T lock); /* the spin lock */
63#endif
Willy Tarreau50e608d2007-05-13 18:26:08 +020064 unsigned int used; /* how many chunks are currently in use */
65 unsigned int allocated; /* how many chunks have been allocated */
66 unsigned int limit; /* hard limit on the number of chunks */
67 unsigned int minavail; /* how many chunks are expected to be used */
68 unsigned int size; /* chunk size */
69 unsigned int flags; /* MEM_F_* */
Willy Tarreau7dcd46d2007-05-14 00:16:13 +020070 unsigned int users; /* number of pools sharing this zone */
Willy Tarreau58102cf2015-10-28 16:24:21 +010071 unsigned int failed; /* failed allocations */
Olivier Houchardcf975d42018-01-24 18:38:31 +010072 struct list list; /* list of all known pools */
Willy Tarreau7dcd46d2007-05-14 00:16:13 +020073 char name[12]; /* name of the pool */
Willy Tarreau1ca1b702017-11-26 10:50:36 +010074} __attribute__((aligned(64)));
Willy Tarreau50e608d2007-05-13 18:26:08 +020075
Willy Tarreau067ac9f2015-10-08 14:12:13 +020076/* poison each newly allocated area with this byte if >= 0 */
77extern int mem_poison_byte;
Willy Tarreau50e608d2007-05-13 18:26:08 +020078
Willy Tarreaua885f6d2014-12-03 15:25:28 +010079/* Allocates new entries for pool <pool> until there are at least <avail> + 1
80 * available, then returns the last one for immediate use, so that at least
81 * <avail> are left available in the pool upon return. NULL is returned if the
82 * last entry could not be allocated. It's important to note that at least one
83 * allocation is always performed even if there are enough entries in the pool.
84 * A call to the garbage collector is performed at most once in case malloc()
85 * returns an error, before returning NULL.
Willy Tarreau50e608d2007-05-13 18:26:08 +020086 */
Christopher Fauletb349e482017-08-29 09:52:38 +020087void *__pool_refill_alloc(struct pool_head *pool, unsigned int avail);
Willy Tarreaua885f6d2014-12-03 15:25:28 +010088void *pool_refill_alloc(struct pool_head *pool, unsigned int avail);
Willy Tarreau50e608d2007-05-13 18:26:08 +020089
90/* Try to find an existing shared pool with the same characteristics and
91 * returns it, otherwise creates this one. NULL is returned if no memory
92 * is available for a new creation.
93 */
94struct pool_head *create_pool(char *name, unsigned int size, unsigned int flags);
95
96/* Dump statistics on pools usage.
97 */
Willy Tarreau12833bb2014-01-28 16:49:56 +010098void dump_pools_to_trash();
Willy Tarreau50e608d2007-05-13 18:26:08 +020099void dump_pools(void);
Willy Tarreau58102cf2015-10-28 16:24:21 +0100100int pool_total_failures();
101unsigned long pool_total_allocated();
102unsigned long pool_total_used();
Willy Tarreau50e608d2007-05-13 18:26:08 +0200103
104/*
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200105 * This function frees whatever can be freed in pool <pool>.
106 */
Willy Tarreaubafbe012017-11-24 17:34:44 +0100107void pool_flush(struct pool_head *pool);
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200108
109/*
110 * This function frees whatever can be freed in all pools, but respecting
111 * the minimum thresholds imposed by owners.
Christopher Fauletb349e482017-08-29 09:52:38 +0200112 *
Willy Tarreaubafbe012017-11-24 17:34:44 +0100113 * <pool_ctx> is used when pool_gc is called to release resources to allocate
Christopher Fauletb349e482017-08-29 09:52:38 +0200114 * an element in __pool_refill_alloc. It is important because <pool_ctx> is
115 * already locked, so we need to skip the lock here.
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200116 */
Willy Tarreaubafbe012017-11-24 17:34:44 +0100117void pool_gc(struct pool_head *pool_ctx);
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200118
119/*
120 * This function destroys a pull by freeing it completely.
121 * This should be called only under extreme circumstances.
122 */
Willy Tarreaubafbe012017-11-24 17:34:44 +0100123void *pool_destroy(struct pool_head *pool);
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200124
Olivier Houchardcf975d42018-01-24 18:38:31 +0100125#ifdef HA_HAVE_CAS_DW
126/*
127 * Returns a pointer to type <type> taken from the pool <pool_type> if
128 * available, otherwise returns NULL. No malloc() is attempted, and poisonning
129 * is never performed. The purpose is to get the fastest possible allocation.
130 */
131static inline void *__pool_get_first(struct pool_head *pool)
132{
133 struct pool_free_list cmp, new;
134
135 cmp.seq = pool->seq;
136 __ha_barrier_load();
137
138 cmp.free_list = pool->free_list;
139 do {
140 if (cmp.free_list == NULL)
141 return NULL;
142 new.seq = cmp.seq + 1;
143 __ha_barrier_load();
144 new.free_list = *POOL_LINK(pool, cmp.free_list);
145 } while (__ha_cas_dw((void *)&pool->free_list, (void *)&cmp, (void *)&new) == 0);
146end:
147 HA_ATOMIC_ADD(&pool->used, 1);
148#ifdef DEBUG_MEMORY_POOLS
149 /* keep track of where the element was allocated from */
150 *POOL_LINK(pool, cmp.free_list) = (void *)pool;
151#endif
152 return cmp.free_list;
153}
154
155static inline void *pool_get_first(struct pool_head *pool)
156{
157 void *ret;
158
159 ret = __pool_get_first(pool);
160 return ret;
161}
162/*
163 * Returns a pointer to type <type> taken from the pool <pool_type> or
164 * dynamically allocated. In the first case, <pool_type> is updated to point to
165 * the next element in the list. No memory poisonning is ever performed on the
166 * returned area.
167 */
168static inline void *pool_alloc_dirty(struct pool_head *pool)
169{
170 void *p;
171
172 if ((p = __pool_get_first(pool)) == NULL)
173 p = __pool_refill_alloc(pool, 0);
174 return p;
175}
176
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200177/*
Olivier Houchardcf975d42018-01-24 18:38:31 +0100178 * Returns a pointer to type <type> taken from the pool <pool_type> or
179 * dynamically allocated. In the first case, <pool_type> is updated to point to
180 * the next element in the list. Memory poisonning is performed if enabled.
181 */
182static inline void *pool_alloc(struct pool_head *pool)
183{
184 void *p;
185
186 p = pool_alloc_dirty(pool);
187#ifdef DEBUG_MEMORY_POOLS
188 if (p) {
189 /* keep track of where the element was allocated from */
190 *POOL_LINK(pool, p) = (void *)pool;
191 }
192#endif
193 if (p && mem_poison_byte >= 0) {
194 memset(p, mem_poison_byte, pool->size);
195 }
196
197 return p;
198}
199
200/*
201 * Puts a memory area back to the corresponding pool.
202 * Items are chained directly through a pointer that
203 * is written in the beginning of the memory area, so
204 * there's no need for any carrier cell. This implies
205 * that each memory area is at least as big as one
206 * pointer. Just like with the libc's free(), nothing
207 * is done if <ptr> is NULL.
208 */
209static inline void pool_free(struct pool_head *pool, void *ptr)
210{
211 if (likely(ptr != NULL)) {
212 void *free_list;
213#ifdef DEBUG_MEMORY_POOLS
214 /* we'll get late corruption if we refill to the wrong pool or double-free */
215 if (*POOL_LINK(pool, ptr) != (void *)pool)
216 *(volatile int *)0 = 0;
217#endif
218 free_list = pool->free_list;
219 do {
220 *POOL_LINK(pool, ptr) = (void *)free_list;
221 __ha_barrier_store();
222 } while (!HA_ATOMIC_CAS(&pool->free_list, (void *)&free_list, ptr));
223end:
224 HA_ATOMIC_SUB(&pool->used, 1);
225 }
226}
227
228#else
229/*
Willy Tarreau02622412014-12-08 16:35:23 +0100230 * Returns a pointer to type <type> taken from the pool <pool_type> if
231 * available, otherwise returns NULL. No malloc() is attempted, and poisonning
232 * is never performed. The purpose is to get the fastest possible allocation.
Willy Tarreau50e608d2007-05-13 18:26:08 +0200233 */
Christopher Fauletb349e482017-08-29 09:52:38 +0200234static inline void *__pool_get_first(struct pool_head *pool)
Willy Tarreaue430e772014-12-23 14:13:16 +0100235{
236 void *p;
237
Willy Tarreau02622412014-12-08 16:35:23 +0100238 if ((p = pool->free_list) != NULL) {
Willy Tarreauac421112015-10-28 15:09:29 +0100239 pool->free_list = *POOL_LINK(pool, p);
Willy Tarreaue430e772014-12-23 14:13:16 +0100240 pool->used++;
Willy Tarreaude30a682015-10-28 15:23:51 +0100241#ifdef DEBUG_MEMORY_POOLS
242 /* keep track of where the element was allocated from */
243 *POOL_LINK(pool, p) = (void *)pool;
244#endif
Willy Tarreaue430e772014-12-23 14:13:16 +0100245 }
246 return p;
247}
Willy Tarreau50e608d2007-05-13 18:26:08 +0200248
Christopher Fauletb349e482017-08-29 09:52:38 +0200249static inline void *pool_get_first(struct pool_head *pool)
250{
251 void *ret;
252
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100253 HA_SPIN_LOCK(POOL_LOCK, &pool->lock);
Christopher Fauletb349e482017-08-29 09:52:38 +0200254 ret = __pool_get_first(pool);
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100255 HA_SPIN_UNLOCK(POOL_LOCK, &pool->lock);
Christopher Fauletb349e482017-08-29 09:52:38 +0200256 return ret;
257}
Willy Tarreau50e608d2007-05-13 18:26:08 +0200258/*
Willy Tarreau02622412014-12-08 16:35:23 +0100259 * Returns a pointer to type <type> taken from the pool <pool_type> or
260 * dynamically allocated. In the first case, <pool_type> is updated to point to
261 * the next element in the list. No memory poisonning is ever performed on the
262 * returned area.
263 */
264static inline void *pool_alloc_dirty(struct pool_head *pool)
265{
266 void *p;
267
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100268 HA_SPIN_LOCK(POOL_LOCK, &pool->lock);
Christopher Fauletb349e482017-08-29 09:52:38 +0200269 if ((p = __pool_get_first(pool)) == NULL)
270 p = __pool_refill_alloc(pool, 0);
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100271 HA_SPIN_UNLOCK(POOL_LOCK, &pool->lock);
Willy Tarreau02622412014-12-08 16:35:23 +0100272 return p;
273}
274
Willy Tarreau158fa752017-11-22 15:47:29 +0100275#ifndef DEBUG_UAF /* normal allocator */
276
Willy Tarreauf13322e2017-11-22 10:50:54 +0100277/* allocates an area of size <size> and returns it. The semantics are similar
278 * to those of malloc().
279 */
280static inline void *pool_alloc_area(size_t size)
281{
282 return malloc(size);
283}
284
285/* frees an area <area> of size <size> allocated by pool_alloc_area(). The
286 * semantics are identical to free() except that the size is specified and
287 * may be ignored.
288 */
289static inline void pool_free_area(void *area, size_t __maybe_unused size)
290{
291 free(area);
292}
293
Willy Tarreau158fa752017-11-22 15:47:29 +0100294#else /* use-after-free detector */
295
296/* allocates an area of size <size> and returns it. The semantics are similar
297 * to those of malloc(). However the allocation is rounded up to 4kB so that a
298 * full page is allocated. This ensures the object can be freed alone so that
299 * future dereferences are easily detected. The returned object is always
300 * 16-bytes aligned to avoid issues with unaligned structure objects.
301 */
302static inline void *pool_alloc_area(size_t size)
303{
304 size_t pad = (4096 - size) & 0xFF0;
305
306 return mmap(NULL, (size + 4095) & -4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0) + pad;
307}
308
309/* frees an area <area> of size <size> allocated by pool_alloc_area(). The
310 * semantics are identical to free() except that the size must absolutely match
311 * the one passed to pool_alloc_area().
312 */
313static inline void pool_free_area(void *area, size_t size)
314{
315 size_t pad = (4096 - size) & 0xFF0;
316
317 munmap(area - pad, (size + 4095) & -4096);
318}
319
320#endif /* DEBUG_UAF */
321
Willy Tarreau02622412014-12-08 16:35:23 +0100322/*
323 * Returns a pointer to type <type> taken from the pool <pool_type> or
324 * dynamically allocated. In the first case, <pool_type> is updated to point to
325 * the next element in the list. Memory poisonning is performed if enabled.
326 */
Willy Tarreaubafbe012017-11-24 17:34:44 +0100327static inline void *pool_alloc(struct pool_head *pool)
Willy Tarreau02622412014-12-08 16:35:23 +0100328{
329 void *p;
330
331 p = pool_alloc_dirty(pool);
Willy Tarreaude30a682015-10-28 15:23:51 +0100332#ifdef DEBUG_MEMORY_POOLS
333 if (p) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100334 HA_SPIN_LOCK(POOL_LOCK, &pool->lock);
Willy Tarreaude30a682015-10-28 15:23:51 +0100335 /* keep track of where the element was allocated from */
336 *POOL_LINK(pool, p) = (void *)pool;
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100337 HA_SPIN_UNLOCK(POOL_LOCK, &pool->lock);
Willy Tarreaude30a682015-10-28 15:23:51 +0100338 }
339#endif
340 if (p && mem_poison_byte >= 0) {
Willy Tarreau02622412014-12-08 16:35:23 +0100341 memset(p, mem_poison_byte, pool->size);
Willy Tarreaude30a682015-10-28 15:23:51 +0100342 }
343
Willy Tarreau02622412014-12-08 16:35:23 +0100344 return p;
345}
346
347/*
Willy Tarreau50e608d2007-05-13 18:26:08 +0200348 * Puts a memory area back to the corresponding pool.
349 * Items are chained directly through a pointer that
350 * is written in the beginning of the memory area, so
351 * there's no need for any carrier cell. This implies
352 * that each memory area is at least as big as one
Willy Tarreau48d63db2008-08-03 17:41:33 +0200353 * pointer. Just like with the libc's free(), nothing
354 * is done if <ptr> is NULL.
Willy Tarreau50e608d2007-05-13 18:26:08 +0200355 */
Willy Tarreaubafbe012017-11-24 17:34:44 +0100356static inline void pool_free(struct pool_head *pool, void *ptr)
Willy Tarreaue430e772014-12-23 14:13:16 +0100357{
358 if (likely(ptr != NULL)) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100359 HA_SPIN_LOCK(POOL_LOCK, &pool->lock);
Willy Tarreaude30a682015-10-28 15:23:51 +0100360#ifdef DEBUG_MEMORY_POOLS
361 /* we'll get late corruption if we refill to the wrong pool or double-free */
362 if (*POOL_LINK(pool, ptr) != (void *)pool)
363 *(int *)0 = 0;
364#endif
Willy Tarreau158fa752017-11-22 15:47:29 +0100365
366#ifndef DEBUG_UAF /* normal pool behaviour */
Willy Tarreauac421112015-10-28 15:09:29 +0100367 *POOL_LINK(pool, ptr) = (void *)pool->free_list;
Willy Tarreaue430e772014-12-23 14:13:16 +0100368 pool->free_list = (void *)ptr;
Willy Tarreau158fa752017-11-22 15:47:29 +0100369#else /* release the entry for real to detect use after free */
370 /* ensure we crash on double free or free of a const area*/
371 *(uint32_t *)ptr = 0xDEADADD4;
372 pool_free_area(ptr, pool->size + POOL_EXTRA);
373 pool->allocated--;
374#endif /* DEBUG_UAF */
Willy Tarreaue430e772014-12-23 14:13:16 +0100375 pool->used--;
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100376 HA_SPIN_UNLOCK(POOL_LOCK, &pool->lock);
Willy Tarreaue430e772014-12-23 14:13:16 +0100377 }
378}
Olivier Houchardcf975d42018-01-24 18:38:31 +0100379#endif /* HA_HAVE_CAS_DW */
Willy Tarreau2dd0d472006-06-29 17:53:05 +0200380#endif /* _COMMON_MEMORY_H */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200381
382/*
383 * Local variables:
384 * c-indent-level: 8
385 * c-basic-offset: 8
386 * End:
387 */