mempool-alloconly.c revision 7e80c968cd8cb63e874b9a5ad9e39bd510005a57
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch/* Copyright (c) 2002-2003 Timo Sirainen */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch/* @UNSAFE: whole file */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* unsigned char data[]; */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch#define SIZEOF_POOLBLOCK (MEM_ALIGN(sizeof(struct pool_block)))
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic const char *pool_alloconly_get_name(pool_t pool);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic void *pool_alloconly_malloc(pool_t pool, size_t size);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic void pool_alloconly_free(pool_t pool, void *mem);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic void *pool_alloconly_realloc(pool_t pool, void *mem,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic size_t pool_alloconly_get_max_easy_alloc_size(pool_t pool);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic void block_alloc(struct alloconly_pool *pool, size_t size);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschpool_t pool_alloconly_create(const char *name __attr_unused__, size_t size)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch size_t min_alloc = sizeof(struct alloconly_pool) + SIZEOF_POOLBLOCK;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* create a fake alloconly_pool so we can call block_alloc() */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* now allocate the actual alloconly_pool from the created block */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch new_apool = p_new(&apool.pool, struct alloconly_pool, 1);
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen new_apool->name = p_strdup(&new_apool->pool, name);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* set base_size so p_clear() doesn't trash alloconly_pool structure. */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch new_apool->base_size = new_apool->block->size - new_apool->block->left;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic void pool_alloconly_destroy(struct alloconly_pool *apool)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* destroy all but the last block */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* destroy the last block */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch memset(block, 0xde, SIZEOF_POOLBLOCK + apool->block->size);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic const char *pool_alloconly_get_name(pool_t pool __attr_unused__)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch struct alloconly_pool *apool = (struct alloconly_pool *) pool;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch return "alloconly";
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch struct alloconly_pool *apool = (struct alloconly_pool *) pool;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch struct alloconly_pool *apool = (struct alloconly_pool *) pool;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic void block_alloc(struct alloconly_pool *apool, size_t size)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* each block is at least twice the size of the previous one */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_warning("Growing pool '%s' with: %"PRIuSIZE_T,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_fatal_status(FATAL_OUTOFMEM, "block_alloc(): Out of memory");
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic void *pool_alloconly_malloc(pool_t pool, size_t size)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch struct alloconly_pool *apool = (struct alloconly_pool *) pool;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_panic("Trying to allocate %"PRIuSIZE_T" bytes", size);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* we need a new block */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic void pool_alloconly_free(pool_t pool, void *mem)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch struct alloconly_pool *apool = (struct alloconly_pool *) pool;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* we can free only the last allocation */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch memset(mem, 0, apool->block->last_alloc_size);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch apool->block->left += apool->block->last_alloc_size;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic int pool_try_grow(struct alloconly_pool *apool, void *mem, size_t size)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* see if we want to grow the memory we allocated last */
639bb36b12b9f9bb54c8bb1be50eac623622f8a0Timo Sirainen /* yeah, see if we can grow */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch if (apool->block->left >= size-apool->block->last_alloc_size) {
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* just shrink the available size */
639bb36b12b9f9bb54c8bb1be50eac623622f8a0Timo Sirainenstatic void *pool_alloconly_realloc(pool_t pool, void *mem,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch struct alloconly_pool *apool = (struct alloconly_pool *) pool;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch unsigned char *new_mem;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch i_panic("Trying to allocate %"PRIuSIZE_T" bytes", new_size);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* see if we can directly grow it */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* slow way - allocate + copy */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch new_mem = pool_alloconly_malloc(pool, new_size);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch struct alloconly_pool *apool = (struct alloconly_pool *) pool;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* destroy all blocks but the oldest, which contains the
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch struct alloconly_pool allocation. */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch memset(block, 0xde, SIZEOF_POOLBLOCK + block->size);
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch /* clear the first block */
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch avail_size = apool->block->size - apool->base_size;
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch memset(PTR_OFFSET(POOL_BLOCK_DATA(apool->block), apool->base_size), 0,
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Boschstatic size_t pool_alloconly_get_max_easy_alloc_size(pool_t pool)
8fe8f97e688779add9cd042a9db4ddb7b117cce2Stephan Bosch struct alloconly_pool *apool = (struct alloconly_pool *) pool;