mempool-system-clean.c revision 2b9884cebb11fdcdfd2959afcd35063d608c287b
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose/* Copyright (c) 2007-2008 Dovecot authors, see the included COPYING file */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose/* @UNSAFE: whole file */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#include "lib.h"
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#include "safe-memset.h"
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#include "mempool.h"
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#ifdef HAVE_MALLOC_H
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose# include <malloc.h>
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#endif
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#ifdef HAVE_MALLOC_NP_H
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose# include <malloc_np.h> /* for malloc_usable_size() with FreeBSD */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#endif
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#include <stdlib.h>
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#ifdef HAVE_GC_GC_H
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose# include <gc/gc.h>
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#elif defined (HAVE_GC_H)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose# include <gc.h>
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#endif
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose/* use the maximum of required memory alignment and sizeof(void *)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose (sizeof(size_t) is assumed to be same. it always is.) */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#if MEM_ALIGN_SIZE > SIZEOF_VOID_P
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose# define EXTRA_SIZE_SPACE MEM_ALIGN_SIZE
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#else
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose# define EXTRA_SIZE_SPACE SIZEOF_VOID_P
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#endif
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose/* FIXME: Disabled for now, broken with Valgrind and HP-UX. */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#undef HAVE_MALLOC_USABLE_SIZE
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic const char *pool_system_clean_get_name(pool_t pool);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic void pool_system_clean_ref(pool_t pool);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic void pool_system_clean_unref(pool_t *pool);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic void *pool_system_clean_malloc(pool_t pool, size_t size);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic void pool_system_clean_free(pool_t pool, void *mem);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic void *pool_system_clean_realloc(pool_t pool, void *mem,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose size_t old_size, size_t new_size);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic void pool_system_clean_clear(pool_t pool);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic size_t pool_system_clean_get_max_easy_alloc_size(pool_t pool);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic struct pool_vfuncs static_system_clean_pool_vfuncs = {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose pool_system_clean_get_name,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose pool_system_clean_ref,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose pool_system_clean_unref,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose pool_system_clean_malloc,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose pool_system_clean_free,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose pool_system_clean_realloc,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose pool_system_clean_clear,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose pool_system_clean_get_max_easy_alloc_size
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose};
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic struct pool static_system_clean_pool = {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose MEMBER(v) &static_system_clean_pool_vfuncs,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose MEMBER(alloconly_pool) FALSE,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose MEMBER(datastack_pool) FALSE
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose};
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosepool_t system_clean_pool = &static_system_clean_pool;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic const char *pool_system_clean_get_name(pool_t pool ATTR_UNUSED)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return "system clean";
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic void pool_system_clean_ref(pool_t pool ATTR_UNUSED)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic void pool_system_clean_unref(pool_t *pool ATTR_UNUSED)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic size_t mem_get_size(void *mem)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#ifdef USE_GC
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return GC_size(mem);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#elif defined(HAVE_MALLOC_USABLE_SIZE)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return malloc_usable_size(mem);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#else
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return *((size_t *)PTR_OFFSET(mem, -EXTRA_SIZE_SPACE));
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#endif
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic void *pool_system_clean_malloc(pool_t pool ATTR_UNUSED, size_t size)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose void *mem;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (unlikely(size == 0 || size > SSIZE_T_MAX))
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose i_panic("Trying to allocate %"PRIuSIZE_T" bytes", size);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#ifdef USE_GC
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose mem = GC_malloc(size);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#else
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#ifndef HAVE_MALLOC_USABLE_SIZE
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose size += EXTRA_SIZE_SPACE;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#endif
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose mem = calloc(size, 1);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#endif
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (unlikely(mem == NULL)) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose i_fatal_status(FATAL_OUTOFMEM, "pool_system_malloc(%"PRIuSIZE_T
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose "): Out of memory", size);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#if !defined(USE_GC) && !defined(HAVE_MALLOC_USABLE_SIZE)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose size_t *saved_size = mem;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose *saved_size = size - EXTRA_SIZE_SPACE;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose mem = PTR_OFFSET(mem, EXTRA_SIZE_SPACE);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#endif
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return mem;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic void pool_system_clean_free(pool_t pool ATTR_UNUSED, void *mem)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (mem != NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose safe_memset(mem, 0, mem_get_size(mem));
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#ifndef USE_GC
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#ifndef HAVE_MALLOC_USABLE_SIZE
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose mem = PTR_OFFSET(mem, -EXTRA_SIZE_SPACE);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#endif
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose free(mem);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#endif
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic void *pool_system_clean_realloc(pool_t pool ATTR_UNUSED, void *mem,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose size_t old_size, size_t new_size)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose void *new_mem;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (unlikely(new_size == 0 || new_size > SSIZE_T_MAX))
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose i_panic("Trying to allocate %"PRIuSIZE_T" bytes", new_size);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose new_mem = pool_system_clean_malloc(pool, new_size);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (mem != NULL) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#if !defined(USE_GC) && defined(HAVE_MALLOC_USABLE_SIZE)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose i_assert(old_size == (size_t)-1 ||
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose old_size <= malloc_usable_size(mem));
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose#endif
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose memcpy(new_mem, mem, mem_get_size(mem));
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose pool_system_clean_free(pool, mem);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose if (old_size < new_size) {
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose /* clear new data */
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose memset((char *)new_mem + old_size, 0,
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose new_size - old_size);
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose }
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return new_mem;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic void ATTR_NORETURN
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosepool_system_clean_clear(pool_t pool ATTR_UNUSED)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose i_panic("pool_system_clean_clear() must not be called");
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosestatic size_t
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bosepool_system_clean_get_max_easy_alloc_size(pool_t pool ATTR_UNUSED)
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose{
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose return 0;
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose}
db36dca3d45e6eefbb30042ee65876566f1a6014Sumit Bose