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