diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:51:24 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:51:24 +0000 |
commit | f7548d6d28c313cf80e6f3ef89aed16a19815df1 (patch) | |
tree | a3f6f2a3f247293bee59ecd28e8cd8ceb6ca064a /src/lib/mempool-system.c | |
parent | Initial commit. (diff) | |
download | dovecot-upstream.tar.xz dovecot-upstream.zip |
Adding upstream version 1:2.3.19.1+dfsg1.upstream/1%2.3.19.1+dfsg1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/lib/mempool-system.c')
-rw-r--r-- | src/lib/mempool-system.c | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/src/lib/mempool-system.c b/src/lib/mempool-system.c new file mode 100644 index 0000000..7d1addc --- /dev/null +++ b/src/lib/mempool-system.c @@ -0,0 +1,163 @@ +/* Copyright (c) 2002-2018 Dovecot authors, see the included COPYING file */ + +/* @UNSAFE: whole file */ + +#include "lib.h" +#include "safe-memset.h" +#include "mempool.h" + +/* + * The system pool is a thin wrapper around calloc() and free(). It exists + * to allow direct heap usage via the pool API. + * + * Implementation + * ============== + * + * Creation + * -------- + * + * The system pool is created statically and therefore is available at any + * time. + * + * Allocation, Reallocation & Freeing + * ---------------------------------- + * + * The p_malloc(), p_realloc(), and p_free() calls get directed to calloc(), + * realloc(), and free(). There is no additional per-allocation information + * to track. + * + * Clearing + * -------- + * + * Not supported. Attempting to clear the system pool will result in a + * panic. + * + * Destruction + * ----------- + * + * It is not possible to destroy the system pool. Any attempt to unref the + * pool is a no-op. + */ + +#ifndef HAVE_MALLOC_USABLE_SIZE +/* no extra includes needed */ +#elif defined (HAVE_MALLOC_NP_H) +# include <malloc_np.h> /* FreeBSD */ +#elif defined (HAVE_MALLOC_H) +# include <malloc.h> /* Linux */ +#endif + +#define CLEAR_CHR 0xde + +static const char *pool_system_get_name(pool_t pool); +static void pool_system_ref(pool_t pool); +static void pool_system_unref(pool_t *pool); +static void *pool_system_malloc(pool_t pool, size_t size); +static void *pool_system_realloc(pool_t pool, void *mem, + size_t old_size, size_t new_size); +static void pool_system_clear(pool_t pool); +static size_t pool_system_get_max_easy_alloc_size(pool_t pool); + +static struct pool_vfuncs static_system_pool_vfuncs = { + pool_system_get_name, + + pool_system_ref, + pool_system_unref, + + pool_system_malloc, + pool_system_free, + + pool_system_realloc, + + pool_system_clear, + pool_system_get_max_easy_alloc_size +}; + +struct pool static_system_pool = { + .v = &static_system_pool_vfuncs, + + .alloconly_pool = FALSE, + .datastack_pool = FALSE +}; + +pool_t system_pool = &static_system_pool; + +static const char *pool_system_get_name(pool_t pool ATTR_UNUSED) +{ + return "system"; +} + +static void pool_system_ref(pool_t pool ATTR_UNUSED) +{ +} + +static void pool_system_unref(pool_t *pool ATTR_UNUSED) +{ +} + +static void *pool_system_malloc(pool_t pool ATTR_UNUSED, size_t size) +{ + void *mem; +#ifdef DEBUG + int old_errno = errno; +#endif + + mem = calloc(size, 1); + if (unlikely(mem == NULL)) { + i_fatal_status(FATAL_OUTOFMEM, "pool_system_malloc(%zu): " + "Out of memory", size); + } +#ifdef DEBUG + /* we rely on errno not changing. it shouldn't. */ + i_assert(errno == old_errno); +#endif + return mem; +} + +void pool_system_free(pool_t pool ATTR_UNUSED, void *mem ATTR_UNUSED) +{ +#ifdef DEBUG + int old_errno = errno; +#endif +#if defined(HAVE_MALLOC_USABLE_SIZE) && defined(DEBUG) + safe_memset(mem, CLEAR_CHR, malloc_usable_size(mem)); +#endif + free(mem); +#ifdef DEBUG + /* we rely on errno not changing. it shouldn't. */ + i_assert(errno == old_errno); +#endif +} + +static void *pool_system_realloc(pool_t pool ATTR_UNUSED, void *mem, + size_t old_size, size_t new_size) +{ +#if defined(HAVE_MALLOC_USABLE_SIZE) + i_assert(old_size == SIZE_MAX || mem == NULL || + old_size <= malloc_usable_size(mem)); +#endif + + mem = realloc(mem, new_size); + if (unlikely(mem == NULL)) { + i_fatal_status(FATAL_OUTOFMEM, "pool_system_realloc(%zu): " + "Out of memory", new_size); + } + + if (old_size < new_size) { + /* clear new data */ + memset((char *) mem + old_size, 0, new_size - old_size); + } + + return mem; +} + +static void ATTR_NORETURN +pool_system_clear(pool_t pool ATTR_UNUSED) +{ + i_panic("pool_system_clear() must not be called"); +} + +static size_t pool_system_get_max_easy_alloc_size(pool_t pool ATTR_UNUSED) +{ + return 0; +} |