3 * $Header: /cvsroot/pgpool/pgpool-II/parser/pool_memory.c,v 1.10 2008/01/29 01:56:39 y-asaba Exp $
5 * pgpool: a language independent connection pool server for PostgreSQL
6 * written by Tatsuo Ishii
8 * Copyright (c) 2003-2008 PgPool Global Development Group
10 * Permission to use, copy, modify, and distribute this software and
11 * its documentation for any purpose and without fee is hereby
12 * granted, provided that the above copyright notice appear in all
13 * copies and that both that copyright notice and this permission
14 * notice appear in supporting documentation, and that the name of the
15 * author not be used in advertising or publicity pertaining to
16 * distribution of the software without specific, written prior
17 * permission. The author makes no representations about the
18 * suitability of this software for any purpose. It is provided "as
19 * is" without express or implied warranty.
21 * pool_memory.c: Memory pooling module for SQL parser.
26 #include "pool_memory.h"
32 #define POOL_HEADER_SIZE (sizeof (POOL_CHUNK_HEADER))
34 POOL_MEMORY_POOL *pool_memory = NULL;
36 static int get_free_index(unsigned int size);
38 static int get_free_index(unsigned int size)
44 size = (size - 1) >> ALIGN;
56 * Returns pointer to allocated memory of given size.
58 void *pool_memory_alloc(POOL_MEMORY_POOL *pool, unsigned int size)
63 if ((size + POOL_HEADER_SIZE) > pool->blocksize)
65 block = malloc(sizeof(POOL_BLOCK));
68 pool_error("pool_memory_alloc: malloc failed: %s", strerror(errno));
71 block->allocsize = block->size = size + POOL_HEADER_SIZE;
72 block->block = malloc(size + POOL_HEADER_SIZE);
73 if (block->block == NULL)
75 pool_error("pool_memory_alloc: malloc failed: %s", strerror(errno));
78 block->freepoint = block + (size + POOL_HEADER_SIZE);
80 chunk->header.size = size + POOL_HEADER_SIZE;
81 block->next = pool->largeblocks;
82 pool->largeblocks = block;
86 int fidx = get_free_index(size + POOL_HEADER_SIZE);
87 int allocsize = 1 << (fidx + ALIGN);
89 /* pick up from freelist */
90 if (pool->freelist[fidx] != NULL)
92 chunk = pool->freelist[fidx];
93 pool->freelist[fidx] = chunk->header.next;
94 chunk->header.size = allocsize;
100 block->freepoint + allocsize > block->block + block->size)
102 block = malloc(sizeof(POOL_BLOCK));
105 pool_error("pool_memory_alloc: malloc failed: %s", strerror(errno));
108 block->size = pool->blocksize;
109 block->allocsize = 0;
110 block->block = malloc(pool->blocksize);
111 if (block->block == NULL)
113 pool_error("pool_memory_alloc: malloc failed: %s", strerror(errno));
116 block->freepoint = block->block;
117 block->next = pool->blocks;
118 pool->blocks = block;
121 block = pool->blocks;
122 chunk = block->freepoint;
123 block->freepoint += allocsize;
124 block->allocsize += allocsize;
125 chunk->header.size = allocsize;
132 * pool_memory_alloc_zero:
133 * Returns pointer to allocated memory of given size.
134 * The allocated memory is cleared.
136 void *pool_memory_alloc_zero(POOL_MEMORY_POOL *pool, unsigned int size)
138 void *ptr = pool_memory_alloc(pool, size);
139 memset(ptr, 0, size);
145 * Frees allocated memory into memory pool.
147 void pool_memory_free(POOL_MEMORY_POOL *pool, void *ptr)
149 POOL_CHUNK *chunk = ptr - POOL_HEADER_SIZE;
155 if (chunk->header.size > pool->blocksize)
157 POOL_BLOCK *block, *ptr = NULL;
159 for (block = pool->largeblocks; block; ptr = block, block = block->next)
161 if (block->block == chunk)
167 pool_log("An adress \"%p\" does not exist in memory pool.", chunk);
173 pool->largeblocks = block->next;
177 ptr->next = block->next;
184 fidx = get_free_index(chunk->header.size);
185 chunk->header.next = pool->freelist[fidx];
186 pool->freelist[fidx] = chunk;
191 * pool_memory_realloc:
192 * Returns new pointer to allocated memory of given size.
193 * The new memory is copied from the old memory, and the old
196 void *pool_memory_realloc(POOL_MEMORY_POOL *pool, void *ptr, unsigned int size)
200 POOL_CHUNK *chunk = ptr - POOL_HEADER_SIZE;
202 if (size <= chunk->header.size - POOL_HEADER_SIZE)
205 fidx = get_free_index(size + POOL_HEADER_SIZE);
206 if (size + POOL_HEADER_SIZE <= pool->blocksize &&
207 chunk->header.size <= pool->blocksize &&
208 fidx == get_free_index(chunk->header.size))
213 p = pool_memory_alloc(pool, size);
214 memmove(p, ptr, chunk->header.size - POOL_HEADER_SIZE);
215 pool_memory_free(pool, ptr);
221 * pool_memory_create:
222 * Create a new memory pool.
224 POOL_MEMORY_POOL *pool_memory_create(int blocksize)
226 POOL_MEMORY_POOL *pool;
229 pool = malloc(sizeof(POOL_MEMORY_POOL));
232 pool_error("pool_memory_create: malloc failed: %s", strerror(errno));
236 pool->largeblocks = NULL;
237 pool->blocksize = blocksize;
239 for (i = 0; i < SLOT_NUM; i++)
241 pool->freelist[i] = NULL;
248 * pool_memory_delete:
249 * Frees all memory which is allocated in the memory pool.
251 void pool_memory_delete(POOL_MEMORY_POOL *pool_memory, int reuse)
253 POOL_BLOCK *block, *ptr;
255 /* Reuse the first memory block */
256 if (reuse && pool_memory->blocks)
257 block = pool_memory->blocks->next;
259 block = pool_memory->blocks;
269 for (block = pool_memory->largeblocks; block;)
281 if (pool_memory->blocks)
283 pool_memory->blocks->next = NULL;
284 pool_memory->blocks->allocsize = 0;
285 pool_memory->blocks->freepoint = pool_memory->blocks->block;
287 pool_memory->largeblocks = NULL;
288 for (i = 0; i < SLOT_NUM; i++)
290 pool_memory->freelist[i] = NULL;
301 * pool_memory_strdup:
302 * Creates the new string which is copied the given string.
304 char *pool_memory_strdup(POOL_MEMORY_POOL *pool_memory, const char *string)
306 int len = strlen(string);
307 char *str = pool_memory_alloc(pool_memory, len + 1);
309 memmove(str, string, len);