GNU libmicrohttpd  0.9.59
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 
88 _MHD_EXTERN void
89 MHD_free (void *ptr)
90 {
91  free (ptr);
92 }
93 
94 
101 struct MemoryPool *
102 MHD_pool_create (size_t max)
103 {
104  struct MemoryPool *pool;
105 
106  pool = malloc (sizeof (struct MemoryPool));
107  if (NULL == pool)
108  return NULL;
109 #if defined(MAP_ANONYMOUS) || defined(_WIN32)
110  if (max <= 32 * 1024)
111  pool->memory = MAP_FAILED;
112  else
113 #if defined(MAP_ANONYMOUS) && !defined(_WIN32)
114  pool->memory = mmap (NULL,
115  max,
116  PROT_READ | PROT_WRITE,
117  MAP_PRIVATE | MAP_ANONYMOUS,
118  -1,
119  0);
120 #elif defined(_WIN32)
121  pool->memory = VirtualAlloc (NULL,
122  max,
123  MEM_COMMIT | MEM_RESERVE,
124  PAGE_READWRITE);
125 #endif
126 #else
127  pool->memory = MAP_FAILED;
128 #endif
129  if ( (MAP_FAILED == pool->memory) ||
130  (NULL == pool->memory))
131  {
132  pool->memory = malloc (max);
133  if (NULL == pool->memory)
134  {
135  free (pool);
136  return NULL;
137  }
138  pool->is_mmap = MHD_NO;
139  }
140  else
141  {
142  pool->is_mmap = MHD_YES;
143  }
144  pool->pos = 0;
145  pool->end = max;
146  pool->size = max;
147  return pool;
148 }
149 
150 
156 void
157 MHD_pool_destroy (struct MemoryPool *pool)
158 {
159  if (NULL == pool)
160  return;
161  if (MHD_NO == pool->is_mmap)
162  free (pool->memory);
163  else
164 #if defined(MAP_ANONYMOUS) && !defined(_WIN32)
165  munmap (pool->memory,
166  pool->size);
167 #elif defined(_WIN32)
168  VirtualFree (pool->memory,
169  0,
170  MEM_RELEASE);
171 #else
172  abort ();
173 #endif
174  free (pool);
175 }
176 
177 
184 size_t
185 MHD_pool_get_free (struct MemoryPool *pool)
186 {
187  return (pool->end - pool->pos);
188 }
189 
190 
202 void *
203 MHD_pool_allocate (struct MemoryPool *pool,
204  size_t size,
205  int from_end)
206 {
207  void *ret;
208  size_t asize;
209 
210  asize = ROUND_TO_ALIGN (size);
211  if ( (0 == asize) && (0 != size) )
212  return NULL; /* size too close to SIZE_MAX */
213  if ( (pool->pos + asize > pool->end) ||
214  (pool->pos + asize < pool->pos))
215  return NULL;
216  if (from_end == MHD_YES)
217  {
218  ret = &pool->memory[pool->end - asize];
219  pool->end -= asize;
220  }
221  else
222  {
223  ret = &pool->memory[pool->pos];
224  pool->pos += asize;
225  }
226  return ret;
227 }
228 
229 
247 void *
248 MHD_pool_reallocate (struct MemoryPool *pool,
249  void *old,
250  size_t old_size,
251  size_t new_size)
252 {
253  void *ret;
254  size_t asize;
255 
256  asize = ROUND_TO_ALIGN (new_size);
257  if ( (0 == asize) &&
258  (0 != new_size) )
259  return NULL; /* new_size too close to SIZE_MAX */
260  if ( (pool->end < old_size) ||
261  (pool->end < asize) )
262  return NULL; /* unsatisfiable or bogus request */
263 
264  if ( (pool->pos >= old_size) &&
265  (&pool->memory[pool->pos - old_size] == old) )
266  {
267  /* was the previous allocation - optimize! */
268  if (pool->pos + asize - old_size <= pool->end)
269  {
270  /* fits */
271  pool->pos += asize - old_size;
272  if (asize < old_size) /* shrinking - zero again! */
273  memset (&pool->memory[pool->pos],
274  0,
275  old_size - asize);
276  return old;
277  }
278  /* does not fit */
279  return NULL;
280  }
281  if (asize <= old_size)
282  return old; /* cannot shrink, no need to move */
283  if ((pool->pos + asize >= pool->pos) &&
284  (pool->pos + asize <= pool->end))
285  {
286  /* fits */
287  ret = &pool->memory[pool->pos];
288  if (0 != old_size)
289  memmove (ret,
290  old,
291  old_size);
292  pool->pos += asize;
293  return ret;
294  }
295  /* does not fit */
296  return NULL;
297 }
298 
299 
313 void *
314 MHD_pool_reset (struct MemoryPool *pool,
315  void *keep,
316  size_t copy_bytes,
317  size_t new_size)
318 {
319  if ( (NULL != keep) &&
320  (keep != pool->memory) )
321  {
322  if (0 != copy_bytes)
323  memmove (pool->memory,
324  keep,
325  copy_bytes);
326  keep = pool->memory;
327  }
328  pool->end = pool->size;
329  /* technically not needed, but safer to zero out */
330  if (pool->size > copy_bytes)
331  memset (&pool->memory[copy_bytes],
332  0,
333  pool->size - copy_bytes);
334  if (NULL != keep)
335  pool->pos = ROUND_TO_ALIGN (new_size);
336  return keep;
337 }
338 
339 
340 /* end of memorypool.c */
void * MHD_pool_reset(struct MemoryPool *pool, void *keep, size_t copy_bytes, size_t new_size)
Definition: memorypool.c:314
#define NULL
Definition: reason_phrase.c:31
void MHD_pool_destroy(struct MemoryPool *pool)
Definition: memorypool.c:157
#define MHD_YES
Definition: microhttpd.h:134
void * MHD_pool_allocate(struct MemoryPool *pool, size_t size, int from_end)
Definition: memorypool.c:203
#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:248
#define _MHD_EXTERN
Definition: mhd_options.h:51
size_t MHD_pool_get_free(struct MemoryPool *pool)
Definition: memorypool.c:185
#define ROUND_TO_ALIGN(n)
Definition: memorypool.c:43
struct MemoryPool * MHD_pool_create(size_t max)
Definition: memorypool.c:102
#define MHD_NO
Definition: microhttpd.h:139
_MHD_EXTERN void MHD_free(void *ptr)
Definition: memorypool.c:89
memory pool; mostly used for efficient (de)allocation for each connection and bounding memory use for...