16
16
/* Routines to handle mallocing of results which will be freed the same time */
20
#include "drizzled/internal/my_sys.h"
21
#include "drizzled/internal/m_string.h"
30
static const unsigned int MAX_BLOCK_TO_DROP= 4096;
31
static const unsigned int MAX_BLOCK_USAGE_BEFORE_DROP= 10;
18
#include <mystrings/m_string.h>
34
25
Initialize memory root
37
memory::init_alloc_root()
38
29
mem_root - memory root to initialize
39
30
block_size - size of chunks (blocks) used for memory allocation
40
31
(It is external size of chunk i.e. it should include
41
32
memory required for internal structures, thus it
42
should be no less than memory::ROOT_MIN_BLOCK_SIZE)
33
should be no less than ALLOC_ROOT_MIN_BLOCK_SIZE)
34
pre_alloc_size - if non-0, then size of block that should be
35
pre-allocated during memory root initialization.
45
38
This function prepares memory root for further use, sets initial size of
49
42
reported as error in first alloc_root() on this memory root.
52
void memory::init_alloc_root(memory::Root *mem_root, size_t block_size)
45
void init_alloc_root(MEM_ROOT *mem_root, size_t block_size,
46
size_t pre_alloc_size __attribute__((unused)))
54
48
mem_root->free= mem_root->used= mem_root->pre_alloc= 0;
55
49
mem_root->min_malloc= 32;
56
mem_root->block_size= block_size - memory::ROOT_MIN_BLOCK_SIZE;
50
mem_root->block_size= block_size - ALLOC_ROOT_MIN_BLOCK_SIZE;
57
51
mem_root->error_handler= 0;
58
52
mem_root->block_num= 4; /* We shift this with >>2 */
59
53
mem_root->first_block_usage= 0;
55
#if !(defined(HAVE_purify) && defined(EXTRA_DEBUG))
58
if ((mem_root->free= mem_root->pre_alloc=
59
(USED_MEM*) my_malloc(pre_alloc_size+ ALIGN_SIZE(sizeof(USED_MEM)),
62
mem_root->free->size= pre_alloc_size+ALIGN_SIZE(sizeof(USED_MEM));
63
mem_root->free->left= pre_alloc_size;
64
mem_root->free->next= 0;
82
void memory::reset_root_defaults(memory::Root *mem_root, size_t block_size,
83
size_t pre_alloc_size)
89
void reset_root_defaults(MEM_ROOT *mem_root, size_t block_size,
90
size_t pre_alloc_size __attribute__((unused)))
85
92
assert(alloc_root_inited(mem_root));
87
mem_root->block_size= block_size - memory::ROOT_MIN_BLOCK_SIZE;
94
mem_root->block_size= block_size - ALLOC_ROOT_MIN_BLOCK_SIZE;
95
#if !(defined(HAVE_purify) && defined(EXTRA_DEBUG))
88
96
if (pre_alloc_size)
90
size_t size= pre_alloc_size + ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
98
size_t size= pre_alloc_size + ALIGN_SIZE(sizeof(USED_MEM));
91
99
if (!mem_root->pre_alloc || mem_root->pre_alloc->size != size)
93
memory::internal::UsedMemory *mem, **prev= &mem_root->free;
101
USED_MEM *mem, **prev= &mem_root->free;
95
103
Free unused blocks, so that consequent calls
96
104
to reset_root_defaults won't eat away memory.
104
112
mem_root->pre_alloc= mem;
107
if (mem->left + ALIGN_SIZE(sizeof(memory::internal::UsedMemory)) == mem->size)
115
if (mem->left + ALIGN_SIZE(sizeof(USED_MEM)) == mem->size)
109
117
/* remove block from the list and free it */
110
118
*prev= mem->next;
114
122
prev= &mem->next;
116
124
/* Allocate new prealloc block and add it to the end of free list */
117
if ((mem= static_cast<memory::internal::UsedMemory *>(malloc(size))))
125
if ((mem= (USED_MEM *) my_malloc(size, MYF(0))))
120
128
mem->left= pre_alloc_size;
121
129
mem->next= *prev;
122
*prev= mem_root->pre_alloc= mem;
130
*prev= mem_root->pre_alloc= mem;
132
140
mem_root->pre_alloc= 0;
137
void *memory::alloc_root(memory::Root *mem_root, size_t length)
144
void *alloc_root(MEM_ROOT *mem_root, size_t length)
146
#if defined(HAVE_purify) && defined(EXTRA_DEBUG)
147
register USED_MEM *next;
149
assert(alloc_root_inited(mem_root));
151
length+=ALIGN_SIZE(sizeof(USED_MEM));
152
if (!(next = (USED_MEM*) my_malloc(length,MYF(MY_WME | ME_FATALERROR))))
154
if (mem_root->error_handler)
155
(*mem_root->error_handler)();
156
return((unsigned char*) 0); /* purecov: inspected */
158
next->next= mem_root->used;
160
mem_root->used= next;
161
return((unsigned char*) (((char*) next)+ALIGN_SIZE(sizeof(USED_MEM))));
139
163
size_t get_size, block_size;
140
164
unsigned char* point;
141
memory::internal::UsedMemory *next= NULL;
142
memory::internal::UsedMemory **prev;
165
register USED_MEM *next= 0;
166
register USED_MEM **prev;
143
167
assert(alloc_root_inited(mem_root));
145
169
length= ALIGN_SIZE(length);
146
170
if ((*(prev= &mem_root->free)) != NULL)
148
172
if ((*prev)->left < length &&
149
mem_root->first_block_usage++ >= MAX_BLOCK_USAGE_BEFORE_DROP &&
150
(*prev)->left < MAX_BLOCK_TO_DROP)
173
mem_root->first_block_usage++ >= ALLOC_MAX_BLOCK_USAGE_BEFORE_DROP &&
174
(*prev)->left < ALLOC_MAX_BLOCK_TO_DROP)
153
177
*prev= next->next; /* Remove block from list */
162
186
{ /* Time to alloc new block */
163
187
block_size= mem_root->block_size * (mem_root->block_num >> 2);
164
get_size= length+ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
165
get_size= max(get_size, block_size);
188
get_size= length+ALIGN_SIZE(sizeof(USED_MEM));
189
get_size= cmax(get_size, block_size);
167
if (!(next = static_cast<memory::internal::UsedMemory *>(malloc(get_size))))
191
if (!(next = (USED_MEM*) my_malloc(get_size,MYF(MY_WME | ME_FATALERROR))))
169
193
if (mem_root->error_handler)
170
194
(*mem_root->error_handler)();
195
return((void*) 0); /* purecov: inspected */
173
197
mem_root->block_num++;
174
198
next->next= *prev;
175
199
next->size= get_size;
176
next->left= get_size-ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
200
next->left= get_size-ALIGN_SIZE(sizeof(USED_MEM));
209
234
in case of success or NULL if out of memory.
212
void *memory::multi_alloc_root(memory::Root *root, ...)
237
void *multi_alloc_root(MEM_ROOT *root, ...)
215
240
char **ptr, *start, *res;
244
269
/* Mark all data in blocks free for reusage */
246
static inline void mark_blocks_free(memory::Root* root)
271
static inline void mark_blocks_free(MEM_ROOT* root)
248
memory::internal::UsedMemory *next;
249
memory::internal::UsedMemory **last;
273
register USED_MEM *next;
274
register USED_MEM **last;
251
276
/* iterate through (partially) free blocks, mark them free */
252
277
last= &root->free;
253
278
for (next= root->free; next; next= *(last= &next->next))
255
next->left= next->size - ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
280
next->left= next->size - ALIGN_SIZE(sizeof(USED_MEM));
262
287
/* now go through the used blocks and mark them free */
263
288
for (; next; next= next->next)
265
next->left= next->size - ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
290
next->left= next->size - ALIGN_SIZE(sizeof(USED_MEM));
282
307
MyFlags Flags for what should be freed:
284
MARK_BLOCKS_FREED Don't free blocks, just mark them free
285
KEEP_PREALLOC If this is not set, then free also the
309
MY_MARK_BLOCKS_FREED Don't free blocks, just mark them free
310
MY_KEEP_PREALLOC If this is not set, then free also the
286
311
preallocated block
291
316
It's also safe to call this multiple times with the same mem_root.
294
void memory::free_root(memory::Root *root, myf MyFlags)
319
void free_root(MEM_ROOT *root, myf MyFlags)
296
memory::internal::UsedMemory *next,*old;
321
register USED_MEM *next,*old;
298
if (MyFlags & memory::MARK_BLOCKS_FREE)
323
if (MyFlags & MY_MARK_BLOCKS_FREE)
300
325
mark_blocks_free(root);
303
if (!(MyFlags & memory::KEEP_PREALLOC))
328
if (!(MyFlags & MY_KEEP_PREALLOC))
304
329
root->pre_alloc=0;
306
331
for (next=root->used; next ;)
319
344
if (root->pre_alloc)
321
346
root->free=root->pre_alloc;
322
root->free->left=root->pre_alloc->size-ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
347
root->free->left=root->pre_alloc->size-ALIGN_SIZE(sizeof(USED_MEM));
323
348
TRASH_MEM(root->pre_alloc);
324
349
root->free->next=0;
332
357
Find block that contains an object and set the pre_alloc to it
335
void memory::set_prealloc_root(memory::Root *root, char *ptr)
360
void set_prealloc_root(MEM_ROOT *root, char *ptr)
337
memory::internal::UsedMemory *next;
338
363
for (next=root->used; next ; next=next->next)
340
365
if ((char*) next <= ptr && (char*) next + next->size > ptr)
357
char *memory::strdup_root(memory::Root *root, const char *str)
382
char *strdup_root(MEM_ROOT *root, const char *str)
359
384
return strmake_root(root, str, strlen(str));
363
char *memory::strmake_root(memory::Root *root, const char *str, size_t len)
388
char *strmake_root(MEM_ROOT *root, const char *str, size_t len)
366
if ((pos=(char *)memory::alloc_root(root,len+1)))
391
if ((pos=alloc_root(root,len+1)))
368
393
memcpy(pos,str,len);
375
void *memory::memdup_root(memory::Root *root, const void *str, size_t len)
400
void *memdup_root(MEM_ROOT *root, const void *str, size_t len)
378
if ((pos=memory::alloc_root(root,len)))
403
if ((pos=alloc_root(root,len)))
379
404
memcpy(pos,str,len);
383
} /* namespace drizzled */