mempool-alloconly.c revision 80d3b05559a9024b8352d52419a1b1c0aeca654e
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen mempool-alloconly.c : Memory pool for fast allocation of memory without
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen need to free it in small blocks
86441ffc028f11857152c15fe7b0d24ff0874504Timo Sirainen Copyright (c) 2002 Timo 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 The above copyright notice and this permission notice shall be
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen included in all copies or substantial portions of the Software.
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/* @UNSAFE: whole file */
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainentypedef struct {
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen char name[MEM_ALIGN_SIZE]; /* variable size */
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen#define SIZEOF_ALLOCONLYPOOL (sizeof(AlloconlyPool)-MEM_ALIGN_SIZE)
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen /* unsigned char data[]; */
8322e7400bbeee586529e797f6e332149178aa4fTimo Sirainen#define SIZEOF_POOLBLOCK (MEM_ALIGN(sizeof(PoolBlock)))
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainentypedef struct {
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen unsigned char data[MEM_ALIGN_SIZE]; /* variable size */
12ff27eadb44c6877298d3e214c7039342669669Timo Sirainen#define SIZEOF_POOLALLOC (sizeof(PoolAlloc)-MEM_ALIGN_SIZE)
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 block_alloc(AlloconlyPool *pool, size_t size);
8587f4288b357bd83f2ec72b4197b529cf02220aTimo SirainenPool pool_alloconly_create(const char *name, size_t size)
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen apool = calloc(SIZEOF_ALLOCONLYPOOL + len+1, 1);
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen i_panic("pool_alloconly_create(): Out of memory");
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainenstatic void pool_alloconly_destroy(AlloconlyPool *apool)
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen /* destroy all but the last block */
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen /* destroy the last block */
833fd67ffe6a1832d72b3d310e07345a42a7b6abTimo Sirainen AlloconlyPool *apool = (AlloconlyPool *) pool;
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen AlloconlyPool *apool = (AlloconlyPool *) pool;
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainenstatic void block_alloc(AlloconlyPool *apool, size_t size)
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 = nearest_power(size + SIZEOF_POOLBLOCK);
8587f4288b357bd83f2ec72b4197b529cf02220aTimo Sirainen i_warning("Growing pool '%s' with: %"PRIuSIZE_T,
833fd67ffe6a1832d72b3d310e07345a42a7b6abTimo Sirainenstatic void *pool_alloconly_malloc(Pool pool, size_t size)
be1749e2421dea6465f9096fd35b28b2500d06e4Timo Sirainen AlloconlyPool *apool = (AlloconlyPool *) pool;
be1749e2421dea6465f9096fd35b28b2500d06e4Timo Sirainen i_panic("Trying to allocate %"PRIuSIZE_T" bytes", size);
be1749e2421dea6465f9096fd35b28b2500d06e4Timo Sirainen if (apool->block->left < size + SIZEOF_POOLALLOC) {
be1749e2421dea6465f9096fd35b28b2500d06e4Timo Sirainen /* we need a new block */
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch alloc = (PoolAlloc *) (POOL_BLOCK_DATA(apool->block) +
e2d420dc4bbb06de56ca225c1d9eb79456c792c5Stephan Bosch apool->block->left -= size + SIZEOF_POOLALLOC;
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Boschstatic void pool_alloconly_free(Pool pool __attr_unused__,
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Boschstatic int pool_try_grow(AlloconlyPool *apool, void *mem, size_t size)
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch /* see if we want to grow the memory we allocated last */
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 */
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Boschstatic void *pool_alloconly_realloc(Pool pool, void *mem, size_t size)
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch AlloconlyPool *apool = (AlloconlyPool *) pool;
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch unsigned char *new_mem;
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch i_panic("Trying to allocate %"PRIuSIZE_T" bytes", size);
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch /* get old size */
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch alloc = (PoolAlloc *) ((char *) mem - SIZEOF_POOLALLOC);
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch /* see if we can directly grow it */
f43734e772a94c8d2b684b59c212fecf66122d15Stephan Bosch /* slow way - allocate + copy */
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen /* clear new data */
1f35f54096589b0fdb04bfac4d079d06b43f2a74Timo Sirainen memset((char *) mem + old_size, 0, size - old_size);
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvistatic void pool_alloconly_clear(Pool pool)
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi AlloconlyPool *apool = (AlloconlyPool *) pool;
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi /* destroy all blocks but the last, which is the largest */
16bb1ac73aed6e30be610a2dc4eb9d1719f28559Martti Rannanjärvi /* clear the last block */