~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/my_alloc.c

  • Committer: Brian Aker
  • Date: 2008-10-06 06:47:29 UTC
  • Revision ID: brian@tangent.org-20081006064729-2i9mhjkzyvow9xsm
RemoveĀ uint.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 
16
16
/* Routines to handle mallocing of results which will be freed the same time */
17
17
 
18
 
#include "config.h"
19
 
 
20
 
#include "drizzled/internal/my_sys.h"
21
 
#include "drizzled/internal/m_string.h"
22
 
 
23
 
#include <algorithm>
24
 
 
25
 
using namespace std;
26
 
 
27
 
namespace drizzled
28
 
{
29
 
 
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>
 
19
#include <my_sys.h>
 
20
#undef EXTRA_DEBUG
 
21
#define EXTRA_DEBUG
 
22
 
32
23
 
33
24
/*
34
25
  Initialize memory root
35
26
 
36
27
  SYNOPSIS
37
 
    memory::init_alloc_root()
 
28
    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.
43
36
 
44
37
  DESCRIPTION
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.
50
43
*/
51
44
 
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)))
53
47
{
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;
60
54
 
 
55
#if !(defined(HAVE_purify) && defined(EXTRA_DEBUG))
 
56
  if (pre_alloc_size)
 
57
  {
 
58
    if ((mem_root->free= mem_root->pre_alloc=
 
59
         (USED_MEM*) my_malloc(pre_alloc_size+ ALIGN_SIZE(sizeof(USED_MEM)),
 
60
                               MYF(0))))
 
61
    {
 
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;
 
65
    }
 
66
  }
 
67
#endif
61
68
  return;
62
69
}
63
70
 
79
86
    before allocation.
80
87
*/
81
88
 
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)))
84
91
{
85
92
  assert(alloc_root_inited(mem_root));
86
93
 
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)
89
97
  {
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)
92
100
    {
93
 
      memory::internal::UsedMemory *mem, **prev= &mem_root->free;
 
101
      USED_MEM *mem, **prev= &mem_root->free;
94
102
      /*
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;
105
113
          return;
106
114
        }
107
 
        if (mem->left + ALIGN_SIZE(sizeof(memory::internal::UsedMemory)) == mem->size)
 
115
        if (mem->left + ALIGN_SIZE(sizeof(USED_MEM)) == mem->size)
108
116
        {
109
117
          /* remove block from the list and free it */
110
118
          *prev= mem->next;
114
122
          prev= &mem->next;
115
123
      }
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))))
118
126
      {
119
 
        mem->size= size;
 
127
        mem->size= size; 
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; 
123
131
      }
124
132
      else
125
133
      {
128
136
    }
129
137
  }
130
138
  else
131
 
  {
 
139
#endif
132
140
    mem_root->pre_alloc= 0;
133
 
  }
134
141
}
135
142
 
136
143
 
137
 
void *memory::alloc_root(memory::Root *mem_root, size_t length)
 
144
void *alloc_root(MEM_ROOT *mem_root, size_t length)
138
145
{
 
146
#if defined(HAVE_purify) && defined(EXTRA_DEBUG)
 
147
  register USED_MEM *next;
 
148
 
 
149
  assert(alloc_root_inited(mem_root));
 
150
 
 
151
  length+=ALIGN_SIZE(sizeof(USED_MEM));
 
152
  if (!(next = (USED_MEM*) my_malloc(length,MYF(MY_WME | ME_FATALERROR))))
 
153
  {
 
154
    if (mem_root->error_handler)
 
155
      (*mem_root->error_handler)();
 
156
    return((unsigned char*) 0);                 /* purecov: inspected */
 
157
  }
 
158
  next->next= mem_root->used;
 
159
  next->size= length;
 
160
  mem_root->used= next;
 
161
  return((unsigned char*) (((char*) next)+ALIGN_SIZE(sizeof(USED_MEM))));
 
162
#else
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));
144
168
 
145
169
  length= ALIGN_SIZE(length);
146
170
  if ((*(prev= &mem_root->free)) != NULL)
147
171
  {
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)
151
175
    {
152
176
      next= *prev;
153
177
      *prev= next->next;                        /* Remove block from list */
161
185
  if (! next)
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);
166
190
 
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))))
168
192
    {
169
193
      if (mem_root->error_handler)
170
194
        (*mem_root->error_handler)();
171
 
      return NULL;
 
195
      return((void*) 0);                      /* purecov: inspected */
172
196
    }
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));
177
201
    *prev=next;
178
202
  }
179
203
 
187
211
    mem_root->first_block_usage= 0;
188
212
  }
189
213
  return((void*) point);
 
214
#endif
190
215
}
191
216
 
192
217
 
209
234
    in case of success or NULL if out of memory.
210
235
*/
211
236
 
212
 
void *memory::multi_alloc_root(memory::Root *root, ...)
 
237
void *multi_alloc_root(MEM_ROOT *root, ...)
213
238
{
214
239
  va_list args;
215
240
  char **ptr, *start, *res;
224
249
  }
225
250
  va_end(args);
226
251
 
227
 
  if (!(start= (char*) memory::alloc_root(root, tot_length)))
228
 
    return(0);
 
252
  if (!(start= (char*) alloc_root(root, tot_length)))
 
253
    return(0);                            /* purecov: inspected */
229
254
 
230
255
  va_start(args, root);
231
256
  res= start;
243
268
 
244
269
/* Mark all data in blocks free for reusage */
245
270
 
246
 
static inline void mark_blocks_free(memory::Root* root)
 
271
static inline void mark_blocks_free(MEM_ROOT* root)
247
272
{
248
 
  memory::internal::UsedMemory *next;
249
 
  memory::internal::UsedMemory **last;
 
273
  register USED_MEM *next;
 
274
  register USED_MEM **last;
250
275
 
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))
254
279
  {
255
 
    next->left= next->size - ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
 
280
    next->left= next->size - ALIGN_SIZE(sizeof(USED_MEM));
256
281
    TRASH_MEM(next);
257
282
  }
258
283
 
262
287
  /* now go through the used blocks and mark them free */
263
288
  for (; next; next= next->next)
264
289
  {
265
 
    next->left= next->size - ALIGN_SIZE(sizeof(memory::internal::UsedMemory));
 
290
    next->left= next->size - ALIGN_SIZE(sizeof(USED_MEM));
266
291
    TRASH_MEM(next);
267
292
  }
268
293
 
273
298
 
274
299
 
275
300
/*
276
 
  Deallocate everything used by memory::alloc_root or just move
 
301
  Deallocate everything used by alloc_root or just move
277
302
  used blocks to free list if called with MY_USED_TO_FREE
278
303
 
279
304
  SYNOPSIS
281
306
      root              Memory root
282
307
      MyFlags           Flags for what should be freed:
283
308
 
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
287
312
 
288
313
  NOTES
291
316
    It's also safe to call this multiple times with the same mem_root.
292
317
*/
293
318
 
294
 
void memory::free_root(memory::Root *root, myf MyFlags)
 
319
void free_root(MEM_ROOT *root, myf MyFlags)
295
320
{
296
 
  memory::internal::UsedMemory *next,*old;
 
321
  register USED_MEM *next,*old;
297
322
 
298
 
  if (MyFlags & memory::MARK_BLOCKS_FREE)
 
323
  if (MyFlags & MY_MARK_BLOCKS_FREE)
299
324
  {
300
325
    mark_blocks_free(root);
301
326
    return;
302
327
  }
303
 
  if (!(MyFlags & memory::KEEP_PREALLOC))
 
328
  if (!(MyFlags & MY_KEEP_PREALLOC))
304
329
    root->pre_alloc=0;
305
330
 
306
331
  for (next=root->used; next ;)
319
344
  if (root->pre_alloc)
320
345
  {
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;
325
350
  }
332
357
  Find block that contains an object and set the pre_alloc to it
333
358
*/
334
359
 
335
 
void memory::set_prealloc_root(memory::Root *root, char *ptr)
 
360
void set_prealloc_root(MEM_ROOT *root, char *ptr)
336
361
{
337
 
  memory::internal::UsedMemory *next;
 
362
  USED_MEM *next;
338
363
  for (next=root->used; next ; next=next->next)
339
364
  {
340
365
    if ((char*) next <= ptr && (char*) next + next->size > ptr)
354
379
}
355
380
 
356
381
 
357
 
char *memory::strdup_root(memory::Root *root, const char *str)
 
382
char *strdup_root(MEM_ROOT *root, const char *str)
358
383
{
359
384
  return strmake_root(root, str, strlen(str));
360
385
}
361
386
 
362
387
 
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)
364
389
{
365
390
  char *pos;
366
 
  if ((pos=(char *)memory::alloc_root(root,len+1)))
 
391
  if ((pos=alloc_root(root,len+1)))
367
392
  {
368
393
    memcpy(pos,str,len);
369
394
    pos[len]=0;
372
397
}
373
398
 
374
399
 
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)
376
401
{
377
 
  void *pos;
378
 
  if ((pos=memory::alloc_root(root,len)))
 
402
  char *pos;
 
403
  if ((pos=alloc_root(root,len)))
379
404
    memcpy(pos,str,len);
380
405
  return pos;
381
406
}
382
 
 
383
 
} /* namespace drizzled */