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