mempool.h revision 9fc1a772651e6f146ed6da5ee33fcb6452dd45db
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen#ifndef __MEMPOOL_H
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Bosch#define __MEMPOOL_H
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Bosch
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen#include "macros.h"
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Bosch
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Bosch/* When DEBUG is enabled, Dovecot warns whenever a memory pool is grown.
e5a55bb6b867ee3ed95ac216996ff2e24bd596ccAki Tuomi This is done so that the initial pool size could be set large enough so that
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Bosch it wouldn't grow in normal use. For some memory pools it's too difficult
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Bosch to calculate a good initial size, so this prefix should be used with those
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Bosch pools to disable the warning. */
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Bosch#define MEMPOOL_GROWING "GROWING-"
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Bosch
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Bosch/* Memory allocated and reallocated (the new data in it) in pools is always
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Bosch zeroed, it will cost only a few CPU cycles and may well save some debug
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Bosch time. */
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Bosch
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Boschtypedef struct pool *pool_t;
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Bosch
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Boschstruct pool_vfuncs {
9b3565b09683b48f66de51aebb52786934d1c324Timo Sirainen const char *(*get_name)(pool_t pool);
9b3565b09683b48f66de51aebb52786934d1c324Timo Sirainen
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Bosch void (*ref)(pool_t pool);
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Bosch void (*unref)(pool_t *pool);
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Bosch
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Bosch void *(*malloc)(pool_t pool, size_t size);
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Bosch void (*free)(pool_t pool, void *mem);
9b3565b09683b48f66de51aebb52786934d1c324Timo Sirainen
9b3565b09683b48f66de51aebb52786934d1c324Timo Sirainen /* memory in old_size..new_size will be zeroed */
9b3565b09683b48f66de51aebb52786934d1c324Timo Sirainen void *(*realloc)(pool_t pool, void *mem,
9b3565b09683b48f66de51aebb52786934d1c324Timo Sirainen size_t old_size, size_t new_size)
9b3565b09683b48f66de51aebb52786934d1c324Timo Sirainen __attr_warn_unused_result__;
9b3565b09683b48f66de51aebb52786934d1c324Timo Sirainen
9b3565b09683b48f66de51aebb52786934d1c324Timo Sirainen /* Frees all the memory in pool. NOTE: system_pool doesn't support
9b3565b09683b48f66de51aebb52786934d1c324Timo Sirainen this and crashes if it's used */
9b3565b09683b48f66de51aebb52786934d1c324Timo Sirainen void (*clear)(pool_t pool);
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Bosch
9b3565b09683b48f66de51aebb52786934d1c324Timo Sirainen /* Returns the maximum amount of bytes that can be allocated with
9b3565b09683b48f66de51aebb52786934d1c324Timo Sirainen minimal trouble. If there's no such concept, always returns 0. */
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Bosch size_t (*get_max_easy_alloc_size)(pool_t pool);
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Bosch};
9b3565b09683b48f66de51aebb52786934d1c324Timo Sirainen
9b3565b09683b48f66de51aebb52786934d1c324Timo Sirainenstruct pool {
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Bosch const struct pool_vfuncs *v;
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Bosch
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Bosch unsigned int alloconly_pool:1;
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Bosch unsigned int datastack_pool:1;
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Bosch};
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Bosch
9b3565b09683b48f66de51aebb52786934d1c324Timo Sirainen/* system_pool uses calloc() + realloc() + free() */
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Boschextern pool_t system_pool;
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Bosch
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Bosch/* memory allocated from data_stack is valid only until next t_pop() call.
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Bosch No checks are performed. */
72a7c4f2ba93a723e23c941369a2985d75f240c9Stephan Boschextern pool_t unsafe_data_stack_pool;
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen/* Create a new alloc-only pool. Note that `size' specifies the initial
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen malloc()ed block size, part of it is used internally. */
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainenpool_t pool_alloconly_create(const char *name, size_t size);
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen/* Like alloconly pool, but clear the memory before freeing it. The idea is
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen that you could allocate memory for storing sensitive information from this
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen pool, and be sure that it gets cleared from the memory when it's no longer
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen needed. */
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainenpool_t pool_alloconly_create_clean(const char *name, size_t size);
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen/* When allocating memory from returned pool, the data stack frame must be
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen the same as it was when calling this function. pool_unref() also checks
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen that the stack frame is the same. This should make it quite safe to use. */
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainenpool_t pool_datastack_create(void);
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen/* Similar to nearest_power(), but try not to exceed buffer's easy
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen allocation size. If you don't have any explicit minimum size, use
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen old_size + 1. */
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainensize_t pool_get_exp_grown_size(pool_t pool, size_t old_size, size_t min_size);
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen/* Pools should be used through these macros: */
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen#define pool_get_name(pool) (pool)->v->get_name(pool)
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen#define pool_ref(pool) (pool)->v->ref(pool)
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen#define pool_unref(pool) (pool)->v->unref(&(pool))
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen#define p_new(pool, type, count) \
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen ((type *) p_malloc(pool, sizeof(type) * (count)))
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen
a071ae737f338f94d2e72c54930b51a1dc336815Timo Sirainen#define p_malloc(pool, size) (pool)->v->malloc(pool, size)
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen#define p_realloc(pool, mem, old_size, new_size) \
a071ae737f338f94d2e72c54930b51a1dc336815Timo Sirainen (pool)->v->realloc(pool, mem, old_size, new_size)
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen/* Free the memory. Currently it also sets memory to NULL, but that shouldn't
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen be relied on as it's only an extra safety check. It might as well be later
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen changed to some invalid pointer causing a segfault, or removed completely
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen in some "optimization".. */
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen#define p_free(pool, mem) \
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen STMT_START { \
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen (pool)->v->free(pool, mem); \
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen (mem) = NULL; \
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen } STMT_END
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen/* A macro that's guaranteed to set mem = NULL. */
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen#define p_free_and_null(pool, mem) p_free(pool, mem)
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen#define p_clear(pool) (pool)->v->clear(pool)
7f52e276c1bf13b4809344492023b90e46c3ac5dTimo Sirainen
e5a55bb6b867ee3ed95ac216996ff2e24bd596ccAki Tuomi#define p_get_max_easy_alloc_size(pool) \
e5a55bb6b867ee3ed95ac216996ff2e24bd596ccAki Tuomi (pool)->v->get_max_easy_alloc_size(pool)
e5a55bb6b867ee3ed95ac216996ff2e24bd596ccAki Tuomi
e5a55bb6b867ee3ed95ac216996ff2e24bd596ccAki Tuomi#endif
e5a55bb6b867ee3ed95ac216996ff2e24bd596ccAki Tuomi