mempool-alloconly.c revision e249c8dafd768240b00be718f46d23874499a0bf
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen/*
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen mempool-alloconly.c : Memory pool for fast allocation of memory without
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen need to free it in small blocks
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen Copyright (c) 2002 Timo Sirainen
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo 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
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
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.
19ed8f08b23d6ed204e6b27e5d1c0c6fe6bb11ddPhil Carmody*/
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen/* @UNSAFE: whole file */
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
b04e76cbc807707d299055be79500f8ff131da43Timo Sirainen#include "lib.h"
b04e76cbc807707d299055be79500f8ff131da43Timo Sirainen#include "mempool.h"
72c4ef3b44c50c662b37bba93b463b0caeb63a4fTimo Sirainen
0c5854b6891c59c1c3f443569bc823d7db571582Teemu Huovila#include <stdlib.h>
19ed8f08b23d6ed204e6b27e5d1c0c6fe6bb11ddPhil Carmody
19ed8f08b23d6ed204e6b27e5d1c0c6fe6bb11ddPhil Carmody#define MAX_ALLOC_SIZE SSIZE_T_MAX
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainenstruct alloconly_pool {
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen struct pool pool;
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen int refcount;
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen struct pool_block *block;
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen
202468f94e6c6c8b5d3d98ee74e01bb0d0bb04aaTimo Sirainen char name[MEM_ALIGN_SIZE]; /* variable size */
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen};
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen#define SIZEOF_ALLOCONLYPOOL (sizeof(struct alloconly_pool)-MEM_ALIGN_SIZE)
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainenstruct pool_block {
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen struct pool_block *prev;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen size_t size;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen size_t left;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen size_t last_alloc_size;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen /* unsigned char data[]; */
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila};
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen#define SIZEOF_POOLBLOCK (MEM_ALIGN(sizeof(struct pool_block)))
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila#define POOL_BLOCK_DATA(block) \
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen ((char *) (block) + SIZEOF_POOLBLOCK)
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainenstatic void pool_alloconly_ref(pool_t pool);
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainenstatic void pool_alloconly_unref(pool_t pool);
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,
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainen size_t old_size, size_t new_size);
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainenstatic void pool_alloconly_clear(pool_t pool);
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainenstatic void block_alloc(struct alloconly_pool *pool, size_t size);
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainenstatic struct pool static_alloconly_pool = {
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen pool_alloconly_ref,
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen pool_alloconly_unref,
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen pool_alloconly_malloc,
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen pool_alloconly_free,
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen pool_alloconly_realloc,
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen pool_alloconly_clear,
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen TRUE
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen};
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainenpool_t pool_alloconly_create(const char *name, size_t size)
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen{
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen struct alloconly_pool *apool;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen int len;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen len = strlen(name);
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen apool = calloc(SIZEOF_ALLOCONLYPOOL + len+1, 1);
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen if (apool == NULL)
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen i_panic("pool_alloconly_create(): Out of memory");
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen apool->pool = static_alloconly_pool;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen apool->refcount = 1;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen memcpy(apool->name, name, len+1);
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen block_alloc(apool, size);
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen return (struct pool *) apool;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen}
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainenstatic void pool_alloconly_destroy(struct alloconly_pool *apool)
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen{
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen /* destroy all but the last block */
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen pool_alloconly_clear(&apool->pool);
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen /* destroy the last block */
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen#ifdef DEBUG
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen memset(apool->block, 0xde, SIZEOF_POOLBLOCK + apool->block->size);
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen#endif
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen free(apool->block);
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen free(apool);
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen}
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainenstatic void pool_alloconly_ref(pool_t pool)
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen{
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen struct alloconly_pool *apool = (struct alloconly_pool *) pool;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen apool->refcount++;
0c5854b6891c59c1c3f443569bc823d7db571582Teemu Huovila}
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainenstatic void pool_alloconly_unref(pool_t pool)
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen{
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen struct alloconly_pool *apool = (struct alloconly_pool *) pool;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen if (--apool->refcount == 0)
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen pool_alloconly_destroy(apool);
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen}
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainenstatic void block_alloc(struct alloconly_pool *apool, size_t size)
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen{
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen struct pool_block *block;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen /* each block is at least twice the size of the previous one */
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen if (apool->block != NULL && size <= apool->block->size)
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen size += apool->block->size;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen size = nearest_power(size + SIZEOF_POOLBLOCK);
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen#ifdef DEBUG
3448096d5b1cd324ed5132045de0345cd7120a25Timo Sirainen if (apool->block != NULL) {
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen i_warning("Growing pool '%s' with: %"PRIuSIZE_T,
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen apool->name, size);
19ed8f08b23d6ed204e6b27e5d1c0c6fe6bb11ddPhil Carmody }
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen#endif
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
78f87ea1d30f3f54bdf8560ea947ab7ee094283aTeemu Huovila block = calloc(size, 1);
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen if (block == NULL)
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen i_panic("block_alloc(): Out of memory");
b04e76cbc807707d299055be79500f8ff131da43Timo Sirainen block->prev = apool->block;
b04e76cbc807707d299055be79500f8ff131da43Timo Sirainen apool->block = block;
0c5854b6891c59c1c3f443569bc823d7db571582Teemu Huovila
0c5854b6891c59c1c3f443569bc823d7db571582Teemu Huovila block->size = size - SIZEOF_POOLBLOCK;
0c5854b6891c59c1c3f443569bc823d7db571582Teemu Huovila block->left = block->size;
19ed8f08b23d6ed204e6b27e5d1c0c6fe6bb11ddPhil Carmody}
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainenstatic void *pool_alloconly_malloc(pool_t pool, size_t size)
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen{
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen struct alloconly_pool *apool = (struct alloconly_pool *) pool;
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen void *mem;
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen if (size == 0 || size > SSIZE_T_MAX)
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen i_panic("Trying to allocate %"PRIuSIZE_T" bytes", size);
202468f94e6c6c8b5d3d98ee74e01bb0d0bb04aaTimo Sirainen
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen size = MEM_ALIGN(size);
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen if (apool->block->left < size) {
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen /* we need a new block */
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen block_alloc(apool, size);
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen }
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen mem = POOL_BLOCK_DATA(apool->block) +
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen (apool->block->size - apool->block->left);
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen apool->block->left -= size;
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila apool->block->last_alloc_size = size;
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila return mem;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen}
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainenstatic void pool_alloconly_free(pool_t pool __attr_unused__,
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen void *mem __attr_unused__)
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen{
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen /* ignore */
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainen}
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainenstatic int pool_try_grow(struct alloconly_pool *apool, void *mem, size_t size)
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen{
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen /* see if we want to grow the memory we allocated last */
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen if (POOL_BLOCK_DATA(apool->block) +
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen (apool->block->size - apool->block->left -
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen apool->block->last_alloc_size) == mem) {
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 */
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen apool->block->left -=
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen size - apool->block->last_alloc_size;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen apool->block->last_alloc_size = size;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen return TRUE;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen }
3448096d5b1cd324ed5132045de0345cd7120a25Timo Sirainen }
fdf70410de49eadfbb77997bb60ebba19aee4752Teemu Huovila
fdf70410de49eadfbb77997bb60ebba19aee4752Teemu Huovila return FALSE;
19ed8f08b23d6ed204e6b27e5d1c0c6fe6bb11ddPhil Carmody}
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainenstatic void *pool_alloconly_realloc(pool_t pool, void *mem,
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen size_t old_size, size_t new_size)
fdf70410de49eadfbb77997bb60ebba19aee4752Teemu Huovila{
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen struct alloconly_pool *apool = (struct alloconly_pool *) pool;
b04e76cbc807707d299055be79500f8ff131da43Timo Sirainen unsigned char *new_mem;
b04e76cbc807707d299055be79500f8ff131da43Timo Sirainen
0c5854b6891c59c1c3f443569bc823d7db571582Teemu Huovila if (new_size == 0 || new_size > SSIZE_T_MAX)
0c5854b6891c59c1c3f443569bc823d7db571582Teemu Huovila i_panic("Trying to allocate %"PRIuSIZE_T" bytes", new_size);
0c5854b6891c59c1c3f443569bc823d7db571582Teemu Huovila
19ed8f08b23d6ed204e6b27e5d1c0c6fe6bb11ddPhil Carmody if (mem == NULL)
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen return pool_alloconly_malloc(pool, new_size);
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen if (new_size <= old_size)
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen return mem;
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen new_size = MEM_ALIGN(new_size);
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen
b6b06530d654f0436bfbaefc1e988d53fff0cbeeTimo Sirainen /* see if we can directly grow it */
202468f94e6c6c8b5d3d98ee74e01bb0d0bb04aaTimo Sirainen if (!pool_try_grow(apool, mem, new_size)) {
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen /* slow way - allocate + copy */
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen new_mem = pool_alloconly_malloc(pool, new_size);
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen memcpy(new_mem, mem, old_size);
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen mem = new_mem;
83172e28d4ac684dfed83f7c9db933493d7c5922Timo Sirainen }
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen if (old_size < new_size) {
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen /* clear new data */
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen memset((char *) mem + old_size, 0, new_size - old_size);
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen }
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila return mem;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen}
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainenstatic void pool_alloconly_clear(pool_t pool)
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen{
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen struct alloconly_pool *apool = (struct alloconly_pool *) pool;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen struct pool_block *block;
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen /* destroy all blocks but the last, which is the largest */
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen while (apool->block->prev != NULL) {
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen block = apool->block;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen apool->block = block->prev;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila#ifdef DEBUG
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila memset(block, 0xde, SIZEOF_POOLBLOCK + block->size);
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila#endif
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila free(block);
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila }
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila /* clear the last block */
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila memset(POOL_BLOCK_DATA(apool->block), 0,
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila apool->block->size - apool->block->left);
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila apool->block->left = apool->block->size;
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila apool->block->last_alloc_size = 0;
19ed8f08b23d6ed204e6b27e5d1c0c6fe6bb11ddPhil Carmody}
3a54211bd6c4dc3f8687c16020770551cf83a548Teemu Huovila