GNU libmicrohttpd 0.9.77
Loading...
Searching...
No Matches
memorypool.c
Go to the documentation of this file.
1/*
2 This file is part of libmicrohttpd
3 Copyright (C) 2007, 2009, 2010, 2018 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
50struct MemoryPool
51{
52
56 char *memory;
57
61 size_t size;
62
66 size_t pos;
67
71 size_t end;
72
76 bool is_mmap;
77};
78
79
88_MHD_EXTERN void
89MHD_free (void *ptr)
90{
91 free (ptr);
92}
93
94
101struct MemoryPool *
102MHD_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 = false;
139 }
140 else
141 {
142 pool->is_mmap = true;
143 }
144 pool->pos = 0;
145 pool->end = max;
146 pool->size = max;
147 return pool;
148}
149
150
156void
157MHD_pool_destroy (struct MemoryPool *pool)
158{
159 if (NULL == pool)
160 return;
161 if (! 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
184size_t
185MHD_pool_get_free (struct MemoryPool *pool)
186{
187 return (pool->end - pool->pos);
188}
189
190
202void *
203MHD_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
247void *
248MHD_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
313void *
314MHD_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_reallocate(struct MemoryPool *pool, void *old, size_t old_size, size_t new_size)
Definition memorypool.c:248
void MHD_pool_destroy(struct MemoryPool *pool)
Definition memorypool.c:157
#define MAP_FAILED
Definition memorypool.c:32
size_t MHD_pool_get_free(struct MemoryPool *pool)
Definition memorypool.c:185
void * MHD_pool_reset(struct MemoryPool *pool, void *keep, size_t copy_bytes, size_t new_size)
Definition memorypool.c:314
struct MemoryPool * MHD_pool_create(size_t max)
Definition memorypool.c:102
void * MHD_pool_allocate(struct MemoryPool *pool, size_t size, int from_end)
Definition memorypool.c:203
#define ROUND_TO_ALIGN(n)
Definition memorypool.c:43
_MHD_EXTERN void MHD_free(void *ptr)
Definition memorypool.c:89
#define NULL
#define _MHD_EXTERN
Definition mhd_options.h:50
memory pool; mostly used for efficient (de)allocation for each connection and bounding memory use for...
@ MHD_YES
Definition microhttpd.h:167