1748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/* 2748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat This file is part of libmicrohttpd 3748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat Copyright (C) 2007, 2009, 2010 Daniel Pittman and Christian Grothoff 4748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 5748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat This library is free software; you can redistribute it and/or 6748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat modify it under the terms of the GNU Lesser General Public 7748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat License as published by the Free Software Foundation; either 8748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat version 2.1 of the License, or (at your option) any later version. 9748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 10748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat This library is distributed in the hope that it will be useful, 11748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat but WITHOUT ANY WARRANTY; without even the implied warranty of 12748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat Lesser General Public License for more details. 14748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 15748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat You should have received a copy of the GNU Lesser General Public 16748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat License along with this library; if not, write to the Free Software 17748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat*/ 19748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 20748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/** 21748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @file memorypool.c 22748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @brief memory pool 23748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @author Christian Grothoff 24748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */ 25748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include "memorypool.h" 26748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 27748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/* define MAP_ANONYMOUS for Mac OS X */ 28748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) 29748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#define MAP_ANONYMOUS MAP_ANON 30748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#endif 31748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#ifndef MAP_FAILED 32748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#define MAP_FAILED ((void*)-1) 33748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#endif 34748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 35748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/** 36748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Align to 2x word size (as GNU libc does). 37748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */ 38748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#define ALIGN_SIZE (2 * sizeof(void*)) 39748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 40748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/** 41748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Round up 'n' to a multiple of ALIGN_SIZE. 42748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */ 43748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#define ROUND_TO_ALIGN(n) ((n+(ALIGN_SIZE-1)) & (~(ALIGN_SIZE-1))) 44748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 45748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 46748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/** 47748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Handle for a memory pool. Pools are not reentrant and must not be 48748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * used by multiple threads. 49748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */ 50748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstruct MemoryPool 51748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{ 52748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 53748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat /** 54748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Pointer to the pool's memory 55748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */ 56748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat char *memory; 57748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 58748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat /** 59748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Size of the pool. 60748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */ 61748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat size_t size; 62748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 63748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat /** 64748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Offset of the first unallocated byte. 65748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */ 66748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat size_t pos; 67748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 68748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat /** 69748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Offset of the last unallocated byte. 70748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */ 71748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat size_t end; 72748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 73748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat /** 74748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * #MHD_NO if pool was malloc'ed, #MHD_YES if mmapped (VirtualAlloc'ed for W32). 75748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */ 76748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat int is_mmap; 77748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}; 78748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 79748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 80748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/** 81748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Create a memory pool. 82748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * 83748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param max maximum size of the pool 84748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @return NULL on error 85748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */ 86748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstruct MemoryPool * 87748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratMHD_pool_create (size_t max) 88748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{ 89748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat struct MemoryPool *pool; 90748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 91748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat pool = malloc (sizeof (struct MemoryPool)); 92748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat if (NULL == pool) 93748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat return NULL; 94748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#if defined(MAP_ANONYMOUS) || defined(_WIN32) 95748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat if (max <= 32 * 1024) 96748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat pool->memory = MAP_FAILED; 97748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat else 98748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#if defined(MAP_ANONYMOUS) && !defined(_WIN32) 99748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat pool->memory = mmap (NULL, max, PROT_READ | PROT_WRITE, 100748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 101748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#elif defined(_WIN32) 102748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat pool->memory = VirtualAlloc(NULL, max, MEM_COMMIT | MEM_RESERVE, 103748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat PAGE_READWRITE); 104748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#endif 105748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#else 106748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat pool->memory = MAP_FAILED; 107748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#endif 108748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat if ((pool->memory == MAP_FAILED) || (pool->memory == NULL)) 109748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat { 110748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat pool->memory = malloc (max); 111748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat if (pool->memory == NULL) 112748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat { 113748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat free (pool); 114748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat return NULL; 115748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat } 116748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat pool->is_mmap = MHD_NO; 117748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat } 118748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat else 119748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat { 120748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat pool->is_mmap = MHD_YES; 121748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat } 122748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat pool->pos = 0; 123748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat pool->end = max; 124748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat pool->size = max; 125748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat return pool; 126748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat} 127748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 128748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 129748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/** 130748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Destroy a memory pool. 131748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * 132748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param pool memory pool to destroy 133748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */ 134748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratvoid 135748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratMHD_pool_destroy (struct MemoryPool *pool) 136748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{ 137748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat if (pool == NULL) 138748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat return; 139748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat if (pool->is_mmap == MHD_NO) 140748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat free (pool->memory); 141748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat else 142748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#if defined(MAP_ANONYMOUS) && !defined(_WIN32) 143748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat munmap (pool->memory, pool->size); 144748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#elif defined(_WIN32) 145748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat VirtualFree(pool->memory, 0, MEM_RELEASE); 146748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#else 147748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat abort(); 148748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#endif 149748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat free (pool); 150748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat} 151748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 152748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 153748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/** 154748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Allocate size bytes from the pool. 155748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * 156748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param pool memory pool to use for the operation 157748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param size number of bytes to allocate 158748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param from_end allocate from end of pool (set to #MHD_YES); 159748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * use this for small, persistent allocations that 160748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * will never be reallocated 161748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @return NULL if the pool cannot support size more 162748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * bytes 163748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */ 164748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratvoid * 165748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratMHD_pool_allocate (struct MemoryPool *pool, 166748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat size_t size, int from_end) 167748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{ 168748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat void *ret; 169748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat size_t asize; 170748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 171748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat asize = ROUND_TO_ALIGN (size); 172748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat if ( (0 == asize) && (0 != size) ) 173748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat return NULL; /* size too close to SIZE_MAX */ 174748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat if ((pool->pos + asize > pool->end) || (pool->pos + asize < pool->pos)) 175748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat return NULL; 176748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat if (from_end == MHD_YES) 177748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat { 178748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat ret = &pool->memory[pool->end - asize]; 179748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat pool->end -= asize; 180748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat } 181748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat else 182748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat { 183748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat ret = &pool->memory[pool->pos]; 184748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat pool->pos += asize; 185748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat } 186748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat return ret; 187748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat} 188748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 189748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 190748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/** 191748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Reallocate a block of memory obtained from the pool. 192748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * This is particularly efficient when growing or 193748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * shrinking the block that was last (re)allocated. 194748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * If the given block is not the most recenlty 195748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * (re)allocated block, the memory of the previous 196748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * allocation may be leaked until the pool is 197748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * destroyed (and copying the data maybe required). 198748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * 199748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param pool memory pool to use for the operation 200748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param old the existing block 201748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param old_size the size of the existing block 202748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param new_size the new size of the block 203748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @return new address of the block, or 204748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * NULL if the pool cannot support @a new_size 205748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * bytes (old continues to be valid for @a old_size) 206748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */ 207748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratvoid * 208748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratMHD_pool_reallocate (struct MemoryPool *pool, 209748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat void *old, 210748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat size_t old_size, 211748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat size_t new_size) 212748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{ 213748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat void *ret; 214748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat size_t asize; 215748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 216748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat asize = ROUND_TO_ALIGN (new_size); 217748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat if ( (0 == asize) && (0 != new_size) ) 218748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat return NULL; /* new_size too close to SIZE_MAX */ 219748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat if ((pool->end < old_size) || (pool->end < asize)) 220748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat return NULL; /* unsatisfiable or bogus request */ 221748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 222748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat if ((pool->pos >= old_size) && (&pool->memory[pool->pos - old_size] == old)) 223748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat { 224748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat /* was the previous allocation - optimize! */ 225748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat if (pool->pos + asize - old_size <= pool->end) 226748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat { 227748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat /* fits */ 228748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat pool->pos += asize - old_size; 229748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat if (asize < old_size) /* shrinking - zero again! */ 230748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat memset (&pool->memory[pool->pos], 0, old_size - asize); 231748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat return old; 232748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat } 233748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat /* does not fit */ 234748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat return NULL; 235748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat } 236748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat if (asize <= old_size) 237748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat return old; /* cannot shrink, no need to move */ 238748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat if ((pool->pos + asize >= pool->pos) && 239748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat (pool->pos + asize <= pool->end)) 240748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat { 241748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat /* fits */ 242748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat ret = &pool->memory[pool->pos]; 243748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat memcpy (ret, old, old_size); 244748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat pool->pos += asize; 245748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat return ret; 246748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat } 247748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat /* does not fit */ 248748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat return NULL; 249748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat} 250748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 251748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 252748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/** 253748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Clear all entries from the memory pool except 254748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * for @a keep of the given @a size. 255748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * 256748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param pool memory pool to use for the operation 257748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param keep pointer to the entry to keep (maybe NULL) 258748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param size how many bytes need to be kept at this address 259748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @return addr new address of @a keep (if it had to change) 260748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */ 261748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratvoid * 262748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratMHD_pool_reset (struct MemoryPool *pool, 263748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat void *keep, 264748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat size_t size) 265748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{ 266748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat if (NULL != keep) 267748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat { 268748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat if (keep != pool->memory) 269748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat { 270748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat memmove (pool->memory, keep, size); 271748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat keep = pool->memory; 272748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat } 273748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat } 274748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat pool->end = pool->size; 275748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat memset (&pool->memory[size], 276748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 0, 277748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat pool->size - size); 278748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat if (NULL != keep) 279748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat pool->pos = ROUND_TO_ALIGN(size); 280748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat return keep; 281748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat} 282748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 283748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat 284748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/* end of memorypool.c */ 285