view src/lib/mempool-system.c @ 6300:7d82a232b5b0 HEAD

pool_system_realloc(): Moved malloc_usable_size() check before realloc() so that we don't assert-crash if realloc() shrinks memory.
author Timo Sirainen <tss@iki.fi>
date Thu, 16 Aug 2007 17:23:11 +0300
parents 48fe4fe9ef64
children 6a64e64fa3a3
line wrap: on
line source

/* Copyright (c) 2002-2003 Timo Sirainen */

/* @UNSAFE: whole file */

#include "lib.h"
#include "mempool.h"

#include <stdlib.h>
#ifdef HAVE_MALLOC_H
#  include <malloc.h>
#endif

#ifdef HAVE_GC_GC_H
#  include <gc/gc.h>
#elif defined (HAVE_GC_H)
#  include <gc.h>
#endif

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_free(pool_t pool, void *mem);
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 = {
	MEMBER(v) &static_system_pool_vfuncs,

	MEMBER(alloconly_pool) FALSE,
	MEMBER(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;

	if (size == 0 || size > SSIZE_T_MAX)
		i_panic("Trying to allocate %"PRIuSIZE_T" bytes", size);

#ifndef USE_GC
	mem = calloc(size, 1);
#else
	mem = GC_malloc(size);
#endif
	if (mem == NULL) {
		i_fatal_status(FATAL_OUTOFMEM,
			       "pool_system_malloc(): Out of memory");
	}
	return mem;
}

static void pool_system_free(pool_t pool __attr_unused__,
			     void *mem __attr_unused__)
{
#ifndef USE_GC
	if (mem != NULL)
		free(mem);
#endif
}

static void *pool_system_realloc(pool_t pool __attr_unused__, void *mem,
				 size_t old_size, size_t new_size)
{
	if (new_size == 0 || new_size > SSIZE_T_MAX)
		i_panic("Trying to allocate %"PRIuSIZE_T" bytes", new_size);

#if !defined(USE_GC) && defined(HAVE_MALLOC_USABLE_SIZE)
	i_assert(old_size == (size_t)-1 || mem == NULL ||
		 old_size <= malloc_usable_size(mem));
#endif

#ifndef USE_GC
	mem = realloc(mem, new_size);
#else
	mem = GC_realloc(mem, new_size);
#endif
	if (mem == NULL) {
		i_fatal_status(FATAL_OUTOFMEM,
			       "pool_system_realloc(): Out of memory");
	}

	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;
}