1748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/*
2748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     This file is part of libmicrohttpd
3748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     Copyright (C) 2007, 2009, 2010 Daniel Pittman and Christian Grothoff
4748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
5748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     This library is free software; you can redistribute it and/or
6748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     modify it under the terms of the GNU Lesser General Public
7748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     License as published by the Free Software Foundation; either
8748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     version 2.1 of the License, or (at your option) any later version.
9748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
10748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     This library is distributed in the hope that it will be useful,
11748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     but WITHOUT ANY WARRANTY; without even the implied warranty of
12748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     Lesser General Public License for more details.
14748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
15748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     You should have received a copy of the GNU Lesser General Public
16748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     License along with this library; if not, write to the Free Software
17748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat*/
19748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
20748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
21748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @file memorypool.c
22748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @brief memory pool
23748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @author Christian Grothoff
24748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
25748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include "memorypool.h"
26748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
27748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/* define MAP_ANONYMOUS for Mac OS X */
28748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
29748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#define MAP_ANONYMOUS MAP_ANON
30748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#endif
31748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#ifndef MAP_FAILED
32748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#define MAP_FAILED ((void*)-1)
33748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#endif
34748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
35748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
36748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Align to 2x word size (as GNU libc does).
37748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
38748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#define ALIGN_SIZE (2 * sizeof(void*))
39748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
40748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
41748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Round up 'n' to a multiple of ALIGN_SIZE.
42748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
43748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#define ROUND_TO_ALIGN(n) ((n+(ALIGN_SIZE-1)) & (~(ALIGN_SIZE-1)))
44748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
45748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
46748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
47748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Handle for a memory pool.  Pools are not reentrant and must not be
48748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * used by multiple threads.
49748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
50748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstruct MemoryPool
51748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
52748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
53748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  /**
54748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat   * Pointer to the pool's memory
55748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat   */
56748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  char *memory;
57748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
58748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  /**
59748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat   * Size of the pool.
60748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat   */
61748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  size_t size;
62748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
63748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  /**
64748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat   * Offset of the first unallocated byte.
65748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat   */
66748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  size_t pos;
67748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
68748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  /**
69748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat   * Offset of the last unallocated byte.
70748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat   */
71748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  size_t end;
72748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
73748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  /**
74748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat   * #MHD_NO if pool was malloc'ed, #MHD_YES if mmapped (VirtualAlloc'ed for W32).
75748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat   */
76748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int is_mmap;
77748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat};
78748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
79748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
80748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
81748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Create a memory pool.
82748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *
83748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param max maximum size of the pool
84748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @return NULL on error
85748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
86748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstruct MemoryPool *
87748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratMHD_pool_create (size_t max)
88748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
89748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct MemoryPool *pool;
90748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
91748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  pool = malloc (sizeof (struct MemoryPool));
92748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (NULL == pool)
93748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return NULL;
94748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#if defined(MAP_ANONYMOUS) || defined(_WIN32)
95748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (max <= 32 * 1024)
96748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    pool->memory = MAP_FAILED;
97748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  else
98748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#if defined(MAP_ANONYMOUS) && !defined(_WIN32)
99748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    pool->memory = mmap (NULL, max, PROT_READ | PROT_WRITE,
100748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat			 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
101748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#elif defined(_WIN32)
102748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    pool->memory = VirtualAlloc(NULL, max, MEM_COMMIT | MEM_RESERVE,
103748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        PAGE_READWRITE);
104748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#endif
105748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#else
106748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  pool->memory = MAP_FAILED;
107748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#endif
108748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if ((pool->memory == MAP_FAILED) || (pool->memory == NULL))
109748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
110748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      pool->memory = malloc (max);
111748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      if (pool->memory == NULL)
112748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        {
113748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          free (pool);
114748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          return NULL;
115748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        }
116748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      pool->is_mmap = MHD_NO;
117748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
118748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  else
119748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
120748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      pool->is_mmap = MHD_YES;
121748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
122748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  pool->pos = 0;
123748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  pool->end = max;
124748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  pool->size = max;
125748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return pool;
126748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
127748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
128748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
129748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
130748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Destroy a memory pool.
131748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *
132748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param pool memory pool to destroy
133748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
134748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratvoid
135748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratMHD_pool_destroy (struct MemoryPool *pool)
136748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
137748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (pool == NULL)
138748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return;
139748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (pool->is_mmap == MHD_NO)
140748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    free (pool->memory);
141748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  else
142748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#if defined(MAP_ANONYMOUS) && !defined(_WIN32)
143748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    munmap (pool->memory, pool->size);
144748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#elif defined(_WIN32)
145748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    VirtualFree(pool->memory, 0, MEM_RELEASE);
146748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#else
147748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    abort();
148748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#endif
149748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  free (pool);
150748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
151748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
152748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
153748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
154748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Allocate size bytes from the pool.
155748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *
156748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param pool memory pool to use for the operation
157748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param size number of bytes to allocate
158748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param from_end allocate from end of pool (set to #MHD_YES);
159748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *        use this for small, persistent allocations that
160748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *        will never be reallocated
161748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @return NULL if the pool cannot support size more
162748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *         bytes
163748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
164748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratvoid *
165748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratMHD_pool_allocate (struct MemoryPool *pool,
166748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat		   size_t size, int from_end)
167748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
168748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  void *ret;
169748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  size_t asize;
170748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
171748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  asize = ROUND_TO_ALIGN (size);
172748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if ( (0 == asize) && (0 != size) )
173748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return NULL; /* size too close to SIZE_MAX */
174748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if ((pool->pos + asize > pool->end) || (pool->pos + asize < pool->pos))
175748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return NULL;
176748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (from_end == MHD_YES)
177748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
178748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      ret = &pool->memory[pool->end - asize];
179748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      pool->end -= asize;
180748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
181748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  else
182748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
183748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      ret = &pool->memory[pool->pos];
184748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      pool->pos += asize;
185748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
186748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return ret;
187748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
188748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
189748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
190748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
191748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Reallocate a block of memory obtained from the pool.
192748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * This is particularly efficient when growing or
193748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * shrinking the block that was last (re)allocated.
194748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * If the given block is not the most recenlty
195748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * (re)allocated block, the memory of the previous
196748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * allocation may be leaked until the pool is
197748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * destroyed (and copying the data maybe required).
198748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *
199748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param pool memory pool to use for the operation
200748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param old the existing block
201748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param old_size the size of the existing block
202748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param new_size the new size of the block
203748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @return new address of the block, or
204748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *         NULL if the pool cannot support @a new_size
205748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *         bytes (old continues to be valid for @a old_size)
206748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
207748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratvoid *
208748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratMHD_pool_reallocate (struct MemoryPool *pool,
209748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                     void *old,
210748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat		     size_t old_size,
211748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat		     size_t new_size)
212748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
213748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  void *ret;
214748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  size_t asize;
215748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
216748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  asize = ROUND_TO_ALIGN (new_size);
217748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if ( (0 == asize) && (0 != new_size) )
218748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return NULL; /* new_size too close to SIZE_MAX */
219748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if ((pool->end < old_size) || (pool->end < asize))
220748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return NULL;                /* unsatisfiable or bogus request */
221748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
222748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if ((pool->pos >= old_size) && (&pool->memory[pool->pos - old_size] == old))
223748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
224748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      /* was the previous allocation - optimize! */
225748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      if (pool->pos + asize - old_size <= pool->end)
226748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        {
227748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          /* fits */
228748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          pool->pos += asize - old_size;
229748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          if (asize < old_size)      /* shrinking - zero again! */
230748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat            memset (&pool->memory[pool->pos], 0, old_size - asize);
231748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          return old;
232748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        }
233748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      /* does not fit */
234748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      return NULL;
235748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
236748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (asize <= old_size)
237748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return old;                 /* cannot shrink, no need to move */
238748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if ((pool->pos + asize >= pool->pos) &&
239748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      (pool->pos + asize <= pool->end))
240748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
241748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      /* fits */
242748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      ret = &pool->memory[pool->pos];
243748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      memcpy (ret, old, old_size);
244748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      pool->pos += asize;
245748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      return ret;
246748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
247748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  /* does not fit */
248748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return NULL;
249748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
250748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
251748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
252748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
253748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * Clear all entries from the memory pool except
254748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * for @a keep of the given @a size.
255748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *
256748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param pool memory pool to use for the operation
257748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param keep pointer to the entry to keep (maybe NULL)
258748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @param size how many bytes need to be kept at this address
259748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @return addr new address of @a keep (if it had to change)
260748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
261748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratvoid *
262748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel EratMHD_pool_reset (struct MemoryPool *pool,
263748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat		void *keep,
264748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat		size_t size)
265748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
266748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (NULL != keep)
267748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
268748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      if (keep != pool->memory)
269748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        {
270748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          memmove (pool->memory, keep, size);
271748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          keep = pool->memory;
272748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        }
273748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
274748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  pool->end = pool->size;
275748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  memset (&pool->memory[size],
276748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat	  0,
277748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat	  pool->size - size);
278748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (NULL != keep)
279748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    pool->pos = ROUND_TO_ALIGN(size);
280748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return keep;
281748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
282748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
283748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
284748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/* end of memorypool.c */
285