blob: 37f987c548ccf97c95a54de8d64ec893b77355c7 [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 Tarreaua1bd1fa2019-03-29 17:26:33 +010029#include <inttypes.h>
Willy Tarreaua7280a12018-11-26 19:41:40 +010030#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020031
Willy Tarreau2dd0d472006-06-29 17:53:05 +020032#include <common/config.h>
Willy Tarreau50e608d2007-05-13 18:26:08 +020033#include <common/mini-clist.h>
Christopher Fauletb349e482017-08-29 09:52:38 +020034#include <common/hathreads.h>
Willy Tarreau7107c8b2018-11-26 11:44:35 +010035#include <common/initcall.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020036
Willy Tarreau50e608d2007-05-13 18:26:08 +020037#define MEM_F_SHARED 0x1
Willy Tarreau581bf812016-01-25 02:19:13 +010038#define MEM_F_EXACT 0x2
Willy Tarreau50e608d2007-05-13 18:26:08 +020039
Willy Tarreauac421112015-10-28 15:09:29 +010040/* reserve an extra void* at the end of a pool for linking */
41#ifdef DEBUG_MEMORY_POOLS
42#define POOL_EXTRA (sizeof(void *))
43#define POOL_LINK(pool, item) (void **)(((char *)item) + (pool->size))
44#else
45#define POOL_EXTRA (0)
46#define POOL_LINK(pool, item) ((void **)(item))
47#endif
48
Willy Tarreau31cbc2e2021-06-09 18:59:58 +020049/* A special pointer for the pool's free_list that indicates someone is
50 * currently manipulating it. Serves as a short-lived lock.
51 */
52#define POOL_BUSY ((void *)1)
53
Willy Tarreaud3a82112020-06-30 14:29:02 +020054#ifndef MAX_BASE_POOLS
55#define MAX_BASE_POOLS 64
56#endif
Willy Tarreau0a93b642018-10-16 07:58:39 +020057
Willy Tarreaue18db9e2018-10-16 10:28:54 +020058struct pool_cache_head {
59 struct list list; /* head of objects in this pool */
60 size_t size; /* size of an object */
61 unsigned int count; /* number of objects in this pool */
62};
63
64struct pool_cache_item {
65 struct list by_pool; /* link to objects in this pool */
66 struct list by_lru; /* link to objects by LRU order */
67};
68
Willy Tarreau7f0165e2018-11-26 17:09:46 +010069extern struct pool_cache_head pool_cache[][MAX_BASE_POOLS];
Willy Tarreaue18db9e2018-10-16 10:28:54 +020070extern THREAD_LOCAL size_t pool_cache_bytes; /* total cache size */
71extern THREAD_LOCAL size_t pool_cache_count; /* #cache objects */
72
Willy Tarreauf161d0f2018-02-22 14:05:55 +010073#ifdef CONFIG_HAP_LOCKLESS_POOLS
Olivier Houchardcf975d42018-01-24 18:38:31 +010074struct pool_free_list {
75 void **free_list;
76 uintptr_t seq;
77};
78#endif
79
Willy Tarreau50e608d2007-05-13 18:26:08 +020080struct pool_head {
Willy Tarreau1ca1b702017-11-26 10:50:36 +010081 void **free_list;
Willy Tarreauf161d0f2018-02-22 14:05:55 +010082#ifdef CONFIG_HAP_LOCKLESS_POOLS
Olivier Houchardcf975d42018-01-24 18:38:31 +010083 uintptr_t seq;
Olivier Houchard5dfbf2e2020-03-18 15:48:29 +010084 HA_SPINLOCK_T flush_lock;
Olivier Houchardcf975d42018-01-24 18:38:31 +010085#else
86 __decl_hathreads(HA_SPINLOCK_T lock); /* the spin lock */
87#endif
Willy Tarreau50e608d2007-05-13 18:26:08 +020088 unsigned int used; /* how many chunks are currently in use */
89 unsigned int allocated; /* how many chunks have been allocated */
90 unsigned int limit; /* hard limit on the number of chunks */
91 unsigned int minavail; /* how many chunks are expected to be used */
92 unsigned int size; /* chunk size */
93 unsigned int flags; /* MEM_F_* */
Willy Tarreau7dcd46d2007-05-14 00:16:13 +020094 unsigned int users; /* number of pools sharing this zone */
Willy Tarreau58102cf2015-10-28 16:24:21 +010095 unsigned int failed; /* failed allocations */
Olivier Houchardcf975d42018-01-24 18:38:31 +010096 struct list list; /* list of all known pools */
Willy Tarreau7dcd46d2007-05-14 00:16:13 +020097 char name[12]; /* name of the pool */
Willy Tarreau1ca1b702017-11-26 10:50:36 +010098} __attribute__((aligned(64)));
Willy Tarreau50e608d2007-05-13 18:26:08 +020099
Willy Tarreau0a93b642018-10-16 07:58:39 +0200100
101extern struct pool_head pool_base_start[MAX_BASE_POOLS];
102extern unsigned int pool_base_count;
103
Willy Tarreau067ac9f2015-10-08 14:12:13 +0200104/* poison each newly allocated area with this byte if >= 0 */
105extern int mem_poison_byte;
Willy Tarreau50e608d2007-05-13 18:26:08 +0200106
Willy Tarreaua885f6d2014-12-03 15:25:28 +0100107/* Allocates new entries for pool <pool> until there are at least <avail> + 1
108 * available, then returns the last one for immediate use, so that at least
109 * <avail> are left available in the pool upon return. NULL is returned if the
110 * last entry could not be allocated. It's important to note that at least one
111 * allocation is always performed even if there are enough entries in the pool.
112 * A call to the garbage collector is performed at most once in case malloc()
113 * returns an error, before returning NULL.
Willy Tarreau50e608d2007-05-13 18:26:08 +0200114 */
Christopher Fauletb349e482017-08-29 09:52:38 +0200115void *__pool_refill_alloc(struct pool_head *pool, unsigned int avail);
Willy Tarreaua885f6d2014-12-03 15:25:28 +0100116void *pool_refill_alloc(struct pool_head *pool, unsigned int avail);
Willy Tarreau50e608d2007-05-13 18:26:08 +0200117
118/* Try to find an existing shared pool with the same characteristics and
119 * returns it, otherwise creates this one. NULL is returned if no memory
120 * is available for a new creation.
121 */
122struct pool_head *create_pool(char *name, unsigned int size, unsigned int flags);
Willy Tarreau7107c8b2018-11-26 11:44:35 +0100123void create_pool_callback(struct pool_head **ptr, char *name, unsigned int size);
124
125/* This registers a call to create_pool_callback(ptr, name, size) */
126#define REGISTER_POOL(ptr, name, size) \
127 INITCALL3(STG_POOL, create_pool_callback, (ptr), (name), (size))
128
129/* This macro declares a pool head <ptr> and registers its creation */
130#define DECLARE_POOL(ptr, name, size) \
131 struct pool_head *(ptr) = NULL; \
132 REGISTER_POOL(&ptr, name, size)
133
134/* This macro declares a static pool head <ptr> and registers its creation */
135#define DECLARE_STATIC_POOL(ptr, name, size) \
136 static struct pool_head *(ptr); \
137 REGISTER_POOL(&ptr, name, size)
Willy Tarreau50e608d2007-05-13 18:26:08 +0200138
139/* Dump statistics on pools usage.
140 */
Willy Tarreau12833bb2014-01-28 16:49:56 +0100141void dump_pools_to_trash();
Willy Tarreau50e608d2007-05-13 18:26:08 +0200142void dump_pools(void);
Willy Tarreau58102cf2015-10-28 16:24:21 +0100143int pool_total_failures();
144unsigned long pool_total_allocated();
145unsigned long pool_total_used();
Willy Tarreau50e608d2007-05-13 18:26:08 +0200146
147/*
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200148 * This function frees whatever can be freed in pool <pool>.
149 */
Willy Tarreaubafbe012017-11-24 17:34:44 +0100150void pool_flush(struct pool_head *pool);
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200151
152/*
153 * This function frees whatever can be freed in all pools, but respecting
154 * the minimum thresholds imposed by owners.
Christopher Fauletb349e482017-08-29 09:52:38 +0200155 *
Willy Tarreaubafbe012017-11-24 17:34:44 +0100156 * <pool_ctx> is used when pool_gc is called to release resources to allocate
Christopher Fauletb349e482017-08-29 09:52:38 +0200157 * an element in __pool_refill_alloc. It is important because <pool_ctx> is
158 * already locked, so we need to skip the lock here.
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200159 */
Willy Tarreaubafbe012017-11-24 17:34:44 +0100160void pool_gc(struct pool_head *pool_ctx);
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200161
162/*
163 * This function destroys a pull by freeing it completely.
164 * This should be called only under extreme circumstances.
165 */
Willy Tarreaubafbe012017-11-24 17:34:44 +0100166void *pool_destroy(struct pool_head *pool);
Willy Tarreau2455ceb2018-11-26 15:57:34 +0100167void pool_destroy_all();
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200168
Willy Tarreau0a93b642018-10-16 07:58:39 +0200169/* returns the pool index for pool <pool>, or -1 if this pool has no index */
170static inline ssize_t pool_get_index(const struct pool_head *pool)
171{
172 size_t idx;
173
174 idx = pool - pool_base_start;
175 if (idx >= MAX_BASE_POOLS)
176 return -1;
177 return idx;
178}
179
Willy Tarreauf161d0f2018-02-22 14:05:55 +0100180#ifdef CONFIG_HAP_LOCKLESS_POOLS
Willy Tarreaue18db9e2018-10-16 10:28:54 +0200181
182/* Tries to retrieve an object from the local pool cache corresponding to pool
183 * <pool>. Returns NULL if none is available.
184 */
185static inline void *__pool_get_from_cache(struct pool_head *pool)
186{
187 ssize_t idx = pool_get_index(pool);
188 struct pool_cache_item *item;
Willy Tarreau7f0165e2018-11-26 17:09:46 +0100189 struct pool_cache_head *ph;
Willy Tarreaue18db9e2018-10-16 10:28:54 +0200190
191 /* pool not in cache */
192 if (idx < 0)
193 return NULL;
194
Willy Tarreau7f0165e2018-11-26 17:09:46 +0100195 ph = &pool_cache[tid][idx];
196 if (LIST_ISEMPTY(&ph->list))
197 return NULL; // empty
Willy Tarreaue18db9e2018-10-16 10:28:54 +0200198
Willy Tarreau7f0165e2018-11-26 17:09:46 +0100199 item = LIST_NEXT(&ph->list, typeof(item), by_pool);
200 ph->count--;
201 pool_cache_bytes -= ph->size;
Willy Tarreaue18db9e2018-10-16 10:28:54 +0200202 pool_cache_count--;
203 LIST_DEL(&item->by_pool);
204 LIST_DEL(&item->by_lru);
Willy Tarreau8e9f4532018-10-28 20:09:12 +0100205#ifdef DEBUG_MEMORY_POOLS
206 /* keep track of where the element was allocated from */
207 *POOL_LINK(pool, item) = (void *)pool;
208#endif
Willy Tarreaue18db9e2018-10-16 10:28:54 +0200209 return item;
210}
211
Olivier Houchardcf975d42018-01-24 18:38:31 +0100212/*
213 * Returns a pointer to type <type> taken from the pool <pool_type> if
214 * available, otherwise returns NULL. No malloc() is attempted, and poisonning
215 * is never performed. The purpose is to get the fastest possible allocation.
216 */
217static inline void *__pool_get_first(struct pool_head *pool)
218{
Willy Tarreaue18db9e2018-10-16 10:28:54 +0200219 void *ret = __pool_get_from_cache(pool);
220
221 if (ret)
222 return ret;
Olivier Houchardcf975d42018-01-24 18:38:31 +0100223
Willy Tarreau31cbc2e2021-06-09 18:59:58 +0200224 /* we'll need to reference the first element to figure the next one. We
225 * must temporarily lock it so that nobody allocates then releases it,
226 * or the dereference could fail.
227 */
228 ret = pool->free_list;
Olivier Houchardcf975d42018-01-24 18:38:31 +0100229 do {
Willy Tarreau31cbc2e2021-06-09 18:59:58 +0200230 while (unlikely(ret == POOL_BUSY)) {
231 pl_cpu_relax();
232 ret = _HA_ATOMIC_LOAD(&pool->free_list);
233 }
234 if (ret == NULL)
235 return ret;
236 } while (unlikely((ret = _HA_ATOMIC_XCHG(&pool->free_list, POOL_BUSY)) == POOL_BUSY));
237
238 if (unlikely(ret == NULL)) {
239 _HA_ATOMIC_STORE(&pool->free_list, NULL);
240 goto out;
241 }
Tim Duesterhus05f6a432018-02-20 00:49:46 +0100242
Willy Tarreau31cbc2e2021-06-09 18:59:58 +0200243 /* this releases the lock */
244 _HA_ATOMIC_STORE(&pool->free_list, *POOL_LINK(pool, ret));
Olivier Houchard20872762019-03-08 18:53:35 +0100245 _HA_ATOMIC_ADD(&pool->used, 1);
Olivier Houchardcf975d42018-01-24 18:38:31 +0100246#ifdef DEBUG_MEMORY_POOLS
247 /* keep track of where the element was allocated from */
Willy Tarreau31cbc2e2021-06-09 18:59:58 +0200248 *POOL_LINK(pool, ret) = (void *)pool;
Olivier Houchardcf975d42018-01-24 18:38:31 +0100249#endif
Willy Tarreau31cbc2e2021-06-09 18:59:58 +0200250
251 out:
252 __ha_barrier_atomic_store();
253 return ret;
Olivier Houchardcf975d42018-01-24 18:38:31 +0100254}
255
256static inline void *pool_get_first(struct pool_head *pool)
257{
258 void *ret;
259
260 ret = __pool_get_first(pool);
261 return ret;
262}
263/*
264 * Returns a pointer to type <type> taken from the pool <pool_type> or
265 * dynamically allocated. In the first case, <pool_type> is updated to point to
266 * the next element in the list. No memory poisonning is ever performed on the
267 * returned area.
268 */
269static inline void *pool_alloc_dirty(struct pool_head *pool)
270{
271 void *p;
272
273 if ((p = __pool_get_first(pool)) == NULL)
274 p = __pool_refill_alloc(pool, 0);
275 return p;
276}
277
Willy Tarreaue6ce59d2007-05-13 19:38:49 +0200278/*
Olivier Houchardcf975d42018-01-24 18:38:31 +0100279 * Returns a pointer to type <type> taken from the pool <pool_type> or
280 * dynamically allocated. In the first case, <pool_type> is updated to point to
281 * the next element in the list. Memory poisonning is performed if enabled.
282 */
283static inline void *pool_alloc(struct pool_head *pool)
284{
285 void *p;
286
287 p = pool_alloc_dirty(pool);
Olivier Houchardcf975d42018-01-24 18:38:31 +0100288 if (p && mem_poison_byte >= 0) {
289 memset(p, mem_poison_byte, pool->size);
290 }
291
292 return p;
293}
294
Willy Tarreau146794d2018-10-16 08:55:15 +0200295/* Locklessly add item <ptr> to pool <pool>, then update the pool used count.
296 * Both the pool and the pointer must be valid. Use pool_free() for normal
297 * operations.
298 */
299static inline void __pool_free(struct pool_head *pool, void *ptr)
300{
Willy Tarreau31cbc2e2021-06-09 18:59:58 +0200301 void **free_list;
Willy Tarreau146794d2018-10-16 08:55:15 +0200302
Willy Tarreau31cbc2e2021-06-09 18:59:58 +0200303 _HA_ATOMIC_SUB(&pool->used, 1);
304 free_list = _HA_ATOMIC_LOAD(&pool->free_list);
Willy Tarreau146794d2018-10-16 08:55:15 +0200305 do {
Willy Tarreau31cbc2e2021-06-09 18:59:58 +0200306 while (unlikely(free_list == POOL_BUSY)) {
307 pl_cpu_relax();
308 free_list = _HA_ATOMIC_LOAD(&pool->free_list);
309 }
310 _HA_ATOMIC_STORE(POOL_LINK(pool, ptr), (void *)free_list);
311 __ha_barrier_atomic_store();
Olivier Houchard20872762019-03-08 18:53:35 +0100312 } while (!_HA_ATOMIC_CAS(&pool->free_list, &free_list, ptr));
313 __ha_barrier_atomic_store();
Willy Tarreau146794d2018-10-16 08:55:15 +0200314}
315
Willy Tarreaue18db9e2018-10-16 10:28:54 +0200316/* frees an object to the local cache, possibly pushing oldest objects to the
317 * global pool.
318 */
319void __pool_put_to_cache(struct pool_head *pool, void *ptr, ssize_t idx);
320static inline void pool_put_to_cache(struct pool_head *pool, void *ptr)
321{
322 ssize_t idx = pool_get_index(pool);
323
324 /* pool not in cache or too many objects for this pool (more than
325 * half of the cache is used and this pool uses more than 1/8 of
326 * the cache size).
327 */
328 if (idx < 0 ||
329 (pool_cache_bytes > CONFIG_HAP_POOL_CACHE_SIZE * 3 / 4 &&
Willy Tarreau7f0165e2018-11-26 17:09:46 +0100330 pool_cache[tid][idx].count >= 16 + pool_cache_count / 8)) {
Willy Tarreaue18db9e2018-10-16 10:28:54 +0200331 __pool_free(pool, ptr);
332 return;
333 }
334 __pool_put_to_cache(pool, ptr, idx);
335}
336
Olivier Houchardcf975d42018-01-24 18:38:31 +0100337/*
338 * Puts a memory area back to the corresponding pool.
339 * Items are chained directly through a pointer that
340 * is written in the beginning of the memory area, so
341 * there's no need for any carrier cell. This implies
342 * that each memory area is at least as big as one
343 * pointer. Just like with the libc's free(), nothing
344 * is done if <ptr> is NULL.
345 */
346static inline void pool_free(struct pool_head *pool, void *ptr)
347{
348 if (likely(ptr != NULL)) {
Olivier Houchardcf975d42018-01-24 18:38:31 +0100349#ifdef DEBUG_MEMORY_POOLS
350 /* we'll get late corruption if we refill to the wrong pool or double-free */
351 if (*POOL_LINK(pool, ptr) != (void *)pool)
352 *(volatile int *)0 = 0;
353#endif
Willy Tarreaubbcce3d2019-11-15 06:59:54 +0100354 if (mem_poison_byte >= 0)
355 memset(ptr, mem_poison_byte, pool->size);
Willy Tarreaue18db9e2018-10-16 10:28:54 +0200356 pool_put_to_cache(pool, ptr);
Olivier Houchardcf975d42018-01-24 18:38:31 +0100357 }
358}
359
Willy Tarreauf161d0f2018-02-22 14:05:55 +0100360#else /* CONFIG_HAP_LOCKLESS_POOLS */
Olivier Houchardcf975d42018-01-24 18:38:31 +0100361/*
Willy Tarreau02622412014-12-08 16:35:23 +0100362 * Returns a pointer to type <type> taken from the pool <pool_type> if
363 * available, otherwise returns NULL. No malloc() is attempted, and poisonning
364 * is never performed. The purpose is to get the fastest possible allocation.
Willy Tarreau50e608d2007-05-13 18:26:08 +0200365 */
Christopher Fauletb349e482017-08-29 09:52:38 +0200366static inline void *__pool_get_first(struct pool_head *pool)
Willy Tarreaue430e772014-12-23 14:13:16 +0100367{
368 void *p;
369
Willy Tarreau02622412014-12-08 16:35:23 +0100370 if ((p = pool->free_list) != NULL) {
Willy Tarreauac421112015-10-28 15:09:29 +0100371 pool->free_list = *POOL_LINK(pool, p);
Willy Tarreaue430e772014-12-23 14:13:16 +0100372 pool->used++;
Willy Tarreaude30a682015-10-28 15:23:51 +0100373#ifdef DEBUG_MEMORY_POOLS
374 /* keep track of where the element was allocated from */
375 *POOL_LINK(pool, p) = (void *)pool;
376#endif
Willy Tarreaue430e772014-12-23 14:13:16 +0100377 }
378 return p;
379}
Willy Tarreau50e608d2007-05-13 18:26:08 +0200380
Christopher Fauletb349e482017-08-29 09:52:38 +0200381static inline void *pool_get_first(struct pool_head *pool)
382{
383 void *ret;
384
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100385 HA_SPIN_LOCK(POOL_LOCK, &pool->lock);
Christopher Fauletb349e482017-08-29 09:52:38 +0200386 ret = __pool_get_first(pool);
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100387 HA_SPIN_UNLOCK(POOL_LOCK, &pool->lock);
Christopher Fauletb349e482017-08-29 09:52:38 +0200388 return ret;
389}
Willy Tarreau50e608d2007-05-13 18:26:08 +0200390/*
Willy Tarreau02622412014-12-08 16:35:23 +0100391 * Returns a pointer to type <type> taken from the pool <pool_type> or
392 * dynamically allocated. In the first case, <pool_type> is updated to point to
393 * the next element in the list. No memory poisonning is ever performed on the
394 * returned area.
395 */
396static inline void *pool_alloc_dirty(struct pool_head *pool)
397{
398 void *p;
399
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100400 HA_SPIN_LOCK(POOL_LOCK, &pool->lock);
Christopher Fauletb349e482017-08-29 09:52:38 +0200401 if ((p = __pool_get_first(pool)) == NULL)
402 p = __pool_refill_alloc(pool, 0);
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100403 HA_SPIN_UNLOCK(POOL_LOCK, &pool->lock);
Willy Tarreau02622412014-12-08 16:35:23 +0100404 return p;
405}
406
Willy Tarreau158fa752017-11-22 15:47:29 +0100407#ifndef DEBUG_UAF /* normal allocator */
408
Willy Tarreauf13322e2017-11-22 10:50:54 +0100409/* allocates an area of size <size> and returns it. The semantics are similar
410 * to those of malloc().
411 */
412static inline void *pool_alloc_area(size_t size)
413{
414 return malloc(size);
415}
416
417/* frees an area <area> of size <size> allocated by pool_alloc_area(). The
418 * semantics are identical to free() except that the size is specified and
419 * may be ignored.
420 */
421static inline void pool_free_area(void *area, size_t __maybe_unused size)
422{
423 free(area);
424}
425
Willy Tarreau158fa752017-11-22 15:47:29 +0100426#else /* use-after-free detector */
427
428/* allocates an area of size <size> and returns it. The semantics are similar
429 * to those of malloc(). However the allocation is rounded up to 4kB so that a
430 * full page is allocated. This ensures the object can be freed alone so that
431 * future dereferences are easily detected. The returned object is always
Willy Tarreau364d7452018-02-22 14:14:23 +0100432 * 16-bytes aligned to avoid issues with unaligned structure objects. In case
433 * some padding is added, the area's start address is copied at the end of the
434 * padding to help detect underflows.
Willy Tarreau158fa752017-11-22 15:47:29 +0100435 */
Olivier Houchard62975a72018-10-21 01:33:11 +0200436#include <errno.h>
Willy Tarreau158fa752017-11-22 15:47:29 +0100437static inline void *pool_alloc_area(size_t size)
438{
439 size_t pad = (4096 - size) & 0xFF0;
Willy Tarreau5a9cce42018-02-22 11:39:23 +0100440 void *ret;
Willy Tarreau158fa752017-11-22 15:47:29 +0100441
Olivier Houchard62975a72018-10-21 01:33:11 +0200442 ret = mmap(NULL, (size + 4095) & -4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
Willy Tarreau364d7452018-02-22 14:14:23 +0100443 if (ret == MAP_FAILED)
444 return NULL;
445 if (pad >= sizeof(void *))
446 *(void **)(ret + pad - sizeof(void *)) = ret + pad;
447 return ret + pad;
Willy Tarreau158fa752017-11-22 15:47:29 +0100448}
449
450/* frees an area <area> of size <size> allocated by pool_alloc_area(). The
451 * semantics are identical to free() except that the size must absolutely match
Willy Tarreau364d7452018-02-22 14:14:23 +0100452 * the one passed to pool_alloc_area(). In case some padding is added, the
453 * area's start address is compared to the one at the end of the padding, and
454 * a segfault is triggered if they don't match, indicating an underflow.
Willy Tarreau158fa752017-11-22 15:47:29 +0100455 */
456static inline void pool_free_area(void *area, size_t size)
457{
458 size_t pad = (4096 - size) & 0xFF0;
459
Willy Tarreau364d7452018-02-22 14:14:23 +0100460 if (pad >= sizeof(void *) && *(void **)(area - sizeof(void *)) != area)
461 *(volatile int *)0 = 0;
462
Willy Tarreau158fa752017-11-22 15:47:29 +0100463 munmap(area - pad, (size + 4095) & -4096);
464}
465
466#endif /* DEBUG_UAF */
467
Willy Tarreau02622412014-12-08 16:35:23 +0100468/*
469 * Returns a pointer to type <type> taken from the pool <pool_type> or
470 * dynamically allocated. In the first case, <pool_type> is updated to point to
471 * the next element in the list. Memory poisonning is performed if enabled.
472 */
Willy Tarreaubafbe012017-11-24 17:34:44 +0100473static inline void *pool_alloc(struct pool_head *pool)
Willy Tarreau02622412014-12-08 16:35:23 +0100474{
475 void *p;
476
477 p = pool_alloc_dirty(pool);
Willy Tarreaude30a682015-10-28 15:23:51 +0100478 if (p && mem_poison_byte >= 0) {
Willy Tarreau02622412014-12-08 16:35:23 +0100479 memset(p, mem_poison_byte, pool->size);
Willy Tarreaude30a682015-10-28 15:23:51 +0100480 }
481
Willy Tarreau02622412014-12-08 16:35:23 +0100482 return p;
483}
484
485/*
Willy Tarreau50e608d2007-05-13 18:26:08 +0200486 * Puts a memory area back to the corresponding pool.
487 * Items are chained directly through a pointer that
488 * is written in the beginning of the memory area, so
489 * there's no need for any carrier cell. This implies
490 * that each memory area is at least as big as one
Willy Tarreau48d63db2008-08-03 17:41:33 +0200491 * pointer. Just like with the libc's free(), nothing
492 * is done if <ptr> is NULL.
Willy Tarreau50e608d2007-05-13 18:26:08 +0200493 */
Willy Tarreaubafbe012017-11-24 17:34:44 +0100494static inline void pool_free(struct pool_head *pool, void *ptr)
Willy Tarreaue430e772014-12-23 14:13:16 +0100495{
496 if (likely(ptr != NULL)) {
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100497 HA_SPIN_LOCK(POOL_LOCK, &pool->lock);
Willy Tarreaude30a682015-10-28 15:23:51 +0100498#ifdef DEBUG_MEMORY_POOLS
499 /* we'll get late corruption if we refill to the wrong pool or double-free */
500 if (*POOL_LINK(pool, ptr) != (void *)pool)
Olivier Houchard51e47412018-12-16 00:58:28 +0100501 *(volatile int *)0 = 0;
Willy Tarreaude30a682015-10-28 15:23:51 +0100502#endif
Willy Tarreau158fa752017-11-22 15:47:29 +0100503
504#ifndef DEBUG_UAF /* normal pool behaviour */
Willy Tarreauac421112015-10-28 15:09:29 +0100505 *POOL_LINK(pool, ptr) = (void *)pool->free_list;
Willy Tarreaue430e772014-12-23 14:13:16 +0100506 pool->free_list = (void *)ptr;
Willy Tarreau158fa752017-11-22 15:47:29 +0100507#else /* release the entry for real to detect use after free */
508 /* ensure we crash on double free or free of a const area*/
509 *(uint32_t *)ptr = 0xDEADADD4;
510 pool_free_area(ptr, pool->size + POOL_EXTRA);
511 pool->allocated--;
512#endif /* DEBUG_UAF */
Willy Tarreaue430e772014-12-23 14:13:16 +0100513 pool->used--;
Christopher Faulet2a944ee2017-11-07 10:42:54 +0100514 HA_SPIN_UNLOCK(POOL_LOCK, &pool->lock);
Willy Tarreaue430e772014-12-23 14:13:16 +0100515 }
516}
Willy Tarreauf161d0f2018-02-22 14:05:55 +0100517#endif /* CONFIG_HAP_LOCKLESS_POOLS */
Willy Tarreau2dd0d472006-06-29 17:53:05 +0200518#endif /* _COMMON_MEMORY_H */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200519
520/*
521 * Local variables:
522 * c-indent-level: 8
523 * c-basic-offset: 8
524 * End:
525 */