GNU libmicrohttpd  0.9.5
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 struct MemoryPool
46 {
47 
51  char *memory;
52 
56  size_t size;
57 
61  size_t pos;
62 
66  size_t end;
67 
71  int is_mmap;
72 };
73 
79 struct MemoryPool *
80 MHD_pool_create (size_t max)
81 {
82  struct MemoryPool *pool;
83 
84  pool = malloc (sizeof (struct MemoryPool));
85  if (pool == NULL)
86  return NULL;
87 #ifdef MAP_ANONYMOUS
88  pool->memory = MMAP (NULL, max, PROT_READ | PROT_WRITE,
89  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
90 #else
91  pool->memory = MAP_FAILED;
92 #endif
93  if ((pool->memory == MAP_FAILED) || (pool->memory == NULL))
94  {
95  pool->memory = malloc (max);
96  if (pool->memory == NULL)
97  {
98  free (pool);
99  return NULL;
100  }
101  pool->is_mmap = MHD_NO;
102  }
103  else
104  {
105  pool->is_mmap = MHD_YES;
106  }
107  pool->pos = 0;
108  pool->end = max;
109  pool->size = max;
110  return pool;
111 }
112 
116 void
117 MHD_pool_destroy (struct MemoryPool *pool)
118 {
119  if (pool == NULL)
120  return;
121  if (pool->is_mmap == MHD_NO)
122  free (pool->memory);
123  else
124  MUNMAP (pool->memory, pool->size);
125  free (pool);
126 }
127 
133 void *
134 MHD_pool_allocate (struct MemoryPool *pool,
135  size_t size, int from_end)
136 {
137  void *ret;
138 
139  size = ROUND_TO_ALIGN (size);
140  if ((pool->pos + size > pool->end) || (pool->pos + size < pool->pos))
141  return NULL;
142  if (from_end == MHD_YES)
143  {
144  ret = &pool->memory[pool->end - size];
145  pool->end -= size;
146  }
147  else
148  {
149  ret = &pool->memory[pool->pos];
150  pool->pos += size;
151  }
152  return ret;
153 }
154 
171 void *
172 MHD_pool_reallocate (struct MemoryPool *pool,
173  void *old,
174  size_t old_size,
175  size_t new_size)
176 {
177  void *ret;
178 
179  new_size = ROUND_TO_ALIGN (new_size);
180  if ((pool->end < old_size) || (pool->end < new_size))
181  return NULL; /* unsatisfiable or bogus request */
182 
183  if ((pool->pos >= old_size) && (&pool->memory[pool->pos - old_size] == old))
184  {
185  /* was the previous allocation - optimize! */
186  if (pool->pos + new_size - old_size <= pool->end)
187  {
188  /* fits */
189  pool->pos += new_size - old_size;
190  if (new_size < old_size) /* shrinking - zero again! */
191  memset (&pool->memory[pool->pos], 0, old_size - new_size);
192  return old;
193  }
194  /* does not fit */
195  return NULL;
196  }
197  if (new_size <= old_size)
198  return old; /* cannot shrink, no need to move */
199  if ((pool->pos + new_size >= pool->pos) &&
200  (pool->pos + new_size <= pool->end))
201  {
202  /* fits */
203  ret = &pool->memory[pool->pos];
204  memcpy (ret, old, old_size);
205  pool->pos += new_size;
206  return ret;
207  }
208  /* does not fit */
209  return NULL;
210 }
211 
220 void *
221 MHD_pool_reset (struct MemoryPool *pool,
222  void *keep,
223  size_t size)
224 {
225  size = ROUND_TO_ALIGN (size);
226  if (keep != NULL)
227  {
228  if (keep != pool->memory)
229  {
230  memmove (pool->memory, keep, size);
231  keep = pool->memory;
232  }
233  pool->pos = size;
234  }
235  pool->end = pool->size;
236  return keep;
237 }
238 
239 
240 
241 /* end of memorypool.c */