GNU libmicrohttpd 0.9.5
|
00001 /* 00002 This file is part of libmicrohttpd 00003 (C) 2007, 2009, 2010 Daniel Pittman and Christian Grothoff 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Lesser General Public 00007 License as published by the Free Software Foundation; either 00008 version 2.1 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Lesser General Public License for more details. 00014 00015 You should have received a copy of the GNU Lesser General Public 00016 License along with this library; if not, write to the Free Software 00017 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00018 */ 00019 00025 #include "memorypool.h" 00026 00027 /* define MAP_ANONYMOUS for Mac OS X */ 00028 #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) 00029 #define MAP_ANONYMOUS MAP_ANON 00030 #endif 00031 #ifndef MAP_FAILED 00032 #define MAP_FAILED ((void*)-1) 00033 #endif 00034 00038 #define ALIGN_SIZE (2 * sizeof(void*)) 00039 00043 #define ROUND_TO_ALIGN(n) ((n+(ALIGN_SIZE-1)) & (~(ALIGN_SIZE-1))) 00044 00045 struct MemoryPool 00046 { 00047 00051 char *memory; 00052 00056 size_t size; 00057 00061 size_t pos; 00062 00066 size_t end; 00067 00071 int is_mmap; 00072 }; 00073 00079 struct MemoryPool * 00080 MHD_pool_create (size_t max) 00081 { 00082 struct MemoryPool *pool; 00083 00084 pool = malloc (sizeof (struct MemoryPool)); 00085 if (pool == NULL) 00086 return NULL; 00087 #ifdef MAP_ANONYMOUS 00088 pool->memory = MMAP (NULL, max, PROT_READ | PROT_WRITE, 00089 MAP_ANONYMOUS, -1, 0); 00090 #else 00091 pool->memory = MAP_FAILED; 00092 #endif 00093 if ((pool->memory == MAP_FAILED) || (pool->memory == NULL)) 00094 { 00095 pool->memory = malloc (max); 00096 if (pool->memory == NULL) 00097 { 00098 free (pool); 00099 return NULL; 00100 } 00101 pool->is_mmap = MHD_NO; 00102 } 00103 else 00104 { 00105 pool->is_mmap = MHD_YES; 00106 } 00107 pool->pos = 0; 00108 pool->end = max; 00109 pool->size = max; 00110 return pool; 00111 } 00112 00116 void 00117 MHD_pool_destroy (struct MemoryPool *pool) 00118 { 00119 if (pool == NULL) 00120 return; 00121 if (pool->is_mmap == MHD_NO) 00122 free (pool->memory); 00123 else 00124 MUNMAP (pool->memory, pool->size); 00125 free (pool); 00126 } 00127 00133 void * 00134 MHD_pool_allocate (struct MemoryPool *pool, 00135 size_t size, int from_end) 00136 { 00137 void *ret; 00138 00139 size = ROUND_TO_ALIGN (size); 00140 if ((pool->pos + size > pool->end) || (pool->pos + size < pool->pos)) 00141 return NULL; 00142 if (from_end == MHD_YES) 00143 { 00144 ret = &pool->memory[pool->end - size]; 00145 pool->end -= size; 00146 } 00147 else 00148 { 00149 ret = &pool->memory[pool->pos]; 00150 pool->pos += size; 00151 } 00152 return ret; 00153 } 00154 00171 void * 00172 MHD_pool_reallocate (struct MemoryPool *pool, 00173 void *old, 00174 size_t old_size, 00175 size_t new_size) 00176 { 00177 void *ret; 00178 00179 new_size = ROUND_TO_ALIGN (new_size); 00180 if ((pool->end < old_size) || (pool->end < new_size)) 00181 return NULL; /* unsatisfiable or bogus request */ 00182 00183 if ((pool->pos >= old_size) && (&pool->memory[pool->pos - old_size] == old)) 00184 { 00185 /* was the previous allocation - optimize! */ 00186 if (pool->pos + new_size - old_size <= pool->end) 00187 { 00188 /* fits */ 00189 pool->pos += new_size - old_size; 00190 if (new_size < old_size) /* shrinking - zero again! */ 00191 memset (&pool->memory[pool->pos], 0, old_size - new_size); 00192 return old; 00193 } 00194 /* does not fit */ 00195 return NULL; 00196 } 00197 if (new_size <= old_size) 00198 return old; /* cannot shrink, no need to move */ 00199 if ((pool->pos + new_size >= pool->pos) && 00200 (pool->pos + new_size <= pool->end)) 00201 { 00202 /* fits */ 00203 ret = &pool->memory[pool->pos]; 00204 memcpy (ret, old, old_size); 00205 pool->pos += new_size; 00206 return ret; 00207 } 00208 /* does not fit */ 00209 return NULL; 00210 } 00211 00220 void * 00221 MHD_pool_reset (struct MemoryPool *pool, 00222 void *keep, 00223 size_t size) 00224 { 00225 size = ROUND_TO_ALIGN (size); 00226 if (keep != NULL) 00227 { 00228 if (keep != pool->memory) 00229 { 00230 memmove (pool->memory, keep, size); 00231 keep = pool->memory; 00232 } 00233 pool->pos = size; 00234 } 00235 pool->end = pool->size; 00236 return keep; 00237 } 00238 00239 00240 00241 /* end of memorypool.c */