GNU libmicrohttpd  0.9.29
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
memorypool.c
Go to the documentation of this file.
1 /*
2  This file is part of libmicrohttpd
3  (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 #ifdef MAP_ANONYMOUS
95  if (max <= 32 * 1024)
96  pool->memory = MAP_FAILED;
97  else
98  pool->memory = MMAP (NULL, max, PROT_READ | PROT_WRITE,
99  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
100 #else
101  pool->memory = MAP_FAILED;
102 #endif
103  if ((pool->memory == MAP_FAILED) || (pool->memory == NULL))
104  {
105  pool->memory = malloc (max);
106  if (pool->memory == NULL)
107  {
108  free (pool);
109  return NULL;
110  }
111  pool->is_mmap = MHD_NO;
112  }
113  else
114  {
115  pool->is_mmap = MHD_YES;
116  }
117  pool->pos = 0;
118  pool->end = max;
119  pool->size = max;
120  return pool;
121 }
122 
123 
129 void
130 MHD_pool_destroy (struct MemoryPool *pool)
131 {
132  if (pool == NULL)
133  return;
134  if (pool->is_mmap == MHD_NO)
135  free (pool->memory);
136  else
137  MUNMAP (pool->memory, pool->size);
138  free (pool);
139 }
140 
141 
153 void *
154 MHD_pool_allocate (struct MemoryPool *pool,
155  size_t size, int from_end)
156 {
157  void *ret;
158  size_t asize;
159 
160  asize = ROUND_TO_ALIGN (size);
161  if ( (0 == asize) && (0 != size) )
162  return NULL; /* size too close to SIZE_MAX */
163  if ((pool->pos + asize > pool->end) || (pool->pos + asize < pool->pos))
164  return NULL;
165  if (from_end == MHD_YES)
166  {
167  ret = &pool->memory[pool->end - asize];
168  pool->end -= asize;
169  }
170  else
171  {
172  ret = &pool->memory[pool->pos];
173  pool->pos += asize;
174  }
175  return ret;
176 }
177 
178 
196 void *
197 MHD_pool_reallocate (struct MemoryPool *pool,
198  void *old,
199  size_t old_size,
200  size_t new_size)
201 {
202  void *ret;
203  size_t asize;
204 
205  asize = ROUND_TO_ALIGN (new_size);
206  if ( (0 == asize) && (0 != new_size) )
207  return NULL; /* new_size too close to SIZE_MAX */
208  if ((pool->end < old_size) || (pool->end < asize))
209  return NULL; /* unsatisfiable or bogus request */
210 
211  if ((pool->pos >= old_size) && (&pool->memory[pool->pos - old_size] == old))
212  {
213  /* was the previous allocation - optimize! */
214  if (pool->pos + asize - old_size <= pool->end)
215  {
216  /* fits */
217  pool->pos += asize - old_size;
218  if (asize < old_size) /* shrinking - zero again! */
219  memset (&pool->memory[pool->pos], 0, old_size - asize);
220  return old;
221  }
222  /* does not fit */
223  return NULL;
224  }
225  if (asize <= old_size)
226  return old; /* cannot shrink, no need to move */
227  if ((pool->pos + asize >= pool->pos) &&
228  (pool->pos + asize <= pool->end))
229  {
230  /* fits */
231  ret = &pool->memory[pool->pos];
232  memcpy (ret, old, old_size);
233  pool->pos += asize;
234  return ret;
235  }
236  /* does not fit */
237  return NULL;
238 }
239 
240 
250 void *
251 MHD_pool_reset (struct MemoryPool *pool,
252  void *keep,
253  size_t size)
254 {
255  size = ROUND_TO_ALIGN (size);
256  if (NULL != keep)
257  {
258  if (keep != pool->memory)
259  {
260  memmove (pool->memory, keep, size);
261  keep = pool->memory;
262  }
263  pool->pos = size;
264  }
265  pool->end = pool->size;
266  memset (&pool->memory[size],
267  0,
268  pool->size - size);
269  return keep;
270 }
271 
272 
273 /* end of memorypool.c */