GNU libmicrohttpd  0.9.29
memorypool.c
Go to the documentation of this file.
1 /*
2  This file is part of libmicrohttpd
3  Copyright (C) 2007, 2009, 2010 Daniel Pittman and Christian Grothoff
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Lesser General Public
7  License as published by the Free Software Foundation; either
8  version 2.1 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, write to the Free Software
17  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19 
25 #include "memorypool.h"
26 
27 /* define MAP_ANONYMOUS for Mac OS X */
28 #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
29 #define MAP_ANONYMOUS MAP_ANON
30 #endif
31 #ifndef MAP_FAILED
32 #define MAP_FAILED ((void*)-1)
33 #endif
34 
38 #define ALIGN_SIZE (2 * sizeof(void*))
39 
43 #define ROUND_TO_ALIGN(n) ((n+(ALIGN_SIZE-1)) & (~(ALIGN_SIZE-1)))
44 
45 
50 struct MemoryPool
51 {
52 
56  char *memory;
57 
61  size_t size;
62 
66  size_t pos;
67 
71  size_t end;
72 
76  int is_mmap;
77 };
78 
79 
86 struct MemoryPool *
87 MHD_pool_create (size_t max)
88 {
89  struct MemoryPool *pool;
90 
91  pool = malloc (sizeof (struct MemoryPool));
92  if (NULL == pool)
93  return NULL;
94 #if defined(MAP_ANONYMOUS) || defined(_WIN32)
95  if (max <= 32 * 1024)
96  pool->memory = MAP_FAILED;
97  else
98 #if defined(MAP_ANONYMOUS) && !defined(_WIN32)
99  pool->memory = mmap (NULL,
100  max,
101  PROT_READ | PROT_WRITE,
102  MAP_PRIVATE | MAP_ANONYMOUS,
103  -1,
104  0);
105 #elif defined(_WIN32)
106  pool->memory = VirtualAlloc (NULL,
107  max,
108  MEM_COMMIT | MEM_RESERVE,
109  PAGE_READWRITE);
110 #endif
111 #else
112  pool->memory = MAP_FAILED;
113 #endif
114  if ( (MAP_FAILED == pool->memory) ||
115  (NULL == pool->memory))
116  {
117  pool->memory = malloc (max);
118  if (NULL == pool->memory)
119  {
120  free (pool);
121  return NULL;
122  }
123  pool->is_mmap = MHD_NO;
124  }
125  else
126  {
127  pool->is_mmap = MHD_YES;
128  }
129  pool->pos = 0;
130  pool->end = max;
131  pool->size = max;
132  return pool;
133 }
134 
135 
141 void
142 MHD_pool_destroy (struct MemoryPool *pool)
143 {
144  if (NULL == pool)
145  return;
146  if (MHD_NO == pool->is_mmap)
147  free (pool->memory);
148  else
149 #if defined(MAP_ANONYMOUS) && !defined(_WIN32)
150  munmap (pool->memory,
151  pool->size);
152 #elif defined(_WIN32)
153  VirtualFree (pool->memory,
154  0,
155  MEM_RELEASE);
156 #else
157  abort ();
158 #endif
159  free (pool);
160 }
161 
162 
169 size_t
170 MHD_pool_get_free (struct MemoryPool *pool)
171 {
172  return (pool->end - pool->pos);
173 }
174 
175 
187 void *
188 MHD_pool_allocate (struct MemoryPool *pool,
189  size_t size,
190  int from_end)
191 {
192  void *ret;
193  size_t asize;
194 
195  asize = ROUND_TO_ALIGN (size);
196  if ( (0 == asize) && (0 != size) )
197  return NULL; /* size too close to SIZE_MAX */
198  if ( (pool->pos + asize > pool->end) ||
199  (pool->pos + asize < pool->pos))
200  return NULL;
201  if (from_end == MHD_YES)
202  {
203  ret = &pool->memory[pool->end - asize];
204  pool->end -= asize;
205  }
206  else
207  {
208  ret = &pool->memory[pool->pos];
209  pool->pos += asize;
210  }
211  return ret;
212 }
213 
214 
232 void *
233 MHD_pool_reallocate (struct MemoryPool *pool,
234  void *old,
235  size_t old_size,
236  size_t new_size)
237 {
238  void *ret;
239  size_t asize;
240 
241  asize = ROUND_TO_ALIGN (new_size);
242  if ( (0 == asize) &&
243  (0 != new_size) )
244  return NULL; /* new_size too close to SIZE_MAX */
245  if ( (pool->end < old_size) ||
246  (pool->end < asize) )
247  return NULL; /* unsatisfiable or bogus request */
248 
249  if ( (pool->pos >= old_size) &&
250  (&pool->memory[pool->pos - old_size] == old) )
251  {
252  /* was the previous allocation - optimize! */
253  if (pool->pos + asize - old_size <= pool->end)
254  {
255  /* fits */
256  pool->pos += asize - old_size;
257  if (asize < old_size) /* shrinking - zero again! */
258  memset (&pool->memory[pool->pos],
259  0,
260  old_size - asize);
261  return old;
262  }
263  /* does not fit */
264  return NULL;
265  }
266  if (asize <= old_size)
267  return old; /* cannot shrink, no need to move */
268  if ((pool->pos + asize >= pool->pos) &&
269  (pool->pos + asize <= pool->end))
270  {
271  /* fits */
272  ret = &pool->memory[pool->pos];
273  if (0 != old_size)
274  memmove (ret,
275  old,
276  old_size);
277  pool->pos += asize;
278  return ret;
279  }
280  /* does not fit */
281  return NULL;
282 }
283 
284 
298 void *
299 MHD_pool_reset (struct MemoryPool *pool,
300  void *keep,
301  size_t copy_bytes,
302  size_t new_size)
303 {
304  if ( (NULL != keep) &&
305  (keep != pool->memory) )
306  {
307  if (0 != copy_bytes)
308  memmove (pool->memory,
309  keep,
310  copy_bytes);
311  keep = pool->memory;
312  }
313  pool->end = pool->size;
314  /* technically not needed, but safer to zero out */
315  if (pool->size > copy_bytes)
316  memset (&pool->memory[copy_bytes],
317  0,
318  pool->size - copy_bytes);
319  if (NULL != keep)
320  pool->pos = ROUND_TO_ALIGN (new_size);
321  return keep;
322 }
323 
324 
325 /* end of memorypool.c */
void * MHD_pool_reset(struct MemoryPool *pool, void *keep, size_t copy_bytes, size_t new_size)
Definition: memorypool.c:299
#define NULL
Definition: reason_phrase.c:31
void MHD_pool_destroy(struct MemoryPool *pool)
Definition: memorypool.c:142
#define MHD_YES
Definition: microhttpd.h:134
void * MHD_pool_allocate(struct MemoryPool *pool, size_t size, int from_end)
Definition: memorypool.c:188
#define MAP_FAILED
Definition: memorypool.c:32
void * MHD_pool_reallocate(struct MemoryPool *pool, void *old, size_t old_size, size_t new_size)
Definition: memorypool.c:233
size_t MHD_pool_get_free(struct MemoryPool *pool)
Definition: memorypool.c:170
#define ROUND_TO_ALIGN(n)
Definition: memorypool.c:43
struct MemoryPool * MHD_pool_create(size_t max)
Definition: memorypool.c:87
#define MHD_NO
Definition: microhttpd.h:139
memory pool; mostly used for efficient (de)allocation for each connection and bounding memory use for...