18 #include <my_global.h>
46 void init_alloc_root(
MEM_ROOT *mem_root,
size_t block_size,
47 size_t pre_alloc_size __attribute__((unused)))
49 DBUG_ENTER(
"init_alloc_root");
50 DBUG_PRINT(
"enter",(
"root: 0x%lx", (
long) mem_root));
52 mem_root->free= mem_root->used= mem_root->pre_alloc= 0;
53 mem_root->min_malloc= 32;
54 mem_root->block_size= block_size - ALLOC_ROOT_MIN_BLOCK_SIZE;
55 mem_root->error_handler= 0;
56 mem_root->block_num= 4;
57 mem_root->first_block_usage= 0;
59 #if !(defined(HAVE_purify) && defined(EXTRA_DEBUG))
62 if ((mem_root->free= mem_root->pre_alloc=
66 mem_root->free->size= pre_alloc_size+ALIGN_SIZE(
sizeof(
USED_MEM));
67 mem_root->free->left= pre_alloc_size;
68 mem_root->free->next= 0;
76 #define TRASH_MEM(X) TRASH(((char*)(X) + ((X)->size-(X)->left)), (X)->left)
96 void reset_root_defaults(
MEM_ROOT *mem_root,
size_t block_size,
97 size_t pre_alloc_size __attribute__((unused)))
99 DBUG_ASSERT(alloc_root_inited(mem_root));
101 mem_root->block_size= block_size - ALLOC_ROOT_MIN_BLOCK_SIZE;
102 #if !(defined(HAVE_purify) && defined(EXTRA_DEBUG))
105 size_t size= pre_alloc_size + ALIGN_SIZE(
sizeof(
USED_MEM));
106 if (!mem_root->pre_alloc || mem_root->pre_alloc->size != size)
108 USED_MEM *mem, **prev= &mem_root->free;
116 if (mem->size == size)
119 mem_root->pre_alloc= mem;
122 if (mem->left + ALIGN_SIZE(
sizeof(
USED_MEM)) == mem->size)
127 mem->left= mem->size;
136 if ((mem= (
USED_MEM *) my_malloc(size, MYF(0))))
139 mem->left= pre_alloc_size;
141 *prev= mem_root->pre_alloc= mem;
145 mem_root->pre_alloc= 0;
151 mem_root->pre_alloc= 0;
155 void *alloc_root(
MEM_ROOT *mem_root,
size_t length)
157 #if defined(HAVE_purify) && defined(EXTRA_DEBUG)
159 DBUG_ENTER(
"alloc_root");
160 DBUG_PRINT(
"enter",(
"root: 0x%lx", (
long) mem_root));
162 DBUG_ASSERT(alloc_root_inited(mem_root));
164 DBUG_EXECUTE_IF(
"simulate_out_of_memory",
166 if (mem_root->error_handler)
167 (*mem_root->error_handler)();
168 DBUG_SET(
"-d,simulate_out_of_memory");
169 DBUG_RETURN((
void*) 0);
172 length+=ALIGN_SIZE(
sizeof(
USED_MEM));
173 if (!(next = (
USED_MEM*) my_malloc(length,MYF(MY_WME | ME_FATALERROR))))
175 if (mem_root->error_handler)
176 (*mem_root->error_handler)();
177 DBUG_RETURN((uchar*) 0);
179 next->next= mem_root->used;
181 mem_root->used= next;
182 DBUG_PRINT(
"exit",(
"ptr: 0x%lx", (
long) (((
char*) next)+
184 DBUG_RETURN((uchar*) (((
char*) next)+ALIGN_SIZE(
sizeof(
USED_MEM))));
186 size_t get_size, block_size;
190 DBUG_ENTER(
"alloc_root");
191 DBUG_PRINT(
"enter",(
"root: 0x%lx", (
long) mem_root));
192 DBUG_ASSERT(alloc_root_inited(mem_root));
194 DBUG_EXECUTE_IF(
"simulate_out_of_memory",
197 if (mem_root->error_handler)
198 (*mem_root->error_handler)();
199 DBUG_SET(
"-d,simulate_out_of_memory");
200 DBUG_RETURN((
void*) 0);
202 length= ALIGN_SIZE(length);
203 if ((*(prev= &mem_root->free)) != NULL)
205 if ((*prev)->left < length &&
206 mem_root->first_block_usage++ >= ALLOC_MAX_BLOCK_USAGE_BEFORE_DROP &&
207 (*prev)->left < ALLOC_MAX_BLOCK_TO_DROP)
211 next->next= mem_root->used;
212 mem_root->used= next;
213 mem_root->first_block_usage= 0;
215 for (next= *prev ; next && next->left < length ; next= next->next)
220 block_size= mem_root->block_size * (mem_root->block_num >> 2);
221 get_size= length+ALIGN_SIZE(
sizeof(
USED_MEM));
222 get_size= MY_MAX(get_size, block_size);
224 if (!(next = (
USED_MEM*) my_malloc(get_size,MYF(MY_WME | ME_FATALERROR))))
226 if (mem_root->error_handler)
227 (*mem_root->error_handler)();
228 DBUG_RETURN((
void*) 0);
230 mem_root->block_num++;
232 next->size= get_size;
233 next->left= get_size-ALIGN_SIZE(
sizeof(
USED_MEM));
237 point= (uchar*) ((
char*) next+ (next->size-next->left));
239 if ((next->left-= length) < mem_root->min_malloc)
242 next->next= mem_root->used;
243 mem_root->used= next;
244 mem_root->first_block_usage= 0;
246 DBUG_PRINT(
"exit",(
"ptr: 0x%lx", (ulong) point));
247 DBUG_RETURN((
void*) point);
271 void *multi_alloc_root(
MEM_ROOT *root, ...)
274 char **ptr, *start, *res;
275 size_t tot_length, length;
276 DBUG_ENTER(
"multi_alloc_root");
278 va_start(args, root);
280 while ((ptr= va_arg(args,
char **)))
282 length= va_arg(args, uint);
283 tot_length+= ALIGN_SIZE(length);
287 if (!(start= (
char*) alloc_root(root, tot_length)))
290 va_start(args, root);
292 while ((ptr= va_arg(args,
char **)))
295 length= va_arg(args, uint);
296 res+= ALIGN_SIZE(length);
299 DBUG_RETURN((
void*) start);
304 static inline void mark_blocks_free(
MEM_ROOT* root)
311 for (next= root->free; next; next= *(last= &next->next))
313 next->left= next->size - ALIGN_SIZE(
sizeof(
USED_MEM));
318 *last= next=root->used;
321 for (; next; next= next->next)
323 next->left= next->size - ALIGN_SIZE(
sizeof(
USED_MEM));
329 root->first_block_usage= 0;
352 void free_root(
MEM_ROOT *root, myf MyFlags)
355 DBUG_ENTER(
"free_root");
356 DBUG_PRINT(
"enter",(
"root: 0x%lx flags: %u", (
long) root, (uint) MyFlags));
358 if (MyFlags & MY_MARK_BLOCKS_FREE)
360 mark_blocks_free(root);
363 if (!(MyFlags & MY_KEEP_PREALLOC))
366 for (next=root->used; next ;)
368 old=next; next= next->next ;
369 if (old != root->pre_alloc)
371 old->left= old->size;
376 for (next=root->free ; next ;)
378 old=next; next= next->next;
379 if (old != root->pre_alloc)
381 old->left= old->size;
386 root->used=root->free=0;
389 root->free=root->pre_alloc;
390 root->free->left=root->pre_alloc->size-ALIGN_SIZE(
sizeof(
USED_MEM));
391 TRASH_MEM(root->pre_alloc);
395 root->first_block_usage= 0;
403 void set_prealloc_root(
MEM_ROOT *root,
char *ptr)
406 for (next=root->used; next ; next=next->next)
408 if ((
char*) next <= ptr && (
char*) next + next->size > ptr)
410 root->pre_alloc=next;
414 for (next=root->free ; next ; next=next->next)
416 if ((
char*) next <= ptr && (
char*) next + next->size > ptr)
418 root->pre_alloc=next;
425 char *strdup_root(
MEM_ROOT *root,
const char *str)
427 return strmake_root(root, str, strlen(str));
431 char *strmake_root(
MEM_ROOT *root,
const char *str,
size_t len)
434 if ((pos=alloc_root(root,len+1)))
443 void *memdup_root(
MEM_ROOT *root,
const void *str,
size_t len)
446 if ((pos=alloc_root(root,len)))