mempool-alloconly.c revision aec53c0bccddc338722bd466dcd93b329c4e5295
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw/*
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw mempool-alloconly.c : Memory pool for fast allocation of memory without
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw need to free it in small blocks
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw Copyright (c) 2002 Timo Sirainen
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw Permission is hereby granted, free of charge, to any person obtaining
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw a copy of this software and associated documentation files (the
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw "Software"), to deal in the Software without restriction, including
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw without limitation the rights to use, copy, modify, merge, publish,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw distribute, sublicense, and/or sell copies of the Software, and to
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw permit persons to whom the Software is furnished to do so, subject to
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw the following conditions:
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw The above copyright notice and this permission notice shall be
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw included in all copies or substantial portions of the Software.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw*/
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw/* @UNSAFE: whole file */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include "lib.h"
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include "mempool.h"
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#include <stdlib.h>
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#define MAX_ALLOC_SIZE SSIZE_T_MAX
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwtypedef struct _PoolBlock PoolBlock;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwtypedef struct {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw struct Pool pool;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw int refcount;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw PoolBlock *block;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw size_t last_alloc_size;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw char name[MEM_ALIGN_SIZE]; /* variable size */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw} AlloconlyPool;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#define SIZEOF_ALLOCONLYPOOL (sizeof(AlloconlyPool)-MEM_ALIGN_SIZE)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstruct _PoolBlock {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw PoolBlock *prev;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw size_t size;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw size_t left;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* unsigned char data[]; */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw};
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#define SIZEOF_POOLBLOCK (MEM_ALIGN(sizeof(PoolBlock)))
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#define POOL_BLOCK_DATA(block) \
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw ((char *) (block) + SIZEOF_POOLBLOCK)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwtypedef struct {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw union {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw size_t size;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw unsigned char alignment[MEM_ALIGN_SIZE];
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw } size;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw unsigned char data[MEM_ALIGN_SIZE]; /* variable size */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw} PoolAlloc;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#define SIZEOF_POOLALLOC (sizeof(PoolAlloc)-MEM_ALIGN_SIZE)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void pool_alloconly_ref(Pool pool);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void pool_alloconly_unref(Pool pool);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void *pool_alloconly_malloc(Pool pool, size_t size);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void pool_alloconly_free(Pool pool, void *mem);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void *pool_alloconly_realloc(Pool pool, void *mem, size_t size);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void *pool_alloconly_realloc_min(Pool pool, void *mem, size_t size);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void pool_alloconly_clear(Pool pool);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void block_alloc(AlloconlyPool *pool, size_t size);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic struct Pool static_alloconly_pool = {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw pool_alloconly_ref,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw pool_alloconly_unref,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw pool_alloconly_malloc,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw pool_alloconly_free,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw pool_alloconly_realloc,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw pool_alloconly_realloc_min,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw pool_alloconly_clear
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw};
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwPool pool_alloconly_create(const char *name, size_t size)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw AlloconlyPool *apool;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw int len;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw len = strlen(name);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw apool = calloc(SIZEOF_ALLOCONLYPOOL + len+1, 1);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (apool == NULL)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw i_panic("pool_alloconly_create(): Out of memory");
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw apool->pool = static_alloconly_pool;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw apool->refcount = 1;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw memcpy(apool->name, name, len+1);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw block_alloc(apool, size);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return (Pool) apool;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void pool_alloconly_destroy(AlloconlyPool *apool)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* destroy all but the last block */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw pool_alloconly_clear(&apool->pool);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* destroy the last block */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw free(apool->block);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw free(apool);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void pool_alloconly_ref(Pool pool)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw AlloconlyPool *apool = (AlloconlyPool *) pool;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw apool->refcount++;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void pool_alloconly_unref(Pool pool)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw AlloconlyPool *apool = (AlloconlyPool *) pool;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (--apool->refcount == 0)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw pool_alloconly_destroy(apool);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void block_alloc(AlloconlyPool *apool, size_t size)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw PoolBlock *block;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* each block is at least twice the size of the previous one */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (apool->block != NULL)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw size += apool->block->size;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (size <= SIZEOF_POOLBLOCK)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw size += SIZEOF_POOLBLOCK;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw size = nearest_power(size);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#ifdef DEBUG
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (apool->block != NULL) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw i_warning("Growing pool '%s' with: %"PRIuSIZE_T,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw apool->name, size);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw#endif
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw block = calloc(size, 1);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (block == NULL)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw i_panic("block_alloc(): Out of memory");
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw block->prev = apool->block;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw apool->block = block;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw block->size = size - SIZEOF_POOLBLOCK;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw block->left = block->size;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void *pool_alloconly_malloc(Pool pool, size_t size)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw AlloconlyPool *apool = (AlloconlyPool *) pool;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw PoolAlloc *alloc;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw size = MEM_ALIGN(size);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (apool->block->left < size + SIZEOF_POOLALLOC) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* we need a new block */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw block_alloc(apool, size);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw alloc = (PoolAlloc *) (POOL_BLOCK_DATA(apool->block) +
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw apool->block->size - apool->block->left);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw alloc->size.size = size;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw apool->block->left -= size + SIZEOF_POOLALLOC;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw apool->last_alloc_size = size;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return alloc->data;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void pool_alloconly_free(Pool pool __attr_unused__,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw void *mem __attr_unused__)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* ignore */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void *pool_alloconly_realloc(Pool pool, void *mem, size_t size)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* there's no point in shrinking the memory usage,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw so just do the same as realloc_min() */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return pool_alloconly_realloc_min(pool, mem, size);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic int pool_try_grow(AlloconlyPool *apool, void *mem, size_t size)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* see if we want to grow the memory we allocated last */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (POOL_BLOCK_DATA(apool->block) + (apool->block->size -
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw apool->block->left -
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw apool->last_alloc_size) == mem) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* yeah, see if we can grow */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (apool->block->left >= size-apool->last_alloc_size) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* just shrink the available size */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw apool->block->left -= size - apool->last_alloc_size;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw apool->last_alloc_size = size;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return TRUE;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return FALSE;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void *pool_alloconly_realloc_min(Pool pool, void *mem, size_t size)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw AlloconlyPool *apool = (AlloconlyPool *) pool;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw PoolAlloc *alloc;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw unsigned char *new_mem;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw size_t old_size;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (mem == NULL) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw alloc = NULL;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw old_size = 0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw } else {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* get old size */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw alloc = (PoolAlloc *) ((char *) mem - SIZEOF_POOLALLOC);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw old_size = alloc->size.size;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (old_size >= size)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return mem;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw size = MEM_ALIGN(size);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* see if we can directly grow it */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (!pool_try_grow(apool, mem, size)) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* slow way - allocate + copy */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw new_mem = pool_alloconly_malloc(pool, size);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw memcpy(new_mem, mem, old_size);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw mem = new_mem;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw if (size > old_size) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* clear new data */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw memset((char *) mem + old_size, 0, size - old_size);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw return mem;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xwstatic void pool_alloconly_clear(Pool pool)
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw{
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw AlloconlyPool *apool = (AlloconlyPool *) pool;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw PoolBlock *block;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* destroy all blocks but the last, which is the largest */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw while (apool->block->prev != NULL) {
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw block = apool->block;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw apool->block = block->prev;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw free(block);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw }
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw /* clear the last block */
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw memset(POOL_BLOCK_DATA(apool->block), 0,
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw apool->block->size - apool->block->left);
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw apool->block->left = apool->block->size;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw apool->last_alloc_size = 0;
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw}
d39a76e7b087a3d0927cbe6898dc0a6770fa6c68xw