mempool-alloconly.c revision e249c8dafd768240b00be718f46d23874499a0bf
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen mempool-alloconly.c : Memory pool for fast allocation of memory without
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen need to free it in small blocks
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen Copyright (c) 2002 Timo Sirainen
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen Permission is hereby granted, free of charge, to any person obtaining
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen a copy of this software and associated documentation files (the
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen "Software"), to deal in the Software without restriction, including
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen without limitation the rights to use, copy, modify, merge, publish,
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen distribute, sublicense, and/or sell copies of the Software, and to
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen permit persons to whom the Software is furnished to do so, subject to
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen the following conditions:
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen The above copyright notice and this permission notice shall be
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen included in all copies or substantial portions of the Software.
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
3448096d5b1cd324ed5132045de0345cd7120a25Timo Sirainen OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19ed8f08b23d6ed204e6b27e5d1c0c6fe6bb11ddPhil Carmody TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19ed8f08b23d6ed204e6b27e5d1c0c6fe6bb11ddPhil Carmody SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen/* @UNSAFE: whole file */
202468f94e6c6c8b5d3d98ee74e01bb0d0bb04aaTimo Sirainen char name[MEM_ALIGN_SIZE]; /* variable size */
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen#define SIZEOF_ALLOCONLYPOOL (sizeof(struct alloconly_pool)-MEM_ALIGN_SIZE)
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen /* unsigned char data[]; */
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen#define SIZEOF_POOLBLOCK (MEM_ALIGN(sizeof(struct pool_block)))
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainenstatic void *pool_alloconly_malloc(pool_t pool, size_t size);
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainenstatic void pool_alloconly_free(pool_t pool, void *mem);
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainenstatic void *pool_alloconly_realloc(pool_t pool, void *mem,
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainenstatic void block_alloc(struct alloconly_pool *pool, size_t size);
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainenpool_t pool_alloconly_create(const char *name, size_t size)
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen apool = calloc(SIZEOF_ALLOCONLYPOOL + len+1, 1);
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen i_panic("pool_alloconly_create(): Out of memory");
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainenstatic void pool_alloconly_destroy(struct alloconly_pool *apool)
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen /* destroy all but the last block */
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen /* destroy the last block */
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen memset(apool->block, 0xde, SIZEOF_POOLBLOCK + apool->block->size);
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen struct alloconly_pool *apool = (struct alloconly_pool *) pool;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen struct alloconly_pool *apool = (struct alloconly_pool *) pool;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainenstatic void block_alloc(struct alloconly_pool *apool, size_t size)
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen /* each block is at least twice the size of the previous one */
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen if (apool->block != NULL && size <= apool->block->size)
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen size = nearest_power(size + SIZEOF_POOLBLOCK);
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen i_warning("Growing pool '%s' with: %"PRIuSIZE_T,
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainenstatic void *pool_alloconly_malloc(pool_t pool, size_t size)
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen struct alloconly_pool *apool = (struct alloconly_pool *) pool;
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen i_panic("Trying to allocate %"PRIuSIZE_T" bytes", size);
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen /* we need a new block */
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainenstatic void pool_alloconly_free(pool_t pool __attr_unused__,
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainenstatic int pool_try_grow(struct alloconly_pool *apool, void *mem, size_t size)
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen /* see if we want to grow the memory we allocated last */
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen /* yeah, see if we can grow */
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen if (apool->block->left >= size-apool->block->last_alloc_size) {
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen /* just shrink the available size */
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainenstatic void *pool_alloconly_realloc(pool_t pool, void *mem,
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen struct alloconly_pool *apool = (struct alloconly_pool *) pool;
b04e76cbc807707d299055be79500f8ff131da43Timo Sirainen unsigned char *new_mem;
0c5854b6891c59c1c3f443569bc823d7db571582Teemu Huovila i_panic("Trying to allocate %"PRIuSIZE_T" bytes", new_size);
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen /* see if we can directly grow it */
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen /* slow way - allocate + copy */
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen new_mem = pool_alloconly_malloc(pool, new_size);
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen /* clear new data */
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen memset((char *) mem + old_size, 0, new_size - old_size);
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen struct alloconly_pool *apool = (struct alloconly_pool *) pool;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen /* destroy all blocks but the last, which is the largest */
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila memset(block, 0xde, SIZEOF_POOLBLOCK + block->size);
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila /* clear the last block */