mempool-alloconly.c revision 1bb6586a424225406d55f9fc52a1f11579563073
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2002-2003 Timo Sirainen */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* @UNSAFE: whole file */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#include "lib.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mempool.h"
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen#include <stdlib.h>
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#ifdef HAVE_GC_GC_H
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen# include <gc/gc.h>
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#elif defined (HAVE_GC_H)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen# include <gc.h>
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#endif
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#define MAX_ALLOC_SIZE SSIZE_T_MAX
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstruct alloconly_pool {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct pool pool;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen int refcount;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct pool_block *block;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen char name[MEM_ALIGN_SIZE]; /* variable size */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen};
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#define SIZEOF_ALLOCONLYPOOL (sizeof(struct alloconly_pool)-MEM_ALIGN_SIZE)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstruct pool_block {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct pool_block *prev;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen size_t size;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen size_t left;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen size_t last_alloc_size;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen /* unsigned char data[]; */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen};
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#define SIZEOF_POOLBLOCK (MEM_ALIGN(sizeof(struct pool_block)))
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#define POOL_BLOCK_DATA(block) \
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen ((char *) (block) + SIZEOF_POOLBLOCK)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic const char *pool_alloconly_get_name(pool_t pool);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void pool_alloconly_ref(pool_t pool);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void pool_alloconly_unref(pool_t pool);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void *pool_alloconly_malloc(pool_t pool, size_t size);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void pool_alloconly_free(pool_t pool, void *mem);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void *pool_alloconly_realloc(pool_t pool, void *mem,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen size_t old_size, size_t new_size);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void pool_alloconly_clear(pool_t pool);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void block_alloc(struct alloconly_pool *pool, size_t size);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic struct pool static_alloconly_pool = {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen pool_alloconly_get_name,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen pool_alloconly_ref,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen pool_alloconly_unref,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen pool_alloconly_malloc,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen pool_alloconly_free,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen pool_alloconly_realloc,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen pool_alloconly_clear,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen TRUE,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen FALSE
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen};
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenpool_t pool_alloconly_create(const char *name, size_t size)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct alloconly_pool *apool;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen size_t len;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen len = strlen(name)+1;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#ifndef USE_GC
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen apool = calloc(SIZEOF_ALLOCONLYPOOL + len, 1);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#else
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen apool = GC_malloc(SIZEOF_ALLOCONLYPOOL + len);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen memset(apool, 0, SIZEOF_ALLOCONLYPOOL + len);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#endif
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (apool == NULL)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_panic("pool_alloconly_create(): Out of memory");
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen apool->pool = static_alloconly_pool;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen apool->refcount = 1;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen memcpy(apool->name, name, len);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen block_alloc(apool, size);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return (struct pool *) apool;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void pool_alloconly_destroy(struct alloconly_pool *apool)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen /* destroy all but the last block */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen pool_alloconly_clear(&apool->pool);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen /* destroy the last block */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#ifdef DEBUG
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen memset(apool->block, 0xde, SIZEOF_POOLBLOCK + apool->block->size);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#endif
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#ifndef USE_GC
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen free(apool->block);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen free(apool);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#else
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen apool->block = NULL;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen apool = NULL;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#endif
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic const char *pool_alloconly_get_name(pool_t pool)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct alloconly_pool *apool = (struct alloconly_pool *) pool;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen return apool->name;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void pool_alloconly_ref(pool_t pool)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct alloconly_pool *apool = (struct alloconly_pool *) pool;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen apool->refcount++;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void pool_alloconly_unref(pool_t pool)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct alloconly_pool *apool = (struct alloconly_pool *) pool;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (--apool->refcount == 0)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen pool_alloconly_destroy(apool);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void block_alloc(struct alloconly_pool *apool, size_t size)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct pool_block *block;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen /* each block is at least twice the size of the previous one */
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (apool->block != NULL && size <= apool->block->size)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen size += apool->block->size;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen size = nearest_power(size + SIZEOF_POOLBLOCK);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#ifdef DEBUG
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (apool->block != NULL) {
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_warning("Growing pool '%s' with: %"PRIuSIZE_T,
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen apool->name, size);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen }
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#endif
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#ifndef USE_GC
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen block = calloc(size, 1);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#else
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen block = GC_malloc(size);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen memset(block, 0, size);
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen#endif
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (block == NULL)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen i_panic("block_alloc(): Out of memory");
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen block->prev = apool->block;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen apool->block = block;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen block->size = size - SIZEOF_POOLBLOCK;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen block->left = block->size;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen}
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainenstatic void *pool_alloconly_malloc(pool_t pool, size_t size)
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen{
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen struct alloconly_pool *apool = (struct alloconly_pool *) pool;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen void *mem;
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen
0c17af9d3f9323136a94e66605776ed4462a172dTimo Sirainen if (size == 0 || size > SSIZE_T_MAX)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_panic("Trying to allocate %"PRIuSIZE_T" bytes", size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen size = MEM_ALIGN(size);
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (apool->block->left < size) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* we need a new block */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen block_alloc(apool, size);
4dc8837ab37c1a606add1067e21ed868754db4e3Timo Sirainen }
8e5fedd9ada47735be8ac0f8af2a66e8528bd776Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mem = POOL_BLOCK_DATA(apool->block) +
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (apool->block->size - apool->block->left);
e8bdf1be00aec45d0c6dd72ad9c8be02a3dfc778Timo Sirainen
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen apool->block->left -= size;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen apool->block->last_alloc_size = size;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return mem;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen}
2abfef71398a61e5ed97c23a1ceb71461933ccb8Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void pool_alloconly_free(pool_t pool, void *mem)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct alloconly_pool *apool = (struct alloconly_pool *) pool;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* we can free only the last allocation */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (POOL_BLOCK_DATA(apool->block) +
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen (apool->block->size - apool->block->left -
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen apool->block->last_alloc_size) == mem) {
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen memset(mem, 0, apool->block->last_alloc_size);
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen apool->block->left += apool->block->last_alloc_size;
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen apool->block->last_alloc_size = 0;
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen }
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen}
b66a7b7ab0db2c9ad425912d3f21a36fcf76d876Timo Sirainen
cbf7138b49d32fce0645dc6523fbb42cc07cb2faTimo Sirainenstatic int pool_try_grow(struct alloconly_pool *apool, void *mem, size_t size)
cbf7138b49d32fce0645dc6523fbb42cc07cb2faTimo Sirainen{
b9b48aaaebf6f72dfab567cda073cde8a7b26598Timo Sirainen /* see if we want to grow the memory we allocated last */
b9b48aaaebf6f72dfab567cda073cde8a7b26598Timo Sirainen if (POOL_BLOCK_DATA(apool->block) +
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen (apool->block->size - apool->block->left -
992a9e2d6c6ee45d87089ac54267e0198a7802c3Timo Sirainen apool->block->last_alloc_size) == mem) {
ae9365d3de0cefae6f2a5d3e9ab79bc11c37b3d5Timo Sirainen /* yeah, see if we can grow */
ae9365d3de0cefae6f2a5d3e9ab79bc11c37b3d5Timo Sirainen if (apool->block->left >= size-apool->block->last_alloc_size) {
ae9365d3de0cefae6f2a5d3e9ab79bc11c37b3d5Timo Sirainen /* just shrink the available size */
ae9365d3de0cefae6f2a5d3e9ab79bc11c37b3d5Timo Sirainen apool->block->left -=
ae9365d3de0cefae6f2a5d3e9ab79bc11c37b3d5Timo Sirainen size - apool->block->last_alloc_size;
ae9365d3de0cefae6f2a5d3e9ab79bc11c37b3d5Timo Sirainen apool->block->last_alloc_size = size;
ae9365d3de0cefae6f2a5d3e9ab79bc11c37b3d5Timo Sirainen return TRUE;
ae9365d3de0cefae6f2a5d3e9ab79bc11c37b3d5Timo Sirainen }
ae9365d3de0cefae6f2a5d3e9ab79bc11c37b3d5Timo Sirainen }
ae9365d3de0cefae6f2a5d3e9ab79bc11c37b3d5Timo Sirainen
ae9365d3de0cefae6f2a5d3e9ab79bc11c37b3d5Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void *pool_alloconly_realloc(pool_t pool, void *mem,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen size_t old_size, size_t new_size)
e30b748edcef3cf3352478bf21fa8f785bdc773aTimo Sirainen{
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen struct alloconly_pool *apool = (struct alloconly_pool *) pool;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen unsigned char *new_mem;
d4dcb9c30dba354cff7af6d303ecef7698194c55Timo Sirainen
1582b4d531679849bba299c17b6ec9402b7df67dTimo Sirainen if (new_size == 0 || new_size > SSIZE_T_MAX)
1582b4d531679849bba299c17b6ec9402b7df67dTimo Sirainen i_panic("Trying to allocate %"PRIuSIZE_T" bytes", new_size);
1582b4d531679849bba299c17b6ec9402b7df67dTimo Sirainen
1582b4d531679849bba299c17b6ec9402b7df67dTimo Sirainen if (mem == NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return pool_alloconly_malloc(pool, new_size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
9c7e765845357342923e16351181091028e5930fTimo Sirainen if (new_size <= old_size)
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen return mem;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen new_size = MEM_ALIGN(new_size);
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen /* see if we can directly grow it */
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen if (!pool_try_grow(apool, mem, new_size)) {
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen /* slow way - allocate + copy */
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen new_mem = pool_alloconly_malloc(pool, new_size);
6bf1543bb7af03324c04e8f9ac8e430f395989aeTimo Sirainen memcpy(new_mem, mem, old_size);
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen mem = new_mem;
b00787191c3c31bebb939c3d00f1fcdb67356c69Timo Sirainen }
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen return mem;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen}
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainenstatic void pool_alloconly_clear(pool_t pool)
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen{
ee116df08d0fdab703483e18fe8076b2ef9fd9d7Timo Sirainen struct alloconly_pool *apool = (struct alloconly_pool *) pool;
ee116df08d0fdab703483e18fe8076b2ef9fd9d7Timo Sirainen struct pool_block *block;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen /* destroy all blocks but the first, which is the largest */
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen while (apool->block->prev != NULL) {
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen block = apool->block->prev;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen apool->block->prev = block->prev;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen#ifdef DEBUG
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen memset(block, 0xde, SIZEOF_POOLBLOCK + block->size);
e30b748edcef3cf3352478bf21fa8f785bdc773aTimo Sirainen#endif
e30b748edcef3cf3352478bf21fa8f785bdc773aTimo Sirainen#ifndef USE_GC
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen free(block);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#endif
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen /* clear the block */
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen memset(POOL_BLOCK_DATA(apool->block), 0,
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen apool->block->size - apool->block->left);
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen apool->block->left = apool->block->size;
44dc970b18c4e2d06f34cb908924152156e4a45bTimo Sirainen apool->block->last_alloc_size = 0;
e30b748edcef3cf3352478bf21fa8f785bdc773aTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen